1. 程式人生 > >php程式碼審計命令執行漏洞

php程式碼審計命令執行漏洞

命令執行漏洞,使用者通過瀏覽器在遠端伺服器上執行任意系統命令,嚴格意義上,與程式碼執行漏洞還是有一定的區別。

 常用命令執行函式

exec()、system()、popen()、passthru()、proc_open()、pcntl_exec()、shell_exec() 、反引號` 實際上是使用shell_exec()函式

system() 輸出並返回最後一行shell結果。 
exec() 不輸出結果,返回最後一行shell結果,所有結果可以儲存到一個返回的數組裡面。 
passthru() 只調用命令,把命令的執行結果原樣地直接輸出到標準輸出裝置上。

popen()、proc_open() 不會直接返回執行結果,而是返回一個檔案指標

漏洞利用及繞過姿勢  

| 命令管道符

<>>> 檔案重定向符

測試: 0 | dir c:

  程式碼只過濾了部分特殊字元,可以考慮用其他字元進行測試,這邊列舉一下Window/Linux可利用的特殊字元:

windows支援:

|     ,不管前面為真還是假 ,直接執行後面的語句      ping 127.0.0.1|whoami          

||    前面出錯執行後面的 ,前面為假 ,若前面為真則不執行後面的      ping  2 || whoami 

&   前面的語句為假執行後面的,前面可真可假 ,如前面為真,前面後面的都會被執行  ping 127.0.0.1&whoami

&&前面的語句為假則直接出錯,後面的也不執行,前面只能為真    ping 127.0.0.1&&whoami

Linux支援:

;     前面的執行完執行後面的 (不管前面的是真是假)     ping 127.0.0.1;whoami  

|     管道符,顯示後面的執行結果   ping 127.0.0.1|whoami            

|| 表示上一條命令執行失敗後,才執行下一條命令   ping 1||whoami  

&   前面的語句為假則直接執行後面的,前面可真可假                       ping 127.0.0.1&whoami

&&前面的語句為假則直接出錯,後面的也不執行,前面只能為真    ping 127.0.0.1&&whoami

參考連結 :https://blog.csdn.net/chinabestchina/article/details/72686002

利用條件

  1. 應用呼叫執行系統命令的函式
  2. 將使用者輸入作為系統命令的引數拼接到了命令列中
  3. 沒有對使用者輸入進行過濾或過濾不嚴

漏洞分類

  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. 等等

漏洞可能程式碼(以system為例)

1. system("$arg"); //直接輸入即可

2. system("/bin/prog $arg"); //直接輸入;ls

3. system("/bin/prog -p $arg"); //和2一樣

4. system("/bin/prog --p=\"$arg\""); //可以輸入";ls;"

5. system("/bin/prog --p='$arg'"); //可以輸入';ls;'

在Linux上,上面的;也可以用|、||代替 ;前面的執行完執行後面的 |是管道符,顯示後面的執行結果 ||當前面的執行出錯時執行後面

在Windows上,不能用;可以用&、&&、|、||代替 &前面的語句為假則直接執行後面的 &&前面的語句為假則直接出錯,後面的也不執行 |直接執行後面的語句 ||前面出錯執行後面的

防禦命令執行漏洞

PHP內建的兩個函式可以有效防止命令執行:

   escapeshellarg() 將給字串增加一個單引號並且能引用或者轉碼任何已經存在的單引號,這樣以確保能夠直接將一個字串傳入 shell 函式,並且還是確保安全的。對於使用者輸入的部分引數就應該使用這個函式。資料參考:http://cn.php.net/manual/zh /function.escapeshellarg.php

   escapeshellcmd() 對字串中可能會欺騙 shell 命令執行任意命令的字元進行轉義。 此函式保證使用者輸入的資料在傳送到 exec() 或 system() 函式,或者 執行操作符 之前進行轉義。資料參考:http://cn.php.net/manual/zh/function.escapeshellcmd.php

  當然,修復方法還有很多方式,修復方式一般有兩種思維:

  1、黑名單:過濾特殊字元或替換字元  2、白名單:只允許特殊輸入的型別/長度

修復程式碼示例一:

<?php
    $target=$_REQUEST['ip'];
    $octet = explode( ".", $target );
    if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
        $target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
        $cmd = shell_exec('ping '.$target);
        echo "<pre>{$cmd}</pre>";
    }
    else {
        echo '<pre>ERROR: You have entered an invalid IP.</pre>';
    }
?>

修復程式碼示例二:

<?php
    $target=$_REQUEST['ip'];
    $cmd = shell_exec('ping '. escapeshellcmd($target));
    echo "<pre>{$cmd}</pre>";
?>

參考連結 :https://www.cnblogs.com/xiaozi/p/7831529.html

                   https://www.jianshu.com/p/1e706f13b088