1. 程式人生 > >漏洞挖掘與防範(進階篇)

漏洞挖掘與防範(進階篇)

今天學習的漏洞挖掘與防範比較好學,而且對於一些使用的存在漏洞的函式實現也是比較順利,所以部落格的進度也加快了,現在我就把學到的東西和大家分享一下。

1.程式碼執行漏洞

程式碼執行漏洞是指應用程式本身過濾不嚴,使用者可以通過請求將程式碼注入到應用中執行。這樣的漏洞如果沒有特殊的過濾,相當於直接有一個web後門的存在,該漏洞主要由eval()、assert()、preg_replace()、call_user_func()、call_user_func_array()、array_map()等函式的引數過濾不嚴格導致,另外還有PHP動態函式($a($b))也是目前出現比較多的。

挖掘經驗
eval()和assert()函式導致的程式碼執行漏洞大多是因為載入快取或者模組以及對變數的處理不嚴格導致;preg_replace()函式的程式碼執行需要存在/e引數,這個函式原本是用來處理字串的,因此漏洞出現最多的是在對字串的處理,比如URL、HTML標籤以及文章內容等過濾功能;call_user_func()和call_user_func_array()函式的功能是呼叫函式,多用在框架裡面動態呼叫函式;array_map()函式的作用是呼叫函式並且處第一個引數外其他引數為陣列,通常會寫死第一個引數。
除了上面這些函式導致的程式碼執行漏洞,還有一類非常常見的動態函式的程式碼執行,寫法如下:
$_GET($_POST[“xx”])
基於這種寫法變形出來的各種異形,經常被用來當做web後門使用。

程式碼執行函式
PHP程式碼執行有多種利用方式,但目前見得最多的是由於函式的使用不當導致的,有eval()、assert()、preg_replace()、call_user_func()、call_user_func_array()、array_map()等函式。

(I)eval和assert函式
這兩個函式的作用就是用來動態執行程式碼,測試程式碼如下:

在瀏覽器輸入http://localhost/ev.php,測試結果如下:

PS:eval和assert函式執行結果相同。

(II)preg_replace函式
preg_replace函式的作用是對字串進行正則處理。
看下面一段程式碼:
mixed preg_replace(mixed $pattern,mixed $replacement,mixed $subject [,int $limit=-1 [, int $count]])
這段程式碼的含義是搜尋$subject中匹配$pattern部分,以$replacement進行替換,而當$pattern處即第一個引數存在e修飾時,$replacement會被當成程式碼來執行。

我們來看一個最簡單的例子:

正則的意思是從$_GET[str]變數裡搜尋括號[]中間的內容作為第一組結果,preg_replace()函式第二個引數為’\1’代表這裡用第一組結果填充。
在瀏覽器輸入http://localhost/pr.php?str=[phpinfo()],結果如下圖所示:

(III)呼叫函式過濾不嚴
call_user_func()和array_map()等數十個函式有呼叫其他函式的功能,其中的一個引數作為要呼叫的函式名,那如果這個傳入的函式名可控,那就可以呼叫以外的函式來執行我們想知道的程式碼,也就是存在程式碼執行漏洞。
測試程式碼如下:

在瀏覽器輸入http://localhost/ca.php?a=assert,當請求ca.php?a=assert,呼叫了assert函式,並且將phpinfo()作為引數傳入,測試結果如下:


動態函式執行
由於PHP的特性原因,PHP的函式可以直接由字串拼接,這導致了PHP在安全上的控制又加大了難度,比如增加了漏洞數量和提高了PHP後門的查殺難度。
PHP動態函式寫法為“變數”,我們來看一個動態函式後門的寫法:

程式碼的意思是接收GET請求的a引數,作為函式,b引數作為函式的引數。
在瀏覽器輸入http://localhost/do.php?a=assert&b=phpinfo(),結果如下:

要挖掘這種形式的程式碼執行漏洞,需要找可控的動態函式名。

