Dvwa之檔案上傳漏洞
阿新 • • 發佈:2019-02-18
今天到了比較有意思的地方,一句話我們要傳木馬啦!這個就比較有意思了,畢竟我們查詢漏洞最想要的效果之一就是傳馬成功,獲得我們想要的許可權。
攻擊原理:
1.web容器的解析漏洞
2.配合解析漏洞進行waf繞過和上傳木馬。
因為我用的web容器是Apache,所以暫且只介紹Apache的檔案解析漏洞。
比如現在我們有一個1.php.rar.xx.kk的檔案,那麼伺服器會報錯嗎?答案是否定的,Apache有自己的一套檔案處理方式,
它會從後往前進行檔案解析,到遇見認識的字尾為止,最終會解析成1.php。那麼,它都認識什麼呢?這個在Apaceh的安裝目錄/conf/mime.types檔案中有詳細介紹。
檔案上傳漏洞的利用是有限制條件的,首先當然是要能夠成功上傳木馬檔案,其次上傳檔案必須能夠被執行,最後就是上傳檔案的路徑必須可知。不幸的是,這裡三個條件全都滿足。
測試:
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>";
}
}
?>
經過分析原始碼,我們可以知道伺服器並未對上傳的檔案進行任何的過濾,並且對檔案路徑進行了回顯。問題來了,我們上傳什麼檔案。當然是我們鍾愛的木馬,接下來以最簡單的一句話木馬為例,進行我們的測試。
首先上傳木馬
密碼123456,上傳以後我們發現檔案路徑是
然後用菜刀進行連線。
這樣菜刀就成功連線到了目標主機,並可以在進行下載,刪除檔案等操作,還可以獲取對方shell。
中級
看原始碼
<?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>';
}
}
?>
分析中級程式碼可知,伺服器對上傳進行了限制,字尾必須是png和jpeg,並且大小必須小於10000b大約是97kb。那麼我們便不能這麼明目張膽的上傳木馬了。主要有以下三種姿勢:
1.配合檔案包含漏洞
把a.php改為a.png,配合檔案上傳進行繞過,當然別忘了繞過檔案包含的waf。由於環境問題,這個實驗就不做了,舉個梨子。
在位址列中輸入
http://192.168.0.104/dvwa/vulnerabilities/fi/?page=hthttp://tp://192.168.0.104/dvwa/hackable/uploads/a.png
2.抓包修改檔案型別
用bp抓包,修改檔案型別。
3.通過00截斷繞過
在php版本小於5.3.4的版本中,當Magic_quote_gpc選項為off時,可以在檔名中使用%00截斷,所以可以把上傳檔案命名a1.php%00.png進行繞過,我們用bp抓包檢測一下檔案型別。
可以發現檔案型別是png成功繞過前端,並且到伺服器檔案會被解析成php檔案,因為00後面的被截斷了,伺服器不解析。
高階程式碼
<?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>';
}
}
?>
高階程式碼主要應用了getimagesize(string filename)函式對圖片進行辨別,該函式會通過讀取檔案頭,返回圖片的長、寬等資訊,如果沒有相關的圖片檔案頭,函式會報錯。並且程式碼通過讀取檔案最後一個“.”希望來限制檔案型別必須是jpg,jpeg,png。高階程式碼看來已經非常嚴格了,但是我們還可以繞過,檔名的限制我們可以通過00截斷繞過而圖片限制,我們可以把木馬放進圖片裡。
在windows下我們可以通過copy命令合成圖片木馬。
copy a1.png/b+a.php/a hack.png
我們把合成的木馬圖片丟進16進位制編輯器看看。
我們可以發現木馬語句就在最後面。
接下來我們構造圖片名為hack.php%00.png即可,當然也可以採用檔案包含和改包的方式進行繞過檔案型別的waf,具體方法參照中級程式碼嘗試。
安全程式碼
<?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();
?>
“`
可以看到,Impossible級別的程式碼對上傳檔案進行了重新命名(為md5值,導致%00截斷無法繞過過濾規則),加入Anti-CSRF token防護CSRF攻擊,同時對檔案的內容作了嚴格的檢查,導致攻擊者無法上傳含有惡意指令碼的檔案。