前言:遇到一个代码审计的题目,略有思考。记录一下~
源码就是这样的

1
2
3
4
5
<?php
show_source(__FILE__);
$content = '<?php exit; ?>';
$content .= $_POST['data'];
file_put_contents($_POST['filename'], $content);

.=就是拼接。前面的$content已经给了<?php exit; ?>,所以说不管后面是什么,都会先执行退出。导致后面的语句不执行。这也叫PHP死亡退出。
P神的讲解
m0re
实战中会比较多的在缓存和配置文件里。
绕过其实也很简单,POST方式提交了参数,这个是可控的,所以尝试PHP伪协议来进行写入一句话,并且使用base64-decode去除死亡退出。

  • 利用php://filter流的base64_decode函数特性去除死亡exit
  • base64编码中只包含64个可打印字符,在解码的时候,遇到这64个之外的字符,就会略过
  • <?php exit; ?>这条代码base64解码时,会解码为phpexit
  • base64解码是四个byte一组,所以再增加一个字符,凑够两组,后面的就会正常解码

在本地进行实验
m0re
payload

1
filename=php://filter/write=convert.base64-decode/resource=shell.php&data=aPD9waHAgcGhwaW5mbygpOyA/Pg

查看网站目录成功写入
m0re
内容是m0re
可以看到已经绕过了exit。直接执行我写入的PHP语句了。
m0re
自己的理解:原本不管写入什么都是拼接在<?php exit;?>后面的,像这样
m0re
执行一下是什么都没有。
m0re
因为先执行了exit退出了。
还有今天下午的慕测平台的软件测试大赛,比较菜就做出来两个,一个是git泄露,一个是文件上传。第一题跟这个类似。
源码是

1
2
3
4
5
<?php
show_source(__FILE__);
$filename = $_REQUEST['file'];
$data = '<?php exit();?> ' . $filename;
file_put_contents($filename,$data);

这个题,可能是运维师傅给的权限太高了,直接将写权限给出来了,就有人搅屎,把index.php给删了。然后网站就访问不了了。
解题过程中这个没想明白的是$_REQUEST虽然是集合get和post的请求方式,但是这个两个都是request,就有点难以理解。我进行复现时是这样的。
m0re
就会有报错,内容是,file_put_contents()需要两个参数,而此请求只提供了一个。
所以无法成功执行。
还有就是如果使用base64-decode

1
file=php://filter/write=convert.base64-decode/resource=shell.php&file=aPD9waHAgZmlsZV9nZXRfY29udGVudHMoImZsYWcucGhwIikgPz4=

是可以成功写入,但是写入的是这样的。而且文件名也是base64编码。无法利用。

m0re
目前思路卡在这里。不知道有没有wp,或者回头问问其他师傅们。
看到的师傅们如果了解还请指点一下,感谢!