DVWA V1.9:File Upload(檔案上傳)
- File Inclusion 介紹
- Low 級别
-
- 核心代碼
- 官方提示
- 漏洞利用
- Medium 級别
-
- 核心代碼
- 官方提示
- 漏洞利用
- High 級别
-
- 核心代碼
- 官方提示
- 漏洞利用
- Impossible 級别
-
- 核心代碼
- 官方提示
File Inclusion 介紹
上傳的檔案是Web應用程式的一大風險。
許多攻擊的第一步是讓一些代碼攻擊系統,然後攻擊者隻需要找到一種方法來執行代碼。
使用檔案上傳有助于攻擊者完成第一步。
不受限制的檔案上傳的後果會有所不同,包括完整的系統接管、過載的檔案系統、向後端系統轉發攻擊和簡單的破壞。
這取決于應用程式對上傳檔案所做的操作,包括存儲的位置。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLxcGRNpXTq1keRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3UjNxUjMzITM1ITMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
Low 級别
核心代碼
<?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' ] );
// 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>";
}
}
?>
basename(path,suffix)
函數傳回路徑中的檔案名部分,如果可選參數suffix為空,則傳回的檔案名包含字尾名,反之不包含字尾名。
可以看到,伺服器對上傳檔案的類型、内容沒有做任何的檢查、過濾,存在明顯的檔案上傳漏洞,生成上傳路徑後,伺服器會檢查是否上傳成功并傳回相應提示資訊。
官方提示
低級别将不檢查檔案以任何方式上載的内容。它隻依賴于信任。
Spoiler: Upload any valid PHP file with command in it.
漏洞利用
檔案上傳漏洞的利用是有限制條件的,
首先當然是要能夠成功上傳木馬檔案,其次上傳檔案必須能夠被執行,最後就是上傳檔案的路徑必須可知。
不幸的是,這裡三個條件全都滿足。
編寫php一句話木馬檔案。
<?php eval($_POST[wanku]);?>
上傳木馬檔案。
路徑也給出來了,使用菜刀去連接配接,成功。
http://43.247.91.228:81/hackable/uploads/shell.php
Medium 級别
核心代碼
<?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>';
}
}
?>
可以看到,Medium級别的代碼對上傳檔案的類型、大小做了限制,要求檔案類型必須是jpeg或者png,大小不能超過100000B(約為97.6KB)。
官方提示
當使用媒體級别時,它将在上傳時檢查用戶端的報告檔案類型。
Spoiler: Worth looking for any restrictions within any "hidden" form fields.
漏洞利用
因為采用的是一句話木馬,是以檔案大小不會有問題,至于檔案類型的檢查,嘗試修改檔案名為hack.png,上傳是OK的。
但是我們使用菜刀去連接配接時,因為木馬不是php檔案,并不以php格式執行,是以編譯不了。
方法一:抓包改名
這時候我們就需要使用burp進行抓包,把png字尾改成php,以便執行php一句話。
發送到Repeater子產品修改字尾,上傳成功。
再使用菜刀去連接配接shell2.php檔案,成功拿到shell。
方法二:截斷繞過
在php版本小于5.3.4的伺服器中,當Magic_quote_gpc選項為off時,可以在檔案名中使用%00截斷,是以可以把上傳檔案命名為hack.php%00.png。
上傳成功。
而伺服器會認為其檔案名為hack.php,順勢解析為php檔案。
遺憾的是,由于本次實驗環境的php版本為5.5.9,是以無法進行驗證。
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>';
}
}
?>
strrpos(string,find,start)
函數傳回字元串find在另一字元串string中最後一次出現的位置,如果沒有找到字元串則傳回false,可選參數start規定在何處開始搜尋。
getimagesize(string filename)
函數會通過讀取檔案頭,傳回圖檔的長、寬等資訊,如果沒有相關的圖檔檔案頭,函數會報錯。
可以看到,High級别的代碼讀取檔案名中最後一個”.”後的字元串,期望通過檔案名來限制檔案類型,是以要求上傳檔案名形式必須是”.jpg”、”.jpeg” 、”*.png”之一。
同時,getimagesize函數更是限制了上傳檔案的檔案頭必須為圖像類型。
官方提示
一旦從用戶端接收到該檔案,伺服器将嘗試調整請求中包含的任何圖像的大小。
Spoiler: need to link in another vulnerability, such as file includion.
漏洞利用
copy參考連結中的利用方法
首先利用copy将一句話木馬檔案php.php與圖檔檔案1.jpg合并
打開可以看到,一句話木馬藏到了最後。
順利通過檔案頭檢查,可以成功上傳。
上菜刀,右鍵添加shell,位址欄填入
http://192.168.153.130/dvwa/vulnerabilities/fi/?page=file:///C:/xampp/htdocs/dvwa/hackable/uploads/hack.jpg
參數名填apple,
腳本語言選擇php。
成功拿到webshell。
Impossible 級别
核心代碼
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ];
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/';
//$target_file = basename( $uploaded_name, '.' . $uploaded_ext ) . '-';
$target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
$temp_file = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) );
$temp_file .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;
// Is it an image?
if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
( $uploaded_size < 100000 ) &&
( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png' ) &&
getimagesize( $uploaded_tmp ) ) {
// Strip any metadata, by re-encoding image (Note, using php-Imagick is recommended over php-GD)
if( $uploaded_type == 'image/jpeg' ) {
$img = imagecreatefromjpeg( $uploaded_tmp );
imagejpeg( $img, $temp_file, 100);
}
else {
$img = imagecreatefrompng( $uploaded_tmp );
imagepng( $img, $temp_file, 9);
}
imagedestroy( $img );
// Can we move the file to the web root from the temp folder?
if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) {
// Yes!
echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>";
}
else {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
// Delete any temp files
if( file_exists( $temp_file ) )
unlink( $temp_file );
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
in_get(varname)
函數傳回相應選項的值
imagecreatefromjpeg ( filename )
函數傳回圖檔檔案的圖像辨別,失敗傳回false
imagejpeg ( image , filename , quality)
從image圖像以filename為檔案名建立一個JPEG圖像,可選參數quality,範圍從0(最差品質,檔案更小)到100(最佳品質,檔案最大)。
imagedestroy( img )
函數銷毀圖像資源
可以看到,Impossible級别的代碼對上傳檔案進行了重命名(為md5值,導緻%00截斷無法繞過過濾規則),加入Anti-CSRF token防護CSRF攻擊,同時對檔案的内容作了嚴格的檢查,導緻攻擊者無法上傳含有惡意腳本的檔案。
官方提示
這将檢查從所有級别到目前為止的一切,然後重新編碼圖像。這将産生一個新的圖像,進而剝離任何“非圖像”代碼(包括中繼資料)。
參考連結:
新手指南:DVWA-1.9全級别教程之File Upload