PHP反序列化
序列化反序列化图解
PHP反序列化
原理:未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行,SQL 注入,目录遍历等不可控后果。在反序列化的过程中自动触发了某些魔术方法。当进行反序列化的时候就有可能会触发对象中的一些魔术方法。
serialize() //将一个对象转换成一个字符串 unserialize() //将字符串还原成一个对象
触发:unserialize 函数的变量可控,文件中存在可利用的类,类中有魔术方法:
参考:https://www.cnblogs.com/20175211lyz/p/11403397.html
__construct() //创建对象时触发 __destruct() //对象被销毁时触发 __call() //在对象上下文中调用不可访问的方法时触发 __callStatic() //在静态上下文中调用不可访问的方法时触发 __get() //用于从不可访问的属性读取数据 __set() //用于将数据写入不可访问的属性 __isset() //在不可访问的属性上调用 isset()或 empty()触发 __unset() //在不可访问的属性上使用 unset()时触发 __invoke() //当脚本尝试将对象调用为函数时触发
无类
<?PHP
$KEY = 'hyj';
echo serialize($KEY);
?>
运行结果:s:3:“hyj”;
整形没有长度
<?PHP
$KEY = 123;
echo serialize($KEY);
?>
如$KEY = 123; 运行结果:i:123; 加函数
<?PHP
class A {
public $numo=1;
public $numt='2';
public $nums='abc';
public $numf="phpinfo.php";
}
$KEY = new A();
echo serialize($KEY);
?>
结果O:1:"A":4:{s:4:"numo";i:1;s:4:"numt";s:1:"2";s:4:"nums";s:3:"abc";s:4:"numf";s:11:"phpinfo.php";}
’
反过来测试,先包含phpinfo.php 通过GET方法获取到s:3:“hyj”;让页面转到phpinfo.php页面,代码如下 这么测试的原因是,echo unserialize($KEY) ;这句话是无法直接进行输出的(可以用var_dump()全部输出和print()输出)
<?PHP
include "phpinfo.php";
$H = "hyj";
$KEY = $_GET['x'];
if (unserialize($KEY) === "$H")
{
echo "phpinfo.php";
}
?>
<?PHP $H = "hyj"; $KEY = serialize($H); var_dump(unserialize($KEY)); print(unserialize($KEY)); ?>
有类
<?php
class ABC{
public $test;
function __construct(){
$test = 1;
echo '调用了构造函数<br>';
}
function __destruct(){
echo '调用了析构函数(销毁函数)<br>';
}
function __wakeup(){
echo '调用了苏醒函数(反序列化)<br>';
}
}
echo '创建对象a<br>';
$a = new ABC;
echo '序列化<br>';
$a_ser=serialize($a);
echo '反序列化<br>';
$a_unser=unserialize($a_ser);
echo '对象快要死了!';
?>
一般反序列化也可以SQL注入,命令执行,只是傻子才会那样子写
function __construct(){
$A = $_GET['x']
$test = "select * from user where id=".$A;
}
加一个 PHP的 == 和 === 是不一样的 双等号是值一样,类型可以不同 三等号是类型也需要相同 如
<?php
$A = 1;
$B = '1';
if($A==$B) {
echo "双";
}
if($A===$B) {
echo "三";
}
$C = ' 1';
if($A==$C) {
echo "4";
}
if($A===$C) {
echo "5";
}
if($B==$C) {
echo "6";
}
if($B===$C) {
echo "7";
}
?>
输出结果是双,没有三
|