Telnel的hontel蜜罐分析
簡介
互聯(lián)網(wǎng)上經(jīng)常有機(jī)器人等爆破telnet嘹锁,ssh弱口令等。如果爆破成功阀湿,則植入病毒等赶熟,為后續(xù)的DDos,遠(yuǎn)控等作準(zhǔn)備陷嘴。本文分析360netlab的hontel蜜罐映砖,并用其部署,捕獲真實(shí)的樣本灾挨。
蜜罐的原理其實(shí)很簡單邑退。模擬一個(gè)真實(shí)的linux系統(tǒng),提供基于telnet的shell操作劳澄。執(zhí)行并記錄每一條命令到日志地技。蜜罐在中病毒木馬后,不會影響真實(shí)的系統(tǒng)秒拔,就像安裝還原卡一樣莫矗,一鍵恢復(fù)到初始話狀態(tài)。
360netlab開源了一個(gè)小巧實(shí)用的蜜罐砂缩,很適合初學(xué)者理解蜜罐的原理作谚。蜜罐基于linux的chroot去限制蜜罐不會影響到真實(shí)機(jī)器。chroot是在unix系統(tǒng)的一個(gè)操作庵芭,針對正在運(yùn)作的軟件進(jìn)程和它的子進(jìn)程妹懒,改變它外顯的根目錄。一個(gè)運(yùn)行在這個(gè)環(huán)境下喳挑,經(jīng)由chroot設(shè)置根目錄的程序彬伦,它不能夠?qū)@個(gè)指定根目錄之外的文件進(jìn)行訪問動(dòng)作滔悉,不能讀取伊诵,也不能更改它的內(nèi)容。chroot這一特殊表達(dá)可能指chroot(2)系統(tǒng)調(diào)用或chroot(8)前端程序回官。由chroot創(chuàng)造出的那個(gè)根目錄曹宴,叫做“chroot監(jiān)獄”(chroot jail,或chroot prison)歉提。
我們的主要目標(biāo)是為了模擬存在弱口令的Iot智能設(shè)備笛坦。此類設(shè)備一般運(yùn)行嵌入式linux(openwrt等),shell為busybox環(huán)境苔巨。所以我們還需要在chroot中安裝busybox文件版扩。還需要建立類似于Iot設(shè)備的文件目錄。推薦直接解壓一個(gè)Iot的固件包即可侄泽。
代碼分析
該蜜罐主要使用python的Tcpserver框架和telnetsrv框架礁芦。只需要繼承telnetsrv框架并重載handler方法。這樣大大降低了開發(fā)難度。
if TELNET_ISSUE:
self.writeline(TELNET_ISSUE)
首先向telnet的客戶端寫入提示信息柿扣。
authenticated = False
for attempt in xrange(MAX_AUTH_ATTEMPTS):
authenticated = self.authentication_ok()
if authenticated:
break
if not authenticated:
return
然后調(diào)用認(rèn)證肖方。這里只需要重寫類變量authNeedUser,authNeedPass即可實(shí)現(xiàn)認(rèn)證方法未状。如果還有特殊需求俯画,可以重載authCallback(self, username, password)
,在里面記錄爆破的username和password等司草。
def authCallback(self, username, password):
if username is not None and password is not None:
self._log("AUTH", "%s:%s" % (username, password))
這樣艰垂,我們就實(shí)現(xiàn)記錄爆破用戶名密碼的功能。
回到handler中埋虹,handler這時(shí)開始調(diào)用self.session_start()
材泄,session_start函數(shù)很簡單,使用subprocess通過busybox開啟一個(gè)shell吨岭。并且使用PIPE的方式去交換數(shù)據(jù)拉宗,也就是執(zhí)行命令。然后設(shè)置為NoneBlock辣辫。
def session_start(self):
self._log("SESSION_START")
self.process = subprocess.Popen(SHELL, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, preexec_fn=os.setsid)
flags = fcntl.fcntl(self.process.stdout, fcntl.F_GETFL)
fcntl.fcntl(self.process.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK)
設(shè)置好shell環(huán)境后旦事,這時(shí)候就可以接收命令了。通過如下代碼獲取用戶用過telnet輸入的命令
line = self.input_reader(self, self.readline(prompt=self.PROMPT).strip())
raw = line.raw
cmd = line.cmd
params = line.params
在蜜罐中急灭,我們主要是記錄用戶輸入的命令內(nèi)容姐浮,如果用戶通過wget等下載一個(gè)文件,我們順便把文件也記錄下來葬馋÷衾穑可以直接調(diào)用self._log("CMD", raw)
即可。針對于wget命令來講畴嘶,我們可以通過正則表達(dá)式匹配到wget后面網(wǎng)址參數(shù)蛋逾,然后下載下來。代碼如下
match = re.search(r"(?i)(wget|curl).+(http[^ >;\"']+)", raw)
if match:
url = match.group(2)
original = posixpath.split(urlparse.urlsplit(url).path)[-1]
filename = self._retrieve_url(url)
通過正則表達(dá)式匹配到下載文件參數(shù)后窗悯,調(diào)用_retrieve_url去下載這個(gè)文件区匣,然后保存下來作為樣本等待研究人員的后續(xù)分析。
所有的流程都結(jié)束后蒋院,我們需要運(yùn)行用戶輸入的這個(gè)命令以便于更好的模擬真實(shí)的linux亏钩。所以我們可以通過如下代碼運(yùn)行
if RUN_ATTACKERS_COMMANDS:
self.process.stdin.write(raw.strip() + "\n")
else:
self.process.stdin.write("\n")
首先判斷蜜罐的配置,是否去允許執(zhí)行命令欺旧,如果允許姑丑,則執(zhí)行raw的內(nèi)容,如果不允許辞友,相當(dāng)于執(zhí)行空命令栅哀。
執(zhí)行完命令后,需要講結(jié)果輸出給用戶,self.write(self._processRead())
昌屉。這里我們需要重載write函數(shù)去實(shí)現(xiàn)自己的邏輯钙蒙。為了保險(xiǎn)起見,運(yùn)行結(jié)果中可能會有關(guān)于該蜜罐的信息间驮。例如X86躬厌,Debian,Ubuntu等竞帽。我們需要講這些信息替換成Iot設(shè)備的信息扛施,例如Mipsel,Openwrt等屹篓。所以我們在write中實(shí)現(xiàn)如下代碼
for key, value in REPLACEMENTS.items():
text = text.replace(key, value)
TelnetHandler.write(self, text)
Replacements主要是一些需要替換的信息
REPLACEMENTS["Ubuntu"] = "Debian"
FAKE_ARCHITECTURE = "arm7"
for arch in ("i386", "i686", "x86_64 x86_64 x86_64", "x86_64 x86_64", "x86_64", "amd64"):
REPLACEMENTS[arch] = FAKE_ARCHITECTURE
至此疙渣,一個(gè)簡易的蜜罐就寫完了。