Code Breaking部分题解
感谢p神的圈子,学到了老多姿势
easy - pcrewaf
1 |
|
才上线时,正则写的是
1 | '/<\?.*[(`].*/is' |
可以用include "php://filter/read=convert.base64-decode/resource=./1.php";
进行代码执行
修改过后,就一脸懵了,硬是没绕过。直到看了师傅们的文章。。。
正确姿势是通过插入极长的冗余代码,使正则匹配不断回溯匹配,超过设置的pcre.backtrack_limit
次数限制后,preg_match
将直接返回false(不是0),导致绕过
生成这样文件的代码如下:
1 |
|
关于PCRE特性的介绍参看p神的文章
easy - phplimit
1 |
|
见过类似这样的题,通过getallheaders()获取消息头中的数据,达到代码执行的效果。但是这个函数数是服务于apache的,而这里通过phpinfo可知是nginx。做完后听说有个get_defined_vars()可解决,也就是说正确姿势是:code=eval(next(current(get_defined_vars())));&a=var_dump(scandir(%27..%27));
而自己在翻文档时,没有找到这个函数,导致走了一条远路~
一开始我尝试拼接出flag文件的完整路径,再readfile
,结果发现由于正则限制,函数中参数只能有一个,基本不可能,于是放弃
然后有了切换当前目录的思路,而chdir(dirname(getcwd()))
返回值为true,解决这个true成了困扰我的又一问题。结果,偶然尝试出dirname(true)
返回.
,NICE~
刚好scandir('/var/www')
数组只有四个元素array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(14) "flag_phpbyp4ss" [3]=> string(4) "html" }
,通过反序array_reverse
和next
可以取得flag文件名
综上,最终的payload:code=readfile(next(array_reverse(scandir(dirname(chdir(dirname(getcwd())))))));
补充
王一航大佬指点,可通过eval(session_id(session_start()))
作为荷载,而session_id是需要符合一定条件的(有趣的是当session_id中含有某些特殊字符时,环境只是发出警告),引号无法使用。所以需要base64或者hex等编码处理,再传入eval
达到代码执行。
最终数据包关键信息类似如下:
1 | GET /?code=eval(base64_decode(session_id(session_start()))); HTTP/1.1 |
easy - function
1 |
|
不会做(哭,看到师傅们fuzz出在函数名前加\
,函数可正常执行。按p神说的,php默认命名空间\
,所有原生函数和原生类都在这个命名空间中
在函数的选择上,使用的是create_function
,该函数可创建一个匿名函数,第二个参数为匿名函数的代码内容。如何执行代码呢,参看师傅们的payloadaction=%5Ccreate_function&arg=return%201;}readfile(%27../flag_h0w2execute_arb1trary_c0de%27);//
easy - phpmagic
1 |
|
看师傅们的文章做出来的,没想到手笨还是弄了很久
由于对文件内容有htmlspecialchars
处理,PHP标签会失效。刚好这里的$log_name
是由$_SERVER['REMOTE_ADDR']
和$_GET['log']
拼接成的,均可控,使用php://filter
伪协议可对写入内容进行处理,例如base64编码。而在后缀问题上可采用/.做为后缀,而不会影响写入
想重复使用同一文件名操作的话,这里有个覆盖文件内容的小技巧,就是使用类似aaa/../1.php/.
的路径
最后的数据包关键信息类似如下:
1 | POST / HTTP/1.1 |