2 回答
TA贡献1884条经验 获得超4个赞
删除构造函数中的双引号,function __construct() 而不是
function __construct() {
$this->hook = "exit(print_flag());";
}
用
function __construct() {
$this->hook = exit(print_flag());
}
TA贡献1911条经验 获得超7个赞
发生错误的原因是unserialize($flag);。由于参数 tounserialize()应该是一个字符串,它尝试将Example2对象转换为字符串。您可能打算使用unserialize($serialized);.
但更一般地,您应该确保该__toString()方法返回一个字符串。如果你不在乎它是什么,你可以返回一个空字符串。
function __toString()
{
if (isset($this->hook)) eval($this->hook);
return "";
}
当您exit()在钩子中时不会发生错误,因为脚本在__toString()方法返回之前退出,因此它从不检查返回值。
之后没有执行任何操作exit()。下面是操作顺序:
new Example2
- 创建新对象serialize($flag)
- 创建一个表示对象的字符串print "$serialized\r\n";
- 打印上面的字符串
以上步骤都不需要调用__toString()
,所以钩子还没有执行。
deserialize($flag)
- 这需要转换$flag
为字符串,以便可以将其解析为序列化数据。称呼
$flag->__toString()
eval($this->hook)
调用
print_flag()
,打印标志调用
exit()
,终止脚本
所以你看到序列化的对象被打印出来,然后标志被打印出来,然后没有别的,因为exit()
.
为了演示该漏洞,您应该unserialize()
使用正确的参数调用。
$deserialized = unserialize($seralized); echo $deserialized;
该echo
语句将导致__toString()
调用该方法。这将退出脚本,您将不会收到错误消息。
- 2 回答
- 0 关注
- 645 浏览
添加回答
举报