背景
webshell就是以asp、php、jsp或者cgi等網頁文件形式存在的一種命令執行環境,也可以將其稱做為一種網頁后門。黑客在入侵了一個網站后,通常會將asp或php后門文件與網站服務器WEB目錄下正常的網頁文件混在一起,然后就可以使用瀏覽器來訪問asp或者php后門,得到一個命令執行環境,以達到控制網站服務器的目的。
webshell檢測模型
Webshell的運行流程:hacker -> HTTP Protocol -> Web Server -> CGI。簡單來看就是這樣一個順序:黑客通過瀏覽器以HTTP協議訪問Web Server上的一個CGI文件。棘手的是,webshell就是一個合法的TCP連接,在TCP/IP的應用層之下沒有任何特征(當然不是絕對的),只有在應用層進行檢測。黑客入侵服務器,使用webshell,不管是傳文件還是改文件,必然有一個文件會包含webshell代碼,很容易想到從文件代碼入手,這是靜態特征檢測;webshell運行后,B/S數據通過HTTP交互,HTTP請求/響應中可以找到蛛絲馬跡,這是動態特征檢測。
靜態檢測
靜態檢測通過匹配特征碼,特征值,危險函數函數來查找webshell的方法,只能查找已知的webshell,並且誤報率漏報率會比較高,但是如果規則完善,可以減低誤報率,但是漏報率必定會有所提高。優點是快速方便,對已知的webshell查找准確率高,部署方便,一個腳本就能搞定。缺點漏報率、誤報率高,無法查找0day型webshell,而且容易被繞過。對於單站點的網站,用靜態檢測還是有很大好處,配合人工,能快速定位webshell,但是如果是一個成千上萬站點的大型企業呢,這個時候再人肉那工作量可就大了。所以用這樣一種思路:強弱特征。即把特征碼分為強弱兩種特征,強特征命中則必是webshell;弱特征由人工去判斷。加入一種強特征,即把流行webshell用到的特征作為強特征重點監控,一旦出現這樣的特征即可確認為webshell立即進行響應。要解決誤報和漏報,就不能拘泥於代碼級別了。可以換個角度考慮問題:文件系統。我們可以結合文件的屬性來判斷,比如apache是noboy啟動的,webshell的屬主必然也是nobody,如果我的Web目錄無緣無故多了個nobody屬主的文件,這里就有問題了。最理想的辦法是需要制度和流程來建設一個web目錄唯一發布入口,控制住這個入口,非法進來的Web文件自然可以發現。
筆者基於靜態檢測的webshell工具 https://github.com/he1m4n6a/findWebshell
動態檢測
webshell傳到服務器了,黑客總要去執行它吧,webshell執行時刻表現出來的特征,我們稱為動態特征。先前我們說到過webshell通信是HTTP協議。只要我們把webshell特有的HTTP請求/響應做成特征庫,加到IDS里面去檢測所有的HTTP請求就好了。webshell起來如果執行系統命令的話,會有進程。Linux下就是nobody用戶起了bash,Win下就是IIS User啟動cmd,這些都是動態特征。再者如果黑客反向連接的話,那很更容易檢測了,Agent和IDS都可以抓現行。Webshell總有一個HTTP請求,如果我在網絡層監控HTTP,並且檢測到有人訪問了一個從沒反問過得文件,而且返回了200,則很容易定位到webshell,這便是http異常模型檢測,就和檢測文件變化一樣,如果非管理員新增文件,則說明被人入侵了。缺點也很明顯,黑客只要利用原文件就很輕易繞過了,並且部署代價高,網站時常更新的話規則也要不斷添加。還有一個思路利用函數劫持。回憶一下,我們調試網馬的時候,怎么還原它各種稀奇古怪的加密算法呢,簡單,把eval改成alert就好了。類似的,所以我們可以在CGI全局重載一些函數(比如ASP.Net的global.asax文件),當有webshell調用的時候就可以發現異常。已js為例(php,asp等語言思路一樣的,都是保存原函數,然后從新定義原函數,最后在調用保存的原函數),比如下面就是把eval重載,還可以彈出個危險提示等,嚇退一些沒經驗黑客。
<script type="text/javascript"> <!-- var _eval = eval; eval = function(s) { if (confirm("eval被調用\n\n調用函數\n" + eval.caller + "\n\n調用參數\n" + s)) { _eval(s); }
日志檢測
使用Webshell一般不會在系統日志中留下記錄,但是會在網站的web日志中留下Webshell頁面的訪問數據和數據提交記錄。日志分析檢測技術通過大量的日志文件建立請求模型從而檢測出異常文件,稱之為:HTTP異常請求模型檢測。例如:一個平時是GET的請求突然有了POST請求並且返回代碼為200、某個頁面的訪問者IP、訪問時間具有規律性等。
webshell的訪問特征(主要特征)
- 少量ip對其發起訪問
- 總的訪問次數少
- 該頁面屬於孤立頁面
當然不是所有的孤立頁面都是webshell,以下情況也會造成孤立頁面
(1)隱藏管理后台等正常孤立頁面的訪問
(2)掃描器行為,常見漏洞掃描,PoC掃描,Webshell掃描(日志中經常可以看到常見webshell路徑加一句話payload的掃描)——這是最主要的干擾數據,需要剔除
對於情況(1)采用白名單的方式,對於情況(2)掃描器識別
(p.s. 爬蟲技術、指紋識別技術、掃描器識別(廣義的可衍生到人機識別)可以稱為web安全技術的三駕馬車,總也繞不過去)
優點:采用了一定數據分析的方式,網站的訪問量達到一定量級時這種檢測方法的結果具有較大參考價值。
缺點:存在一定誤報,對於大量的訪問日志,檢測工具的處理能力和效率會比較低。
語法檢測
語法語義分析形式,是根據php語言掃描編譯的實現方式,進行剝離代碼、注釋,分析變量、函數、字符串、語言結構的分析方式,來實現關鍵危險函數的捕捉方式。這樣可以完美解決漏報的情況。但誤報上,仍存在問題。
public function startLexing($code) { if (preg_match('/<\?(php)?\s*@Zend;[\r\n|\n]+\d+;/', $code)) { $this->errMsg = 'Encrypt with Zend optimizer.'; return false; } $this->resetErrors(); $this->tokens = token_get_all($code); $this->code = $code; $this->pos = -1; $this->line = 1; return $this->checkError(); }
誤報問題所在,一是被檢測文件是否為合法php語法文件,token_get_all函數的實現,是不驗證是否問合法php語法文件的,只是對其進行掃描,分析。服務器雲判斷是一種根據惡意代碼串的指紋,根據大量后門數據,做語法、語義分析,做業務邏輯分析,理解這段代碼的用途,給出其是否為惡意代碼的定位,而其他使用者,直接可以得到該代碼片段是否為惡意代碼的結果反饋。Pecker Scanner首先是基於語法分析,剝離token、注釋、字符串、變量、語言結構,再進行php語法檢測,提取惡意代碼的掃描工具,來解決漏報問題。同時支持服務器雲判斷,盡量避免誤報問題。基於語法的pecker檢測工具
統計學檢測
webshell由於往往經過了編碼和加密,會表現出一些特別的統計特征,根據這些特征統計學習。
典型的代表: NeoPI -- https://github.com/Neohapsis/NeoPI
NeoPi使用以下五種檢測方法:
- 信息熵(Entropy):通過使用ASCII碼表來衡量文件的不確定性;
- 最長單詞(LongestWord):最長的字符串也許潛在的被編碼或被混淆;
- 重合指數(Indexof Coincidence):低重合指數預示文件代碼潛在的被加密或被混效過;
- 特征(Signature):在文件中搜索已知的惡意代碼字符串片段;
- 壓縮(Compression):對比文件的壓縮比
采用這種檢測方法也存在明顯的弱點,NeoPi的檢測重心在於識別混淆代碼,它常常在識別模糊代碼或者混淆編排的木馬方面表現良好。未經模糊處理的代碼對於NeoPi的檢測機制較為透明。如果代碼整合於系統中的其它腳本之上,這種“正常”的文件極可能無法被NeoPi識別出來。
變形、竊密型webshell檢測
變形webshell可以由上面所說的統計學NeoPI工具檢測,也可以動態檢測。比如,一個正常的程序員如果使用eval、system是不會刻意的轉換隱藏的,如果發現某個函數執行了,代碼中卻找不到這個函數名,我們認為這是一個異常行為。所以變形加密也可以用這種方式查找,在日志中找到某個文件執行system等命令,但在原文件中沒找到這個文件代碼,說明文件是后門文件。
針對竊密型Webshell必須具有操作數據庫的能力,可以引申出一種新的檢測方法,通過分析正常WEB腳本文件和竊密型Webshell對數據庫操作的差異進行分析是本檢測方法所重點研究的方向。正常情況下WEB站點進行數據操作的過程應該是重復性且較為復雜的查詢過程,這種查詢通常精確度非常高,查詢過程不會出現類似於“select * from”這種查詢語句。正常的WEB腳本在進行數據庫操作的過程中也不會出現跨越數據庫查詢的情況,一旦出現這種現象基本可以判斷為非正常的WEB腳本操作過程。
就以上思路設計如下的檢測方案:
- 審計數據操作記錄。通過審計數據庫操作記錄可以單獨的為每一個WEB站點甚至WEB站點中的每一個腳步文件建立查詢請求模型,通過幾天甚至數月的自我學習過程來學習並維護一份查詢請求數據庫。該數據庫的內容包含了每次查詢操作的詳細信息、請求歸類和分析結果。並且建立動態查詢請求規則,Agent一旦檢測到違反該規則的查詢請求后會向Server端傳遞相關信息,Server端再結合其它的掃描過程綜合判斷發起請求的文件是否為Webshell,並最終決定是否向管理員報警。
總結
沒有最好的檢測方法,應該根據實際情況和公司業務合理應用。