一个session序列化问题

补去年写的session序列化问题,这题虽然不难但是对于我自己来说很有启发性

知识储备

(1)session.upload_progress 是PHP5.4的新特性

1565920914177

(2)session.serialize_handler (php | php_serialize | php_binary) #定义用来序列化/反序列化的处理器名字。php 5.5.4以前默认选择的是php,5.5.4之后就是php_serialize

1
2
3
php #储存为 键名 + | + 经过了serialize()处理过的值
php_serialize #储存为经过了serialize()函数处理过的值(将键名和值当作一个数组序列化)
php_binary #键名的长度对应的ascii字符 + 键名 + 经过serialize()函数序列化后的值

漏洞成因

漏洞产生的主要主要原因就是,当你去执行 “ini_set(‘session.serialize_handler’,x);”的时候,当x和默认的处理器不一样的话,就会出现问题。简单来说漏洞的成因就是储存序列化的处理器和反序列化的处理器不相同

题目

链接:http://web.jarvisoj.com:32784/

描述:无

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
public $mdzz;
function __construct()
{
$this->mdzz = 'phpinfo();';
}

function __destruct()
{
eval($this->mdzz);
}
}
if(isset($_GET['phpinfo']))
{
$m = new OowoO();
}
else
{
highlight_string(file_get_contents('index.php'));
}
?>

分析:

(1)第一眼看见应该是序列化的问题

(2)要把$mdzz的参数变为找到flag的php代码

(3)get发送可得到phpinfo

(4)第一行 ini_set(‘session.serialize_handler’, ‘php’);

(5)打开phpinfo发现了

1565922772405

默认处理器和设置的处理器不同

(6)session.upload_progress.enabled = On

在根据上面的知识储备中,根据第二条,我们需要在session中添加一条“很像”有php处理器序列化储存的记录,可以通过第一条提到的特性来实现。

payload:

1
2
3
4
5
<form action="http://web.jarvisoj.com:32784/index.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="session.upload_progress.name" value="123" />
<input type="file" name="file" />
<input type="submit" />
</form>

根据要求,需要在上传的同时,post一个和session.upload_progress.name的同名变量就即可以实现session的注入,查phpinfo可得session.upload_progress.name=session.upload_progress.name。

1565926350825

这里的”|O…….”中的 “|”就是为了当被php处理器反序列时执行其中的代码

得到flag

后记

希望有时间还是多去看看php的手册,里面有很多好东西,另外推一手这个浙大的OJ,真心很不错,题目的难度和风格都很不错:https://www.jarvisoj.com/challenges

序列化真的是一个大东西,慢慢找漏洞来做复现才行,CTF的题目的环境略理想。(java还一点都没动呢,请加油)