前言:檔案上傳漏洞是很常見的漏洞,也非常有趣,接下來就在DVWA靶場中邊學邊練。
檔案上傳漏洞:
檔案上傳漏洞是指由于程式員在對使用者檔案上傳部分的控制不足或者處理缺陷,而導緻的使用者可以越過其本身權限向伺服器上上傳可執行的動态腳本檔案。這裡上傳的檔案可以是木馬,病毒,惡意腳本或者WebShell等。這種攻擊方式是最為直接和有效的,“檔案上傳”本身沒有問題,有問題的是檔案上傳後,伺服器怎麼處理、解釋檔案。如果伺服器的處理邏輯做的不夠安全,則會導緻嚴重的後果。
具體的原理可以看大師傅的講解
Smi1e_——檔案上傳漏洞 學習筆記
檔案上傳漏洞
low級别
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL0UFVNhXTE5keRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyQDN0IDN0ATMxMzNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
觀察源碼
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
# $_FILES["file"]["name"] - 被上傳檔案的名稱
# $_FILES["file"]["tmp_name"] - 存儲在伺服器的檔案的臨時副本的名稱
# basename() 函數傳回路徑中的檔案名部分
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
# move_uploaded_file() 函數将上傳的檔案移動到新位置
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
?>
通過對源碼的分析,我們發現沒有任何防護和限制,那就構造一句話木馬
進行上傳
根據相應的路徑進行菜刀連接配接即可
Medium級别
上傳剛才一句話木馬試一下,發現
隻能上傳JPG或者是PNG,那就來檢視一下源碼
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
// Is it an image?
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
?>
通過分析源碼,發現隻有這一段代碼進行了限制
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) )
隻能上傳jpeg或png的圖像,限制了大小,其他沒有任何防護,那就可以用
一句話木馬圖檔
一句話木馬圖檔的制作
一、建立一個bat檔案,用記事本打開輸入cmd
二、将上傳的圖檔和一句話php檔案執行以下指令即可
copy 圖檔1.jpg/b+PHP檔案2.php/a 自定義圖檔名3.jpg
發現一句話确實已經插入圖檔中
上傳成功,用菜刀連接配接
結果連接配接不上去,這裡我們上傳的是一張圖檔,那對方伺服器就認為我們上傳的是一張很正常的圖,是以隻會當做圖檔來解析,是以圖檔裡的php代碼不會被解析了,這裡需要了解檔案包含漏洞才能将圖檔進行解析。因為檔案包含漏洞也是很好玩的知識,這裡就不詳細寫了,之後單獨總結出一篇部落格來學習檔案包含漏洞
我這裡上傳的是3.jpg
在url位址欄中輸入
http://127.0.0.1/DVWA/vulnerabilities/fi/?page=file://D:\PHPstudy\PHPTutorial\WWW\DVWA\hackable\uploads\3.jpg
發現圖檔已經被解析了,那麼PHP代碼也肯定被伺服器解析了,用菜刀進行連接配接
結果還是連不上去,發現有三行警告
警告:無法修改頭資訊
做到這裡實在連不上去,不知道是什麼原因,這種方法就暫時先留到這,等找到解決方法了再繼續做
除下這種方法還可以用抓包修改檔案的type
通過觀察這兩段代碼
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {
隻是限制了Content-Type,沒有限制字尾名,是以這裡可以直接抓包修改Content-Type即可
發包,上傳成功
通路成功
這裡為了友善就不連接配接菜刀了,将一句話木馬改為
High級别
檢視源碼
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Is it an image?
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
#$_FILES['myFile']['name'] 顯示用戶端檔案的原名稱。
#$_FILES['myFile']['type'] 檔案的 MIME 類型,例如"image/gif"。
#$_FILES['myFile']['size'] 已上傳檔案的大小,機關為位元組。
#$_FILES['myFile']['tmp_name'] 儲存的臨時檔案名,一般是系統預設。
#$_FILES['myFile']['error'] 該檔案上傳相關的錯誤代碼。以下為不同代碼代表的意思:
#strtolower() 函數把字元串轉換為小寫
#getimagesize() 函數将測定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 圖像檔案的大小并傳回圖像的尺寸以及檔案類型及圖檔高度與寬度。
#strrpos() 函數查找字元串在另一字元串中最後一次出現的位置
?>
觀察源碼發現,代碼中增加了一段代碼
并且修改了這一段代碼
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&
( $uploaded_size < 100000 ) &&
getimagesize( $uploaded_tmp ) )
先來解讀一下第一段代碼,
strrpos()函數
查找
.
出現在
$uploaded_name
的位置然後加1,再利用
substr()函數
從變量
$uploaded_name
的指定位置截取部分字元串。是以這段代碼的作用就是為了截取上傳檔案的字尾名
第二段代碼,
strtolower()函數
将無論是大寫或小寫的字尾名全改為小寫,以防
大小寫繞過
,并且
getimagesize() 函數
用于擷取圖像大小及相關資訊,是以這裡再用之前的php檔案字尾名改為jpg或png就不可行了,不過也可以利用這個函數的漏洞進行繞過,既然對檔案的開頭内容進行了檢測并且通過二進制識别是否為圖像,那麼就可以利用檔案頭欺騙,來讓getimagesize()函數檢測無效。
先了解一下常用圖檔的檔案頭辨別
通過檔案頭辨別判斷圖檔格式
檔案頭欺騙
getimagesize() 函數
在這裡作用就是檢測是否為圖像的作用,這裡就用最簡便的GIF的檔案頭,在一句話木馬前加上GIF的檔案頭辨別
上傳
上傳成功,說明成功繞過
用檔案包含來進行通路
但應該是我配置有問題,我的檔案包含報錯,但這種方法沒錯
除此之外那,也可以上傳圖檔馬,然後用檔案包含進行解析,由于我這裡配置的有問題就不再示範了,不過這種方法确實是可行的,看過許多大師傅們都是這樣做的
總結:雖然遇到了很多問題,不過也初步了解了檔案上傳漏洞的原理和一些姿勢,接下來通過Upload-labs進行學習。