1、php面向对象基本概念
类的定义:
类是定义了一件事物的抽象特征,它将数据的形式以及这些数据上的操作封装住在一起。(对象是具有类类型的变量,是对类的实例)
构成:
成员变量(属性)+成员函数(方法)
成员变量的值对外不可见,需要通过成员函数访问。
2、类与对象
实例化和赋值:再给实例化进行赋值的时候要首先确保类里面定义过这个属性
类的修饰符介绍:
在类中直接声明的变量称为成员属性(也可以成为成员变量)。
可以在类中声明多个变量,即“对象”中可以有多个成员属性,每个变量都存储"对象’不同的属性信息。
常用访问权限修饰符:(对属性的定义)
public:公共的,在类的内部、子类中或者类的外部都可以使
用,不受限制;
protected:受保护的,在类的内部、子类中可以使用,但不能
在类的外部使用;
private:私有的,只能在类的内部使用,在类的外部或者子类中
都无法使用。
类与对象的关系:
类是对象的抽象,而对象是类的具体实例。
类是想法,把类实例化(new),调用具体值后就变成了对象。
类的成员方法:
在类中定义的函数被称为成员方法。函数实现的是某个独立的功能;
成员方法实现的是类中的一个行为,是类的一部分。
可以在类中声明多个成员方法,成员方法的声明和函数声明完全一样,只
不过在声明成员方法时可以在function关键字前加一些访问权限修饰符,
如public、protected、private(可以省略,默认为public)
3、序列化
对象的序列化:不能序列化‘类’,可以序列化‘对象’,只序列化成员变量不序列化成员函数
private私有属性序列化时在变量前加空格(就是url编码中的%00类名%00)
protected受保护属性序列化时在变量名前加%00*%00
4、反序列化特性
1、反序列化之后的内容为一个对象
2、反序列化生成的对象里的值,又反序列化里的值提供,与原有类预定定义的值无关。
3、反序列化不触发类的成员方法;需要调用方法后才能触发
5、反序列化漏洞
简单例题:
首先定义了一个test类,其中有成员变量a和成员方法(调用displayvar)并输出,通过get传入benben,并将其反序列化后复制再次调用displayvar。因此可以利用get传入的参数来完成所需要的指令。如果要执行system(‘ls’)指令,就需要将其写为序列化的形式通过get上传。
payload:
?benben=o:4:"test":1:{s:1:"a";s:13:"system('id');";}
6、魔术方法
定义:
一个预定好的,在特定情况下自动触发的行为方法
作用:
特定条件下自动调用相关方法,达到触发代码
实例:
_construct():构造函数,在实例化一个对象时,首先会去自动化执行的方法
触发时机:实例化对象
功能:提前清理不必要的内容
_destruct():析构函数,在对象的所有引用被删除或者当对象被显式销毁时执行的魔术方法。(实例化对象结束后会被销毁,也会触发析构函数)
_sleep():序列化serialize()函数会检查类中是否存在一个魔术方法_sleep()如果存在,该方法会先被调用,然后才执行序列化操作。
触发时机:序列化serialize()之前
将benben的值传给cmd,然后对user进行实例化,此时触发_construct(),对user进行序列化触发_sleep(),因此想要通过命令执行获得信息就可以在benben中传入任意命令进行执行。
_wakeup():unserialize()会检查是否存在一个_wakeup()方法,如果存在,则会先调用_wakeup()方法,预先准备对象需要的资源。
触发时机:unserialize()反序列化之前
_wakeup():在反序列化unserialize()之前
_destruct():在反序列化unserialize()之后
_toString():表达方式错误导致魔术方法触发
触发时机:把对象当成字符串调用
_invoke():格式表达错误导致魔术方法触发
触发时机:把对象当成函数调用