关于php面向对象编程
对象:可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性。
类:一个共享相同结构和行为的对象的集合。
每个类的定义都以关键字class开头,后面跟着类的名字。一个类可以包含有属于自己的变量,变量(称为“属性”)以及函数(“称为方法”)。类定义了一件事物的抽象特点。通常来说,类定义了事物的属性和它可以做到的。类可能会包含一些特殊的函数叫magic函数,magic函数命名是以符号“_”开头的,比如_construct,_destruct,_toString,_sleep,_wakeup等。这些函数在某些情况下会自动调用,比如:_construct当一个对象创建时调用(constructor);_destruct当一个对象被销毁时调用(destructor);_toString当一个对象被当作一个字符串时使用。
反序列化漏洞
简介
PHP反序列化漏洞也叫PHP对象注入,是一个非常常见的漏洞,这种类型的漏洞虽然有些难以利用,但一旦利用成功就会造成非常危险的后果。漏洞的形成的根本原因是程序没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造成代码执行、getshell等一系列不可控的后果。反序列化漏洞并不是PHP特有,也存在于Java、Python等语言之中,但其原理基本相通。
一般程序在创建的时候,都会重写析构函数和构造函数,反序列化就是利用这些重写的函数。
原理
未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行,SQL注入,目录遍历等不可控后果。
在反序列化的过程中自动触发了某些魔术方法。
触发条件
unserialize函数的变量可控,php文件中存在可利用的类,类中有魔法函数
序列化与反序列化
序列化serialize()
序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象:
class S{
public $test="pikachu";
}
$s=new S(); //创建一个对象
serialize($s); //把这个对象进行序列化
序列化后得到的结果是这个样子的:O:1:"S":1:{
s:4:"test";s:7:"pikachu";}
O:代表object
1:代表对象名字长度为一个字符
S:对象的名称
1:代表对象里面有一个变量
s:数据类型
4:变量名称的长度
test:变量名称
s:数据类型
7:变量值的长度
pikachu:变量值
反序列化unserialize()
就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用。
$u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");
echo $u->test; //得到的结果为pikachu
PHP中的魔法函数
序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题
常见的几个魔法函数:
__construct()当一个对象创建时被调用
__destruct()当一个对象销毁时被调用
__toString()当一个对象被当作一个字符串使用
__sleep() 在对象在被序列化之前运行
__wakeup将在序列化之后立即被调用
漏洞举例:
class S{
var $test = "pikachu";
function __destruct(){
echo $this->test;
}
}
$s = $_GET['test'];
@$unser = unserialize($a);
payload:O:1:"S":1:{
s:4:"test";s:29:"<script>alert('xss')</script>";}
这些就是我们要关注的几个魔术方法了,如果服务器能够接收我们反序列化过的字符串、并且未经过滤的把其中的变量直接放进这些魔术方法里面的话,就容易造成很严重的漏洞了。
防范措施
1.严格控制unserialize函数的参数,坚持用户所输入的信息都是不可靠的原则
2.对于unserialize后的变量内容进行检查,以确定内容没有被污染
pikachu练习
叫我们输入一个接受序列化数据的api
我们试试概述的一个:
O:1:“S”:1:{s:4:“test”;s:7:“pikachu”;}
我们也可以构造一个payload:
O:1:"S":1:{
s:4:"test";s:29:"<script>alert('xss')</script>";}