LCTF-babyphp’s revenge
题目直接给出代码
index.php
1 | <?php |
flag.php
1 | session_start(); |
此题利用了session反序列化和SSRF
本地测试
拿着代码在本地测试一下
文件解释
win下的目录是\tmp\tmp
,文件名为sess_37re68hmo2t39dem52s87vkbk5
,而37re68hmo2t39dem52s87vkbk5
是生成的session,文件的内容为name|s:6:"hu3sky";
name是键值s:6:"hu3sky";
是serialize("hu3sky")
的结果。这里用到的存储引擎是php
,也即是默认的存储引擎
回到题目
session反序列化存储机制
php是利用配置项session.save_handler来进行确定的,默认是以文件的方式存储
之前本地测试的就是默认的存储机制,这里介绍一下其他两个引擎
在php_serialize
引擎下
1 | <?php |
此时生成的文件内容会是a:1:{s:4:"name";s:6:"hu3sky";}
a:1
是使用php_serialize进行序列话都会加上
在php_binary
引擎下
1 | <?php |
此时生成的内容
由于该模式是 键的长度的ASCII+键名+反序列化内容
而name长度是4,4对应的ASCII是EOT,所以这就是文件的内容
如何造成危害
造成危害主要是由于反序列化存储的$_SESSION
数据时使用的引擎和序列化使用的引擎不一样
例如$_SESSION['name'] = '|O:11:"PeopleClass":0:{}';
在php_serialize
进行存储的时候,存储为a:1:{s:4:"name";s:24:"|O:11:"PeopleClass":0:{}";}
在php引擎进行序列化的时候,php引擎会以|
作为作为key
和value
的分隔符
于是a:1:{s:4:"name";s:24:"|
就成了key,O:11:"PeopleClass":0:{}";}
就成了value,再进行序列化的时候,就会将value部分进行序列化,最后就会得到PeopleClas这个类。
题目需要解决问题
本题用到的存储引擎为默认的php
引擎,于是我们要造成漏洞,就需要将存储的引擎变为php_serialize
,而序列化的引擎还是php
,但是代码里并没有序列化的地方,所以我们需要构造
在call_user_func($_GET[f],$_POST);
想办法进行对b的变量覆盖,将b覆盖为unserialize
,以便于最后call_user_func($b,$a);
进行反序列化,但是反序列化还需要找到一个可以被我们利用的类,同时这里的$a
是一个数组,不方便操作,于是这就是我们要解决的两个问题
变量覆盖通过extract
函数进行解决
SOAP
该类是用来创建SOAP数据报文的,和WSDL接口进行交互
SOAP是连接在web服务和web客户端之间的接口。它采用http作为底层通讯协议,xml作为数据传送的格式,且为php内置类
重点放在__call
和__construct
先看到__construct
,也就是
传入两个参数,第一个$wsdl
参数,如果为NULL,就是非wsdl
模式,如果是非wsdl
模式,就会对第二个参数里的url进行远程请求
第二个参数数组$options
,是soap请求的一些参数和属性
本地测试
SOAP扩展
首先需要在ini里打开
测试代码
1 | <?php |
该类还会造成CRLF
于是,利用该类进行反序列化,就能对内网进行请求,够造成SSRF
利用过程
大致思路
总结一下这道题的大致思路
首先第一次利用变量覆盖,将serialize_handler
设置为php_serialize
,这样就能修改存储的引擎,此时传入我们构造的序列化的内容,保存成文件,把flag
的内容带入session
文件中
第二次利用变量覆盖,将b设置为call_user_func
,php自动进行默认的反序列化,这时,就会去调用soapclient类中不存在的方法welcome_to_the_lctf2018
,就会去调用Soapclient的__call
,从而触发ssrf
实现过程
本地构造代码
1 | <?php |
session9uh1i2rhbr172uemrkd27kn6p4
,这里需要带上session,才会把$_SESSION['flag']
保存进session文件里
生成反序列化的内容
1 |
|
记得要在前面加上|
接着
然后带着写入文件的session,就能var_dump
出