php反序列化
反序列化
docker 靶场安装sudo docker pull mcc0624/ser:1.8
docker run -p 8002:80 -d mcc0624/ser:1.8
php面向对象
类的定义
php反序列化中的符号都有其特定的标识符
什么是反序列化(unserialize)
将字符串转换为状态信息
在定义变量前面的符号为序列符
每个序列符的作用不一样
序列化
public:属性被序列化的时候属性值会变成 属性名
protected:属性被序列化的时候属性值会变成 \x00*\x00属性名
private:属性被序列化的时候属性值会变成 \x00类名\x00属性名
反序列化
new函数可以用来将变量实例化
PHP内的几个特殊魔术方法
__construct() 类的构造函数,在类实例化对象时自动调用构造函数
__destruct() 类的析构函数,在对象销毁之前自动调用析构函数
__sleep() 在对象被序列化(使用 serialize() 函数)之前自动调用,可以在此方法中指定需要被序列化的属性,返回一个包含对象中所有应被序列化的变量名称的数组
__wakeup() 在对象被反序列化(使用 unserialize() 函数)之前自动调用,可以在此方法中重新初始化对象状态。
__set($property, $value) 当给一个对象的不存在或不可访问(private修饰)的属性赋值时自动调用,传递属性名和属性值作为参数。
__get($property) 当访问一个对象的不存在或不可访问的属性时自动调用,传递属性名作为参数。
__isset($property) 当对一个对象的不存在或不可访问的属性使用 isset() 或 empty() 函数时自动调用,传递属性名作为参数。
__unset($property) 当对一个对象的不存在或不可访问的属性使用 unset() 函数时自动调用,传递属性名作为参数。
__call($method, $arguments) 调用不存在或不可见的成员方法时,PHP会先调用__call()方法来存储方法名及其参数
__callStatic($method, $arguments) 当调用一个静态方法中不存在的方法时自动调用,传递方法名和参数数组作为参数。
__toString() 当使用echo或print输出对象将对象转化为字符串形式时,会调用__toString()方法
__invoke() 当将一个对象作为函数进行调用时自动调用。
__clone() 当使用 clone 关键字复制一个对象时自动调用。
__set_state($array) 在使用 var_export() 导出类时自动调用,用于返回一个包含类的静态成员的数组。
__debugInfo() 在使用 var_dump() 打印对象时自动调用,用于自定义对象的调试信息。
需要的flag编码
$c-> c=d; $c->是php中控制对象的表示符
eval($this->b); 的作用是将 $this->b 的值作为 PHP 代码运行。
__call() //在对象上下文中调用不可访问的方法时触发
魔术方法
想要触发魔术方法必须调用其所在的类
__construct() //创建类对象时调用
__destruct() //对象被销毁时触发
__call() //在对象中调用不可访问的方法时触发
__callStatic() //在静态方式中调用不可访问的方法时触发
__get() //调用类中不存在变量时触发(找有连续箭头的 this->a->b)
__set() //给一个未定义的属性赋值时触发
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__sleep() //使用serialize()时触发
__clone(),当对象复制完成时调用
__autoload(),尝试加载未定义的类
__debugInfo(),打印所需调试信息
该题目直接上传一句话木马__wakeup() //执行unserialize()时触发
__
__toString() //当对象被当做字符串时自动调用(找echo $this->a这种、strtolower()等)__invoke() //对象被当做函数进行调用时触发(找有括号的类似$a()这种)
__set_state() //使用var_export()时触发
__clone() //对象复制完成时调用
__autoload() //实例化一个未定义的类时触发
__debugInfo() //使用var_dump时触发
是private成员,序列化结果需要将indextest改成%00index%00test
?test=O:5:”index”:1:{s:11:”%00index%00test”;O:4:”evil”:1:{s:5:”test2”;s:13:”system(‘id’);”;}}
pop链的构造
上述例题中存在toString,construct,wakeup ,get,invoke五个魔法函数
反着推要让include函数读取flag需要激活invoke函数
invoke() 当将一个对象作为函数进行调用时自动调用。
又因为__construct() 类的构造函数,在类实例化对象时自动调用构造函数
所以先出发construct再触发invoke即可又因为tostring在反序列化时被激活所以pop链顺序应该为
show->test->modifier
入口点:
Show类的__wakeup()方法会在反序列化时自动调用,输出$this->source触发__toString: 如果
source是一个对象且被当作字符串使用,会调用该对象的__toString()方法触发__get: 在
Show::__toString()中,访问$this->str->source,如果source是Test类的一个不存在的属性,会触发Test::__get()触发__invoke:
Test::__get()将$this->p作为函数调用,如果$p是Modifier对象,会调用__invoke()最终执行:
Modifier::__invoke()调用append()方法包含指定文件
字符串逃逸
字符串减少
反序列化之所以存在字符串逃逸,最主要的原因是代码中存在针对序列化(serialize())后的字符串进行了过滤操作(变多或者变少)
判断功能性符号依靠前方字符长度来判断
字符串逃逸即将前方对后方代码的约束部分也变为字符串使其约束作用失效
将原有的成员属性并列到前面,然后添加一个成员属性已达到字符串逃逸的效果
字符串增多
利用增加的字符串使其可以终端反序列化并且使其执行
相应的代码
注意使用\“表示“本身避免报错
绕过weakup
增加成员属性即可绕过
利用gc回收机制绕过weakup
SESSION反序列化
php |
默认格式 | `key1 | s:4:”test”;key2 |
|---|---|---|---|
php_serialize |
完全使用 serialize | a:2:{s:4:"key1";s:4:"test";s:4:"key2";i:123;} |
直接使用 PHP serialize 的结果 |
php_binary |
二进制格式 | \x04key1s:4:"test";\x04key2i:123; |
键名前有长度字节,适合处理特殊字符的键名 |
phar反序列化
基本介绍
Phar反序列化不依赖unserialize()函数进行反序列化。而是构造phar文件,以序列化的形式存储用户自定义的meta-data这一特性,phar_parse_metadata在解析meta数据时,会调用php_var_unserialize进行反序列化操作。具体解析代码。该方法需要在文件系统函数(file_exits()、is_dir()等)参数可控的情况下,配合phar://伪协议直接进行反序列化。即本地构造phar文件把恶意代码本地序列化好,再通过文件上传功能点上传phar文件至目标网站,最后用phar协议配合文件系统函数反序列化phar文件,达到预期目的。
phar文件简介
phar文件是一种打包形式,把php代码和其他资源(图像、表等)捆绑到一个归档文件中来实现应用程序和库的开发,跟jar文件差不多。本质上是一个压缩文件,会议序列化的形式存储用户在自定义的meta-data内的内容
stub:phar文件的标志,必须以 xxx __HALT_COMPILER();?> 结尾,否则无法识别。xxx可以为自定义内容。
//简单地说就是告诉系统自己是一个什么样的文件,声明文件后缀
manifest:phar文件本质上是一种压缩文件,其中每个被压缩文件的权限、属性等信息都放在这部分。这部分还会以序列化的形式存储用户自定义的meta-data,这是漏洞利用最核心的地方。
//存放序列化的内容
content:被压缩文件的内容
signature (可空):签名,放在末尾。
生成phar文件的poc
1 |
|
漏洞实现前提
1 | 1.phar文件要能够上传到服务器端。 |
文件操作函数
php大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化
使用phar为协议读取
file=phar:///var/www/html/upload/321532365639f31b3b9f8ea8be0c6be2.png
注意在修改phar为off时;要删去并且要在phpstorm的解释器的ini文件修改
¥






