前言
我們知道對靶機的滲透可以提高自己對知識的掌握能力,這篇文章就對上傳靶機upload-labs做一個全面的思路分析,一共21個關卡。讓我們開始吧,之前也寫過關於上傳的專題,分別為淺談文件上傳漏洞(客戶端JS檢測繞過)
淺談文件上傳漏洞(其他方式繞過總結)
靶機環境搭建
Upload-Labs 環境要求
操作系統:windows、Linux
php版本:推薦5.2.17(其它版本可能會導致部分Pass無法突破)
php組件:php_gd2,php_exif(部分Pass需要開啟這兩個擴展)
apache:以moudel方式連接
項目地址:https://github.com/c0ny1/upload-labs
直接使用phpstudy搭建,將下載的文件放在對應的根目錄即可。訪問如下:
解題思路
pass-01
首先看第一關,查看提示和源碼,發現是前端JS驗證,而我們知道,前端驗證,有和沒有基本一樣。
繞過也非常簡單,可以瀏覽器直接禁用JS,先按F12,然后按F1,找到禁用JS,如下圖:
然后直接上傳php木馬。結果如下:
這是一種方法,當然也可以直接burp抓包,修改后綴直接上傳。
pass-02
看第二關,首先分析源碼
分析代碼,發現只是檢查了content-type類型,這個也是很好繞過的,直接抓取數據包,修改類型就可以了。抓的數據包如下:
將類型改為image/jpeg,直接上傳PHP木馬,結果如下
木馬上傳成功。
pass-03
看第三關,分析源碼
發現第三關是基於黑名單防護,不允許上傳'.asp','.aspx','.php','.jsp'后綴的文件,這個黑名單是不全的,比如可以嘗試上傳.phtml .phps .php5 .pht的后綴文件,也是可以當做php腳本解析的,如果Web服務器是apache的話,也可以上傳.htaccess文件,來繞過黑名單。首先嘗試上傳.phtml,發現上傳成功,再響應包中找到上傳路徑。這里要注意一下,要在apache的httpd.conf中有如下配置代碼
AddType application/x-httpd-php .php .phtml .phps .php5 .pht
pass-04
看第四關,分析源碼
發現這里黑名單基本過濾了后綴,但是,沒有.htaccess,可以上傳.htaccess文件,來達到解析腳本的目的。也可以用另外的一種方法,看代碼6到10行,這里是對文件后綴的一些處理,包括刪除結尾的點,刪除空格,全都轉換成小寫等,然而這么處理肯定有想不到的地方,比如構造后綴.php. .中間是一個空格(后面的第八關和第十關是同樣的思路),即達到了繞過黑名單,又經過檢查使得腳本木馬可以解析。如下圖:
訪問腳本木馬,成功解析
pass-05
第五關和第四關一樣,只是黑名單里添加了.htaccess,所以只能使用構造后綴的方式了,四關的方法五官通用,所以這里就不詳細贅述了。
pass-06
看第六關,分析源碼
看第5至10行,里面的過濾沒有限制大小寫,所以可以嘗試大小寫組合繞過。比如.pHP等。嘗試上傳,如下圖:
上傳成功,腳本木馬成功解析:
pass-07
看第七關,分析源碼:
通過觀察源碼,發現沒有對空格進行處理,可以直接在末尾添加空格來繞過黑名單。如下:
上傳成功,成功解析。
pass-08
看第八關,分析源碼:
這里的黑名單限制了所有可以解析的后綴,所以只能構造特殊后綴來繞過防護,這里去除了空格,並用strrchr函數查找指定小黑點最后一次出現,所以構造的后綴為.php. (點php點加空格),成功繞過,如下圖:
上傳成功,成功解析。
pass-09
看第九關,分析源碼:
看第5行到第10行,源碼中未過濾::$DATA,可以利用::$DATA來繞過過濾,到這里小伙伴可能就要問了,為什么::$DATA可以繞過黑名單呢?這其實是利用了windows的特性,在window的時候如果文件名+"::$DATA"會把::$DATA之后的數據當成文件流處理,不會檢測后綴名,且保持::$DATA之前的文件名,他的目的就是不檢查后綴名。例如:"test.php::$DATA"Windows會自動去掉末尾的::$DATA變成"test.php"。
現在抓取數據包驗證。上傳成功,如下圖。
上傳成功,成功解析。
pass-10
看第十關,分析源碼
這一關和第八關類似,就比第八關多了一行,多刪除了一個點,所以還是采用構造后綴的方式,這次構造的后綴為.php. .(點php點空格點)正好繞過過濾。
構造好后,上傳成功
解析成功
pass-11
看第十一關,分析源碼
這里的重點在第八行,這里使用了str_ireplace函數將匹配到的字符替換為空,所以繞過思路就很簡單了,只需要雙寫就可以了,刪除字符后,剩余的又重新拼接為后綴,達到繞過的目的,抓取數據包測試如下,上傳成功。
訪問,解析成功。
pass-12
看十二關,分析源碼
分析源碼我們可以知道,這里是基於白名單過濾,只允許上傳'jpg','png','gif',但是這里注意第八行,上傳路徑是可以控制的,所以可以利用%00截斷,來達到上傳木馬的目的。這里要注意一下,%00截斷想要利用成功,php版本小於5.3.4(高版本php官方修復了這個漏洞),php的magic_quotes_gpc為OFF狀態。抓取數據包,進行嘗試,如下圖:
訪問,解析成功
pass-13
看十三關,分析源碼
同樣是白名單,也是上傳位置可控,不過是由GET傳輸變為POST,還是利用%00截斷。不過因為POST不會進行自動解碼,所以要自己在16進制中進行修改,如下圖:
上傳成功,解析成功
pass-14
第十四關是上傳圖片馬,配合解析漏洞
分析代碼
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 = "上傳出錯!";
}
}
}
下面是文件包含的代碼
include.php
<?php
/*
本頁面存在文件包含漏洞,用於測試圖片馬是否能正常運行!
*/
header("Content-Type:text/html;charset=utf-8");
$file = $_GET['file'];
if(isset($file)){
include $file;
}else{
show_source(__file__);
}
?>
分析代碼可以知道它只讀2字節,只需要將木馬后綴改為圖片格式,內容加個圖片頭部,然后在返回包中找到路徑,然后寫在file參數后,因為file參數include的原因都會直接執行。如下:
長傳成功,配合文件包含漏洞解析圖片格式的木馬。
pass-15
先看源碼:
這里使用getimagesize()函數來驗證是否是圖片,這里說一下getimagesize(),這個函數功能會對目標文件的16進制去進行一個讀取,去讀取頭幾個字符串是不是符合圖片的要求的。getimagesize()返回結果中有文件大小和文件類型,如果用這個函數來獲取類型,從而判斷是否是圖片的話,會存在問題。是可以被繞過的,因為圖片頭可以被偽造。這里偽造gif的圖片頭,來進行上傳,如下
圖片木馬上傳成功。
pass-16
這一關需要開啟php_exif
看源碼
這里使用exif_imagetype函數來檢查是否是圖片,這里說一下exif_imagetype(),它是讀取一個圖像的第一個字節並檢查其簽名。所以也是可以通過偽造圖片頭來進行繞過的。這里同樣偽造gif的圖片頭,來進行上傳,如下
上傳成功
pass-17
看源碼
這一關比較綜合,判斷了后綴名、content-type,以及利用imagecreatefromgif判斷是否為gif圖片,最后再做了一次二次渲染。還是按照第16關的思路走一下,看是否成功。顯然失敗了。
那就做一個圖片木馬,上傳一個正常圖片,抓取數據包,在圖片末尾插入惡意代碼,如下:
然后,進行上傳操作。上傳成功,如下。
因為這里進行了二次渲染,所以還沒有結束,我們將上傳的圖片下載到本地查看。
這里發現在進行二次渲染的過程中,我們插入到圖片的惡意代碼被清理掉了,所以需要對比渲染前后,哪些地方沒有變化,我們將惡意代碼插入到那里,來繞過二次渲染。對比發現,這里渲染前后沒有發生變化。
所以,我將惡意代碼插入到這里,如下圖:
重新上傳,上傳成功,再次下載到本地,發現惡意代碼沒有被清除,繞過了二次渲染。
pass-18
看源碼
這里的代碼邏輯是先將文件上傳到服務器,然后判斷文件后綴是否在白名單里,如果在則重命名,否則刪除。這樣就存在一個安全問題,那就是我同時上傳多個相同文件,在它刪除之前訪問就可以了。也就是條件競爭問題。可以借助burp的暴力破解模塊。這里復現失敗了=_="。
pass-19
這里同樣存在條件競爭問題,不過就是需要換成圖片木馬。其他和第十八關一樣。
pass-20
看源碼
這里發現move_uploaded_file()函數中的img_path是由post參數save_name控制的,因此可以在save_name利用00截斷繞過,和前面關卡的00截斷類似。如下:
上傳成功。
pass-21
看源碼
說實話,這個代碼看的我有點懵。參考網上文章一點點分析吧,首先第五行以白名單的形式檢查MIME這個可以直接在數據包中修改,然后向下分析,到第十行,這里的含義是如果POST接收的save_name值為空則賦值給$_FILES['upload_file']['name'],否則是本身。接着是用explode() 函數把字符串打散為數組,然后解釋一下下面涉及到的函數的含義。
end()函數將 array的內部指針移動到最后一個單元並返回其值
reset()函數將 array 的內部指針倒回到第一個單元並返回第一個數組單元的值
count() 函數計算數組中的單元數目或對象中的屬性個數,這里要注意,數組下標從0開始
然后這里用end函數將接收的后綴與白名單比較,如果符合,繼續執行,然后數組第一位和$file[count($file) - 1]進行拼接,產生保存文件名file_name。
所以這里采用數組繞過,save_name[0]=pass21.php, save_name[2]=jpg,$ext=jpg過白名單,reset($file)=pass21.php
$file[1]=null,這樣就成功上傳pass21.php.(windows多個點不影響)
抓包測試。上傳成功。
結語
這篇文章對於upload-labs靶場進行了全通關思路講解,如有錯誤請斧正。