ciscn决赛-2022-backdoor
这里写这篇文章的目的是来加深对这道题的理解
题目源码
1 |
|
阅读代码,存在两个魔法函数:
__sleep()
,执行serialize()时,先会调用这个函数。这里可以实现任意文件包含。__wakeup()
,执行unserialize()时,先会调用这个函数。这里可以执行一次无参函数结构。
对于__sleep__
来说,如果我们能够包含临时文件或者session即可rce。
目前的思路就有了,我们能够通过回调函数调用session_start
,这里会触发序列化操作,如果我们能够控制session内容,那么就可以触发__sleep
函数进行文件包含达成rce。接下来的目标则是想办法控制session内容。
(这个session_start
是关键,在开启这个的时候会自动进行序列化,就是将session里的值进行序列化后存入存储介质中,然后因为访问了session中的数据,会自动将session中的值进行反序列化操作)
(是先进行—-反序列化—-在进行—-序列化—-操作)
对于__wakeup__
来说,我们可以执行一次php内部类,那么我们可以利用此来探测信息
构造反序列化payload查看phpinfo
1 |
|
发现imagick拓展,想起之前看过的文章exploiting-arbitrary-object-instantiations,文章讲述了针对以下结构的php代码的一种攻击方法
1 | new $_GET['a']($_GET['b']); |
再查看一下__wakeup
方法
1 | public function __wakeup() { |
一方面题目给了同类型代码,另一方面题目限制了通过内置类的利用,显然我们需要利用imagick
的特性进行攻击
imagick
类在初始化时可以执行Magick Scripting Language
。那么考虑用其特性,在临时文件中写入Magick Scripting Language
,然后在imagick
类初始化的时候执行临时文件并且写入session
文件。再触发__sleep
包含session
文件以RCE
。
首先利用网站提供的功能,删除/tmp
下的文件。
1 | http://127.0.0.1:9999/?cmd=rm |
接下来发包写入session
构造反序列化数据
1 |
|
最后在反序列化的时候是会执行这样 new imagick("vid:msl:/tmp/php*")
发包
1 | POST /?data=O%3A8%3A%22backdoor%22%3A4%3A%7Bs%3A4%3A%22path%22%3BN%3Bs%3A4%3A%22argv%22%3Bs%3A17%3A%22vid%3Amsl%3A%2Ftmp%2Fphp*%22%3Bs%3A5%3A%22class%22%3Bs%3A7%3A%22imagick%22%3Bs%3A12%3A%22do_exec_func%22%3Bb%3A0%3B%7D&cmd=unserialze HTTP/1.1 |
这里就是强制文件上传 xml
这些内容就会上传到/tmp/php*
临时文件下
接着因为new imagick("vid:msl:/tmp/php*")
初始会执行msl
语言,所以临时文件里的内容就会被执行
就是将序列化好的字符进行base64编码 然后传入/tmp/sess_snakin
下
随后使用执行一次任意无参函数的功能,触发session_start
函数,并设置cookie
为PHPSESSID=snakin
,即可文件包含session
,成功RCE
。flag
执行根目录的readflag
即可。
1 | GET /?data=O%3A8%3A%22backdoor%22%3A2%3A%7Bs%3A5%3A%22class%22%3Bs%3A13%3A%22session_start%22%3Bs%3A12%3A%22do_exec_func%22%3Bb%3A1%3B%7D&cmd=unserialze&1=system('/readflag'); HTTP/1.1 |
上面的传的序列化字符就是为了开启session_start()
的
然后就会进行反序列化将path给赋值,反序列化完后再进行序列化,将序列化后的执行存入存储介质中 因为session文件中含有php代码,包含的时候就会执行
上面就是imagick
配合session
进行rce的过程了