DDCTF2019 WEB Upload-IMG

这题主要考察文件包含的二次渲染。

思路借鉴自博客:https://blog.csdn.net/weixin_43571641/article/details/84667126

脚本工具来源于博客:https://xz.aliyun.com/t/2657

源码复现

下面是我根据服务器行为进行的代码复现,主要代码来源于https://github.com/c0ny1/upload-labs/blob/master/Pass-16/index.php 。需要依赖于php-gd模块,没有的话可以自行安装。

<?php

// 设置本地路径为上传路径
define('UPLOAD_PATH',dirname(__FILE__));

// 默认上传失败
$is_upload = false;

if (isset($_GET['type']) && $_GET['type'] === 'upload'){
    // 获得上传文件的基本信息,文件名,类型,大小,临时文件路径
    $filename = $_FILES['file']['name'];
    $filetype = $_FILES['file']['type'];
    $tmpname = $_FILES['file']['tmp_name'];
    $target_path=UPLOAD_PATH.'/'.basename($filename);
    // 获得上传文件的扩展名
    $fileext= substr(strrchr($filename,"."),1);
    //判断文件后缀与类型,合法才进行上传操作
    if(($fileext == "jpg") && ($filetype=="image/jpeg")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefromjpeg($target_path);
            if($im == false){
                $msg = "该文件不是jpg格式的图片!";
                @unlink($target_path);
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".jpg";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagejpeg($im,$img_path);
                @unlink($target_path);
                $is_upload = true;
            }
        } else {
            $msg = "上传出错!";
        }
    }else if(($fileext == "png") && ($filetype=="image/png")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefrompng($target_path);
            if($im == false){
                $msg = "该文件不是png格式的图片!";
                @unlink($target_path);
            }else{
                 //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".png";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagepng($im,$img_path);
                @unlink($target_path);
                $is_upload = true;               
            }
        } else {
            $msg = "上传出错!";
        }
    }else if(($fileext == "gif") && ($filetype=="image/gif")){
        if(move_uploaded_file($tmpname,$target_path)){
            //使用上传的图片生成新的图片
            $im = imagecreatefromgif($target_path);
            if($im == false){
                $msg = "该文件不是gif格式的图片!";
                @unlink($target_path);
            }else{
                //给新图片指定文件名
                srand(time());
                $newfilename = strval(rand()).".gif";
                //显示二次渲染后的图片(使用用户上传图片生成的新图片)
                $img_path = UPLOAD_PATH.'/'.$newfilename;
                imagegif($im,$img_path);
                @unlink($target_path);
                $is_upload = true;
            }
        } else {
            $msg = "上传出错!";
        }
    }else{
        $msg = "请上传JPG/GIF/PNG格式的图片文件";
    }

    if($is_upload === true){
        // 判断是否有字符串
        if(strpos( file_get_contents($img_path), 'phpinfo()') === false){
            $msg = "<img src=\"$newfilename\"><br>[Check Error]上传的图片源代码中未包含指定字符串:<font color=\"red\">phpinfo()</font>";
        }else{
            $msg = "<img src=\"$newfilename\"><br>[Success]Flag=DDCTF{B3s7_7ry_php1nf0_1d2667badf479fad}";
        }
    }

    die($msg);
}

?>
<html>
<body>

<form action="upload.php?type=upload" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /> 
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>

赛题分析

先访问看看有什么提示。看到需要授权访问,但是题目已经给了用户名和密码,直接登录就行。

ex@Ex:~/test$ curl -v http://117.51.148.166/upload.php
*   Trying 117.51.148.166...
* TCP_NODELAY set
* Connected to 117.51.148.166 (117.51.148.166) port 80 (#0)
> GET /upload.php HTTP/1.1
> Host: 117.51.148.166
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 401 Unauthorized
< Server: nginx
< Date: Mon, 15 Apr 2019 02:05:03 GMT
< Content-Type: text/html
< Content-Length: 188
< Connection: keep-alive
< WWW-Authenticate: Basic realm="ddctf"
< 
<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host 117.51.148.166 left intact

下面是登录成功的网页:

<html>
<body>

<form action="upload.php?type=upload" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /> 
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>

随便上传一张图片试试。得到下面的回应:

<img src="image/190415100910_21035964.jpg"><br>[Check Error]上传的图片源代码中未包含指定字符串:<font color="red">phpinfo()</font>

直接加到文件尾部echo -n "phpinfo()" >> t.jpg,再次上传还是上面的情况。把图片下载下来查看,发现原先被我们加在文件尾部的phpinfo()不见了。应该是被渲染了。

二次渲染

构造图片时,我们可以将代码插入到图片不会被渲染的部分就行。

可以直接使用国外大牛编写的脚本jpg_payload.php

jpg_payload.php下载:http://file.eonew.cn/ctf/web/jpg_payload.php

使用方法:php jpg_payload.php 1.jpg,1.jpg为你要处理的图片,可以修改代码中的$miniPayload = "<?=phpinfo();?>";来更改要传入的内容,然后上传处理好的图片,如果被绊住了,就把渲染的图片下载下来,继续用jpg_payload.php处理,多试几次flag就出来了。

最终html

<img src="image/190415104238_533203990.jpg"><br>[Success]Flag=DDCTF{B3s7_7ry_php1nf0_1d2667badf479fad}

总结

有些原理不必深究,会用就行,人的时间是有限的,所以在学习时应该懂得取舍。

说点什么

avatar
  Subscribe  
提醒