看下面程式碼:
‘$var[\’\1\’]=”\2”;’
程式碼意思是吧正則匹配出來的引數1初始化到$var變數中,並且賦值為引數2的值,問題是這段程式碼在賦值的時候使用的是雙引號(”),在php中,如果字串使用雙引號括起來,中間的變數是會正常解析的,測試程式碼如下:

在瀏覽器輸入,結果如下:

漏洞防範
採用引數白名單過濾,我們可以結合正則表示式來進行白名單限制。

2.命令執行漏洞

程式碼執行漏洞指得是可以執行PHP指令碼程式碼,而命令執行漏洞指的是可以執行系統或者應用指令(入CMD命令或者bash命令)的漏洞,PHP的命令執行漏洞主要是基於一些函式的引數過濾不嚴導致,可以執行命令的函式有system()、exec()、shell_exec()、passthru()、pcntl_exec()、popen()、proc_open(),另外反引號(`)也可以執行命令。PHP執行命令使繼承Webserver使用者的許可權,這個使用者一般都有許可權向web目錄寫檔案。

挖掘經驗
命令執行漏洞最多出現在包含環境包的應用裡,類似於eyou(億郵)這類產品,直接在系統安裝即可啟動自帶的Web服務和資料庫服務。Web應用服務會有比較多的點之間使用system()、exec()、shell_exec()、passthru()、pcntl_exec()、popen()、proc_open()等函式執行系統命令來呼叫指令碼,用得多了難免會出現漏洞。

命令執行函式
函式system()、exec()、shell_exec()、passthru()以及反引號(`)是可以直接傳入命令並且函式會返回執行結果。
測試程式碼如下:

在瀏覽器輸入http://localhost/sy.php,有結果可以看到執行結果輸出了當前WebServer使用者

pcntl是PHP的多程序處理擴充套件,在處理大量任務的情況下會使用得到,使用pcntl需要額外安裝,它的函式說明如下:void pcntl_exec(string $path [, array $args[, array $envs ]])
其中$path為可執行程式路徑,如果是perl或者Bash指令碼,則需要在檔案頭加上#!/bin/bash來標識可執行程式路徑。

popen()、proc_open()函式不會直接返回執行結果,而是返回一個檔案指標。下面我們看看popen()函式的用法,它需要兩個引數,一個是執行的命令,另外一個是指標檔案的連線模式,有r和w表示讀和寫,測試程式碼如下:

在瀏覽器輸入

執行完成後,開啟D盤目錄看到1.txt檔案,內容為WebServer使用者名稱,截圖如下:

反引號命令執行
反引號也可以執行命令,寫法很簡單,實際上反引號執行命令是呼叫的shell_exec()函式。測試程式碼如下:

在瀏覽器輸入http://localhost/y.php,正常情況輸出的結果如下:

當我們在php.ini配置檔案中把PHP安全模式開啟

在重啟WebServer重新載入PHP配置檔案,在瀏覽器輸入http://localhost/y.php,結果如下:

這個提示說明反引號執行命令的方式是使用的shell_exec()函式。

漏洞防範
(I)防注入函式
關於命令執行漏洞的防範大概有兩種方式:一種是使用PHP再帶的命令方注入函式,包括escapeshellcmd()和escapeshellarg(),其中escapeshellcmd()是過濾的整條命令,所以它的引數是一整條命令,escapeshellarg()函式則是用來保證傳入命令執行函式裡面的引數確實是以字串引數形式存在的,不能被注入。
測試程式碼如下:

在瀏覽器輸入,結果如下:

escapeshellarg()函式的功能是過濾引數,將引數限制在一對雙引號裡,確保引數為一個字串,因此它會把雙引號替換為空格,測試程式碼如下:

在瀏覽器輸入,結果如下:

(II引數白名單)
引數白名單方式在大多數由於引數過濾不嚴產生的漏洞中都很好用,是一種通用修復方法。