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 關注
- 676 瀏覽
添加回答
舉報