1. 程式人生 > >本地檔案包含漏洞詳解

本地檔案包含漏洞詳解

0x00:漏洞定義
在通過伺服器指令碼的函式引入檔案時,由於傳入的檔名沒有經過合理的校驗,從而操作了預想之外的檔案,導致意外的檔案洩露、惡意程式碼的注入等。

檔案包含分為兩種,一種為本地檔案包含,一種為遠端檔案包含,此篇記錄本地檔案包含。本地檔案包含(Local File Include),簡稱 LFI。

0x01:涉及函式
檔案包含在 php 中,涉及到的危險函式有四個,分別是 include()、include_once()、require()、require_once()。

區別如下:

include:包含並執行指定的檔案,包含檔案發生錯誤時,程式警告,但會繼續執行。
include_once:和 include 類似,不同處在於 include_once 會檢查這個檔案是否已經被匯入,如果已匯入,下文便不會再匯入,直面 once 理解就是隻匯入一次。

require:包含並執行指定的檔案,包含檔案發生錯誤時,程式直接終止執行。
require_once:和 require 類似,不同處在於 require_once 只匯入一次。

0x02:產生場景
開發過程中,多個檔案都會用到的程式碼,通常會放到一個單獨的檔案中,用到時再包含進來。當把包含的檔案寫死在程式中時,該漏洞是不存在的,但很多情況都會動態的去包含所需的檔案,這時候則會產生檔案包含漏洞。

0x03:簡單示例
以下程式碼是最簡單的一個檔案包含示例,程式沒有對要包含的檔案進行驗證,導致可控。

<?php
    $file = $_GET['file'];
    if(isset($file)){
        include("$file");
    }else{
        echo "file fail";
    }

因為檔案路徑可控,當輸入系統的密碼檔案所在路徑時,內容會輸出出來,如下圖:

這樣的程式碼過於危險,所以很少有人這麼寫,但有些防護措施是很差的,例如通過替換../, 程式碼如下:

$file=str_replace('../','',$_GET['file']);
 
if(isset($file)){
    include("$file");
}else{
    echo "file fail";
}

通過檢測../ 然後替換為空,上一種情況是通過../ 定位到根目錄的,當../ 被過濾後,可以直接通過 / 定位,如下圖:

有時的程式也會通過新增字尾來做防護措施,例如如下程式碼:

$file=str_replace('../','',$_GET['file']);
 
if(isset($file)){
    include("$file" . "php");
}else{
    echo "file fail";
}

這個可以通過 %00 截斷來繞過,但要注意,是老版本了,php5.2.x 的測試可以,php5.3.x 的測試不行,而且 php.ini 中的 magic_quotes_gpc 配置項為 off 時,才可以。magic_quotes_gpc 是用來轉義特殊字元的,開啟後 %00 會被轉義,這個可以做下了解,畢竟老版本用的比較少了。測試結果如下圖(win):

新建一個 txt 檔案,內容為 <? phpinfo(); ?>

php5.2.17 測試結果:

當把 magic_quotes_gpc 設定為 on 時,%00 會被轉義,結果如下:

當把 php 版本切換為 php5.3.29 時,測試不通過,結果如下:

順便提一下,為什麼 %00 能截斷,PHP 核心是 C 實現的,使用了 C 中的字元處理函式,在連線字串時,0 位元組也就是 x00 會作為結束符,所以只要加入一個 0 位元組,就可以截斷字串,0 經過 URL 編碼後為 %00。

對於 %00 截斷可以通過以上幾個圖的提示來判斷出 php 的版本或是否開啟了 magic_quotes_gpc 配置項,能迅速查出原因即可。

當 %00 不能截斷時,在 win 系統中,可以利用 php 的 zip:// 協議,例如:寫一個 hello.php,內容為 <?php phpinfo();?>,然後壓縮成檔案 test.zip 並上傳,隨後在系統中輸入 localhost/test.php?file=zip://test.zip%23hello 即可,因為程式有後綴措施,這樣引數 file 實際就變成了 zip://test.zip#23hello.php,意思為讀取 test.zip 中的 hello.php 檔案內容,如下圖:

0x04:利用示例

1,如果存在本地檔案包含漏洞時,不論包含 txt 還是 jpg,程式都會以 php 來解析執行,也就意味著可以上傳一句話木馬,直接用菜刀連線。

例如新建一個 1.txt 內容為:

<?php @eval($_POST['caidao']);?>

隨後將字尾改為 jpg,利用檔案包含漏洞包含此檔案,結果如下:

2,可以利用 php://input 輸入流執行任意命令,前提是 php.ini 的 allow_url_include 項設定為 on,不受版本控制,例如以下操作圖:

使用火狐外掛 hackbar 即可。

3,利用 php 的資料協議 data:// 可以檢視檔案原始碼,前提是 php.ini 中的 allow_url_fopen 和 allow_url_include 兩個配置為 on, 例如以下操作圖:

當碰到 WAF 時,可以把 <> 這些特殊符號進行編碼再試。

0x05: 如何防禦

1,儘量不使用動態包含檔案,如果可以靜態的去包含最好。
2,在使用動態包含時,新增字尾措施的情況下,請保證 php 版本高於 5.3 或是最新版,防止截斷攻擊。
3,對於動態包含的檔案可以設定一個白名單,如果不屬於白名單內的檔名,則不包含。
4,可以使用 open_basedir 限制目錄項來指定包含的目錄範圍,防止目錄遍歷,php.ini 中設定 open_basedir="指定目錄"。

5,對於中介軟體 apache 或 nginx 等,可以使用中介軟體自身的指定目錄範圍配置,效果更好。
--------------------- 
作者:發哥微課堂 
來源:CSDN 
原文:https://blog.csdn.net/fageweiketang/article/details/80699051 
版權宣告:本文為博主原創文章,轉載請附上博文連結!