1. 程式人生 > >Dvwa之檔案上傳漏洞

Dvwa之檔案上傳漏洞

今天到了比較有意思的地方,一句話我們要傳木馬啦!這個就比較有意思了,畢竟我們查詢漏洞最想要的效果之一就是傳馬成功,獲得我們想要的許可權。
攻擊原理:
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攻擊,同時對檔案的內容作了嚴格的檢查,導致攻擊者無法上傳含有惡意指令碼的檔案。