PHP在utf8 MySQL表中序列化对象注入

时间:2017-04-24 21:41:36

标签: php mysql object serialization code-injection

在任何事情之前,我想表明我会从不做这样的事情。我正在对一个项目进行一次小型审计,我发现他们正在序列化整个$ _POST数组并将它们保存为文章注释,我已在下面的代码中复制了该场景:

    <?php
        /*
                CREATE TABLE `comments` (
                        `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
                        `data` mediumtext NOT NULL,
                        PRIMARY KEY (`id`)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
        */

        ini_set('display_errors','On');
        error_reporting(E_ALL);

        $comments = Array();

        try{

                $options = [
                                PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
                                PDO::MYSQL_ATTR_INIT_COMMAND => 'SET CHARACTER SET utf8'

                ];

                $dsn = 'mysql:host=localhost;dbname=test';
                $pdo = new \PDO($dsn,'user','password',$options);
                $pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

                if($_POST){

                        $comment = serialize($_POST);
                        $sql = "INSERT INTO comments SET data = :data";
                        $stmt = $pdo->prepare($sql);
                        $stmt->bindValue(':data',serialize($_POST));
                        $stmt->execute();

                }

                $stmt = $pdo->prepare('SELECT data FROM comments');
                $stmt->execute();
                $comments = $stmt->fetchAll(PDO::FETCH_ASSOC);

        }catch(\Exception $e){

                echo $e->getMessage();

        }
?>
<html>
        <head>
                <title>My nice little comment form</title>
        </head>
        <body>
                <form method="POST" action="" enctype="text/plain">
                        <label for="name">Name</label>
                        <input type="text" name="name" />
                        <br />
                        <label for="comment">Comment</label>
                        <textarea name="comment"></textarea>
                        <br />
                        <input type="submit" value="Send" />
                </form>
                <?php foreach($comments as $comment):?>
                        <?php $data = unserialize($comment['data']);?>
                        <p>Name: <?php echo $data['name']; ?></p>
                        <p><?php echo $data['comment'];?></p>
                <?php endforeach;?>
        </body>
</html>

由于表编码(不正确),如果要在名称中插入unicode字符,例如输出将被截断,从而导致可能的对象注入

示例:

数据集1:无注入

  • name = John
  • comment =我的评论
  • 表数据值= a:2:{s:4:“name”; s:4:“John”; s:7:“comment”; s:10:“我的评论”;}

数据集2:对象注入

  • name = John“; O:8:”stdClass“:1:{s:4:”test“; i:1;}; s:4:blah; s:1:”comment“}
  • 评论=随便

  • 表数据值= a:2:{s:4:“name”; s: 69 :“John”; O:8:“stdClass”:1:{s :4: “测试”; I:1;}; S:4:等等; S:1: “注释”}

在最后一种情况下,我们可以看到注入实际上有些成功,但是,与名称(John)相关的值的字符串长度不正确,它应该是4而不是 69 使注入成功,以便在调用unserialize时执行。

我尝试了几种方法,例如插入空字符,退格字符,删除字符等等,但是我无法使其工作。

开发人员说“它并不脆弱”所以我希望有人可以帮助我找到它实际上很脆弱的证据。

感谢您的时间。

0 个答案:

没有答案