PHP代碼審計學習(6)——命令執行

命令執行

  應用程序有時需要調用一些執行系統命令的函數,如在PHP中,使用system、exec、shell_exec、passthru、popen、proc_popen等函數可以執行系統命令。當黑客能控制這些函數中的參數時,就可以將惡意的系統命令拼接到正常命令中,從而造成命令執行漏洞,這就是命令執行漏洞。

  DVWA的命令審計:https://www.cnblogs.com/Lee-404/p/13038623.html

挖掘思路

  1、用戶可以控制輸入,沒有對應用的輸入進行過濾

  2、存在危險函數,直接搜索危險函數

命令執行的漏洞分類

  1、代碼層過濾不嚴

    商業應用的一些核心代碼封裝在二進制文件中,在web應用中通過system函來調用:system("/bin/program --arg$arg");

  2、系統的漏洞造成

    bash破殼漏洞(CVE-2014-6271)

  3、調用第三方組件存在命令執行

    如WordPress中用來處理圖片的ImageMagick組件、JAVA中的命令執行漏洞(struts2/ElasticsearchGroovy等)、ThinkPHP命令執行

  漏洞危害

  1. 繼承Web服務程序的權限去執行系統命令或讀寫文件
  2. 反彈shell
  3. 控制整個網站甚至服務器
  4. 進一步內網滲透
  5. 等等

  命令通配符

    |、||、&、&&的區別:
    &:無論左邊是false還是true,右邊都執行
    &&:具有短路效果,左邊是false,右邊不執行。
    |:無論左邊是false還是true,右邊都會執行
    ||:具有短路效果,左邊是true,右邊不執行

危險函數

  system

    system函數可以用來執行一個外部的應用程序並將相應的執行結果輸出,函數原型如下:

    string system(string command, int&return_var)

    command是要執行的命令,return_var存放執行命令的執行後的狀態值。

<?php
if(isset($_REQUEST['cmd'])){
    $cmd = ($_REQUEST["cmd"]);
    system($cmd);//eval($cmd);
    echo "</pre>$cmd<pre>";
    die;
}
?>   

 

  exce

    exec函數可以用來執行一個外部的應用程序

    string exec (string command, array&output, int &return_var)

    其中,command是要執行的命令,output是獲得執行命令輸出的每一行字符串,return_var存放執行命令後的狀態值。

<?php
if(isset($_REQUEST['cmd'])){
    $cmd = ($_REQUEST["cmd"]);
    echo exec($cmd);//eval($cmd);
    echo "</pre>$cmd<pre>";
    die;
}
?>

    其實用法差不多

  passthru

    passthru函數可以用來執行一個UNIX系統命令並顯示原始的輸出,當UNIX系統命令的輸出是二進制的數據,並且需要直接返回值給瀏覽器時,需要使用passthru函數來替代system與exec函數。Passthru函數原型如下:

    void passthru (string command, int&return_var)

    其中,command是要執行的命令,return_var存放執行命令後的狀態值

  shell_exce

    shell_exec — 通過 shell 環境執行命令,並且將完整的輸出以字符串的方式返回

    string shell_exec ( string $cmd )

    其中,command是要執行的命令。

  反引號

    命令執行的輸出。 如果執行過程中發生錯誤或者進程不產生輸出,則返回 NULL

<?php
   echo `whoami`; 
?>

    在php中稱之爲執行運算符,PHP 將嘗試將反引號中的內容作爲 shell 命令來執行,並將其輸出信息返回(即,可以賦給一個變量而不是簡單地丟棄到標準輸出,使用反引號運算符“`”的效果與函數 shell_exec() 相同。

代碼中常見位置 

  https://blog.csdn.net/weixin_33798152/article/details/92606607?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-7

  system("$arg"); //可控點直接是待執行的程序

  system("/bin/prog $arg"); //可控點是傳入程序的整個參數

  system("/bin/prog -p $arg"); //可控點是傳入程序的某個參數的值(無引號包裹)

  system("/bin/prog --p=\"$arg\"");//可控點是傳入程序的某個參數的值(有雙引號包裹)

  system("/bin/prog --p='$arg'"); //可控點是傳入程序的某個參數的值(有單引號包裹)

 

  第一種情況

    如果我們能直接控制$arg,那麼就能執行執行任意命令了,沒太多好說的。

  第二種情況

    我們能夠控制的點是程序的整個參數,我們可以直接用&& || 或 | 等等,利用與、或、管道命令來執行其他命令(可以涉及到很多linux命令行技巧)。

還有一個偏門情況,當$arg被 escapeshellcmd處理之後,我們不能越出這個外部程序的範圍,我們可以看看這個程序自身是否有“執行外部命令”的參數或功能,比如linux下的sendmail 命令自帶讀寫文件功能,我們可以用來寫webshell。

  第三種情況

    我們控制的點是一個參數,我們也同樣可以利用與、或、管道來執行其他命令,情境與二無異。

  第四種情況

    這種情況壓力大一點,有雙引號包裹。如果引號沒有被轉義,我們可以先閉合引號,成爲第三種情況後按照第三種情況來利用,如果引號被轉義(addslashes),我們也不必着急。linux shell 環境下雙引號中間的變量也是可以被解析的,我們可以在雙引號內利用反引號執行任意命令 `id`

  第五種情況

    這是最難受的一種情況了,因爲單引號內只是一個字符串,我們要先閉合單引號纔可以執行命令。如:system("/bin/prog –p='aaa' | id")

    危害自然不言而喻,執行命令可以讀寫文件、反彈shell、獲得系統權限、內網***等。

    在漏洞檢測中,除了有回顯的命令注入(比如執行dir 命令或者cat 讀取系統文件);還可以使用盲打的方式,比如curl遠程機器的某個目錄(看access.log),或者通過dns解析的方式獲取到漏洞機器發出的請求

過濾函數

  Escapesshellcmd()
  過濾整條命令

  功能:escapeshellcmd() 對字符串中可能會欺騙 shell 命令執行任意命令的字符進行轉義。 此函數保證用戶輸入的數據在傳送到 exec() 或 system() 函數,或者 執行操作符 之前進行轉義。
反斜線(\)會在以下字符之前插入: &#;`|?~<>^()[]{}$*, \x0A 和 \xFF。 ‘ 和 “ 僅在不配對兒的時候被轉義。 在 Windows 平臺上,所有這些字符以及 % 和 ! 字符都會被空格代替。
定義 :string escapeshellcmd ( string $command)

  Escapeshellarg()
  過濾整個參數
  功能 :escapeshellarg() 將給字符串增加一個單引號並且能引用或者轉碼任何已經存在的單引號,這樣以確保能夠直接將一個字符串傳入 shell 函數,shell 函數包含 exec(), system() 執行運算符(反引號
)

  定義 :string escapeshellarg ( string $arg )

漏洞修復

  1. 儘量少用執行命令的函數或者直接禁用
  2. 參數值儘量使用引號包括
  3. 在使用動態函數之前,確保使用的函數是指定的函數之一
  4. 在進入執行命令的函數/方法之前,對參數進行過濾,對敏感字符進行轉義
  5. 對PHP語言來說,不能完全控制的危險函數最好不要使用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章