唯品会 一家专门做特卖的网站手机版,外贸网站建设推广,高端网站建设四川,什么是新闻源网站一、定义
序列化#xff08;串行化#xff09;#xff1a;将变量转换为可保存或传输的字符串的过程#xff08;通常是字节流、JSON、XML格式#xff09; 反序列比#xff08;反串行化#xff09;#xff1a;把这个字符串再转化成原始数据结构或对象#xff08;原来的…一、定义
序列化串行化将变量转换为可保存或传输的字符串的过程通常是字节流、JSON、XML格式 反序列比反串行化把这个字符串再转化成原始数据结构或对象原来的变量使用
二、常见的php序列化格式
JSON:轻量级数据交换格式易于阅读编写和机器的解析与生成
HML:标记语言用于储存和传输数据
pickle:python模块可将python对象序列化为二进制格式
Protocol Buffers(protobuf):可以高效地储存和交换数据结构的二进制序列化格式
三、基础知识
php面对对象编程
对象可以对其做事情的一些东西。一个对象有状态、行为和标识三种属性。类一个共享相同结构和行为的对象的集合。每个类的定义都以关键字class开头后面跟着类的名字。一个类可以包含有属于自己的变量变量称为“属性”以及函数“称为方法”。类可能会包含一些特殊的函数叫magic函数magic函数命名是以符号“_”开头的比如_sleep,_wakeup等。这些函数在某些情况下会自动调用比如_construct当一个对象创建时调用constructor_destruct当一个对象被销毁时调用destructor_toString当一个对象被当作一个字符串时使用。
反序列化后对象里面的值与类里面预定义的值无关
private私有化属性出现特殊字符要用%00来代替空最后再用urldecode()进行解码后进行反序列化
displayvar(),展示属性必须要有预定义的类才能使用
漏洞成因是因为unserialize()需要传参而传入的参数可控就可以产生漏洞
常见的php序列化和反序列化方式主要有serializeunserialize 1.serilaize()
用于序列化对象或数组并返回一个字符串序列化对象后可以很方便的将它传递给其他需要它的地方且其类型和结构不会改变
语法string serialize ( mixed $value ) //$value是要序列化的对象或数组
eg.
?php
$sites array(Google, Runoob, Facebook);
$serialized_data serialize($sites);
echo $serialized_data . PHP_EOL;
?
输出为
a:3:{i:0;s:6:Google;i:1;s:6:Runoob;i:2;s:8:Facebook;}
2.unserialize()
用于将通过serialize()函数序列化后的对象或数组进行反序列化并返回原始的对象结构
语法mixed unserialize ( string $str ) //$str是反序列化后的字符串
返回的是转换后的值integer、float、string、array 或 object如果传递的字符串不可解序列化则返回 FALSE并产生一个 E_NOTICE
eg.
?php
$str a:3:{i:0;s:6:Google;i:1;s:6:Runoob;i:2;s:8:Facebook;};
$unserialized_data unserialize($str);
print_r($unserialized_data);
?
输出为
a:3:{i:0;s:6:Google;i:1;s:6:Runoob;i:2;s:8:Facebook;}
Array
([0] Google[1] Runoob[2] Facebook
)
四、常见魔术方法
定义在php类保留方法中以 “__”两个下划线开头的函数称为魔术方法是一个预定义好的在特定情况下自动触发的行为方法这些函数可以在代码中任何地方不用声明就可以使用
__construct()类的构造函数触发时机是实例化对象用于提前清理不必要内容__destruct()类的析构函数对象的所有引用被删除或者对象被显示销毁时执行的魔术方法__call()在对象中调用一个不可访问方法时调用__callStatic()用静态方式中调用一个不可访问方法时调用__get()获得一个类的成员变量时调用__set()设置一个类的成员变量时调用__isset()当对不可访问属性调用isset()或empty()时调用__unset()当对不可访问属性调用unset()时被调用__sleep()执行serialize()时先会调用这个函数__wakeup()执行unserialize()时先会调用这个函数__toString()类被当成字符串时的回应方法__invoke()调用函数的方式调用一个对象时的回应方法__set_state()调用var_export()导出类时此静态方法会被调用__clone()当对象复制完成时调用__autoload()尝试加载未定义的类__debugInfo()打印所需调试信息
五、绕过
1.常用手段
1常见起点
__wakeup 一定会调用 //使用unserialize时触发
__destruct 一定会调用 //对象被销毁时触发
__toString 当一个对象被反序列化后又被当做字符串使用
2常见中间跳板
__toString 当一个对象被当做字符串使用
__get 读取不可访问或不存在属性时被调用
__set 当给不可访问或不存在属性赋值时被调用
__isset 对不可访问或不存在的属性调用isset()或empty()时被调用
形如 $this- $func();
3常见终点
__call 调用不可访问或不存在的方法时被调用
call_user_func 一般php代码执行都会选择这里
call_user_func_array 一般php代码执行都会选择这里
2.protected和private绕过
变量前是protected是\x00*\x00类名的形式
变量前是private是\x00类名\x00的形式
方法将protected改为public手动将序列化后的形式改为protected或者private的标准形式结合urlencode和base64编码进行操作
3.__wakeup绕过
当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup 的执行
比如将O:4:Dino:1:{s:1:a;s:4:misc;}改为O:4:Dino:2:{s:1:a;s:4:misc;} 4.利用16进制绕过字符过滤
序列化结果O:4:Dino:1:{s:3:way;s:3:web;}中含有字符web但将s改成S后O:4:Dino:1:{S:3:\\77ay;s:3:web;}利用十六进制绕过了字符的过滤检测
练习
[SWPUCTF 2021 新生赛]ez_unserialize 打开后找不到题目查看源代码得到提示是robots协议的语句
http://t.csdnimg.cn/tgwG8 可以看到出现新地址 访问后得到一串php代码关闭了报错显示cl45s.php中的内容判断admin和passwd的值是否正确如果admin“admin,passwdctf,就会输出flag.php通过GET传参上传参数p传递给unserialize()函数进行反序列化 构造url后得到flag
[SWPUCTF 2021 新生赛]no_wakeup 打开看到php源码关闭报错显示class.php中的内容有个__wakeup()需要绕过判断admin和passwd的值是否正确如果admin“admin,passwdwllm,就会输出flag.php用GET传参传入p并且执行反序列化 构造url绕过__wakeup即可得到flag
[ZJCTF 2019]NiZhuanSiWei 打开发现一串php源码查找发现需要使用php伪协议运用data协议并且需要base64绕过传入welcome to the zjctf 用bp进行编码 传入url还需要绕过一个正则匹配 构造url可以得到一串base64编码 得出新的代码 原本的代码中还对password进行了反序列化就将fileflag.php进行序列化作为password的参数 构造url得到这个界面 查看源码即可得到flag