取證分析之 OpenSSH Session 信息解密

luochicun
在協(xié)商加密算法并生成session密鑰之前,SSH框架將不被加密,并且即使加密了該框架,根據(jù)算法的不同,部分框架可能也不會(huì)被加密。例如,aes256-gcm不會(huì)對(duì)框架中的4個(gè)字節(jié)長(zhǎng)度進(jìn)行加密,但是chacha20-poly1305會(huì)進(jìn)行加密。

不久前,我們遇到了一個(gè)取證案例,一個(gè)Linux服務(wù)器被攻破,一個(gè)修改過(guò)的OpenSSH二進(jìn)制文件被加載到一個(gè)web服務(wù)器的內(nèi)存中。修改后的OpenSSH二進(jìn)制文件被攻擊者用作系統(tǒng)的后門(mén)。在系統(tǒng)遭到破壞時(shí),客戶擁有pcap和系統(tǒng)的虛擬機(jī)監(jiān)控程序截圖。根據(jù)這個(gè)發(fā)現(xiàn),我們開(kāi)始懷疑是否有可能通過(guò)從內(nèi)存截圖中恢復(fù)密鑰材料來(lái)解密SSH session并獲得有關(guān)它的知識(shí)。在本文中,我將介紹我對(duì)OpenSSH所做的研究,并發(fā)布一些從內(nèi)存中轉(zhuǎn)儲(chǔ)OpenSSHsession密鑰的工具,并結(jié)合使用pcap解密和解析session,另外我還向2020 Volatility framework plugin contest提交了我的研究成果。

SSH協(xié)議

首先,我會(huì)閱讀OpenSSH及其工作原理。幸運(yùn)的是,OpenSSH是開(kāi)源的,因此我們可以輕松下載和閱讀實(shí)現(xiàn)細(xì)節(jié)。RFC的內(nèi)容,雖然讀起來(lái)有點(diǎn)枯燥,但也包含了豐富的信息。從較高的層次來(lái)看,SSH協(xié)議如下所示:

1.SSH協(xié)議+軟件版本交換;

2.算法協(xié)商(KEX INIT):

2.1密鑰交換算法;

2.2加密算法;

2.3MAC算法;

2.4壓縮算法;

3.密鑰交換;

4.用戶認(rèn)證;

5.客戶請(qǐng)求“session”類(lèi)型的頻道;

6.客戶端請(qǐng)求一個(gè)偽終端;

7.客戶端與session進(jìn)行交互;

一開(kāi)始,客戶端就會(huì)連接到服務(wù)器并發(fā)送協(xié)議版本和軟件版本:

SSH-2.0-OpenSSH_8.3,服務(wù)器以其協(xié)議和軟件版本進(jìn)行響應(yīng)。交換初始協(xié)議和軟件版本后,所有流量都封裝在SSH框架中。SSH框架主要存在于框架的長(zhǎng)度、填充長(zhǎng)度、有效載荷數(shù)據(jù)、填充內(nèi)容和MAC中。SSH框架示例如下:

2345截圖20200908083720.png

使用dissect.cstruct解析的SSH框架示例

在協(xié)商加密算法并生成session密鑰之前,SSH框架將不被加密,并且即使加密了該框架,根據(jù)算法的不同,部分框架可能也不會(huì)被加密。例如,aes256-gcm不會(huì)對(duì)框架中的4個(gè)字節(jié)長(zhǎng)度進(jìn)行加密,但是chacha20-poly1305會(huì)進(jìn)行加密。

接下來(lái),客戶端將向服務(wù)器發(fā)送KEX_INIT消息,以開(kāi)始協(xié)商session的參數(shù),例如密鑰交換和加密算法。根據(jù)這些算法的順序,客戶端和服務(wù)器將選擇雙方都支持的第一個(gè)首選算法。在KEX_INIT消息之后,交換幾個(gè)與密鑰交換相關(guān)的消息,然后雙方互相發(fā)送NEWKEYS消息。這個(gè)消息會(huì)告訴另一方一切都準(zhǔn)備好開(kāi)始加密session,并且流程中的下一個(gè)框架將被加密。在雙方都獲得新的加密密鑰生效后,客戶端將請(qǐng)求用戶身份驗(yàn)證,并根據(jù)服務(wù)器上配置的身份驗(yàn)證機(jī)制執(zhí)行基于密碼/密鑰/等的身份驗(yàn)證。通過(guò)session身份驗(yàn)證后,客戶端將打開(kāi)一個(gè)通道,并根據(jù)請(qǐng)求的操作(ssh/sftp/scp等)通過(guò)該通道請(qǐng)求服務(wù)。

恢復(fù)session密鑰

恢復(fù)session密鑰的第一步是分析OpenSSH源代碼并調(diào)試現(xiàn)有的OpenSSH二進(jìn)制文件,我嘗試自己編譯OpenSSH,將生成的session密鑰記錄在某個(gè)地方,并附加一個(gè)調(diào)試器,然后在程序的內(nèi)存中搜索這些密鑰。成功以后,session密鑰保存在堆中的內(nèi)存中。對(duì)源代碼的更多深入研究使我了解了負(fù)責(zé)發(fā)送和接收NEWKEYS框架的函數(shù)。我發(fā)現(xiàn)有一個(gè)存儲(chǔ)“session_state”結(jié)構(gòu)的“ssh”結(jié)構(gòu),該結(jié)構(gòu)又包含與當(dāng)前SSHsession有關(guān)的所有信息,包括一個(gè)newkeys結(jié)構(gòu),其中包含與加密、mac和壓縮算法有關(guān)的信息。經(jīng)過(guò)深入研究,我們最終找到了包含密碼名稱、密鑰、IV和塊長(zhǎng)度的“shenc”結(jié)構(gòu)。OpenSSH的結(jié)構(gòu)概述如下所示:

2345截圖20200908083720.png

SSHENC的結(jié)構(gòu)和關(guān)系

以及shenc結(jié)構(gòu)的定義:

2345截圖20200908083720.png

SSHENC結(jié)構(gòu)

很難在內(nèi)存中找到密鑰本身(因?yàn)樗皇且粋€(gè)隨機(jī)字節(jié)的字符串),但是shenc和其他結(jié)構(gòu)更加獨(dú)特,具有一些我們可以驗(yàn)證的屬性。然后,我們可以抓取程序的整個(gè)內(nèi)存地址空間,并驗(yàn)證針對(duì)這些約束的每個(gè)偏移量。我們可以檢查以下屬性:

1.名稱,密碼,密鑰和iv成員都是有效的指針;

2.name成員指向一個(gè)有效的密碼名,該密碼名稱等于cipher->name;

3.key_len在有效范圍內(nèi);

4.iv_len在有效范圍內(nèi);

5.block_size在有效范圍內(nèi);

如果我們針對(duì)所有這些約束進(jìn)行驗(yàn)證,那么應(yīng)該能夠可靠地找到shenc結(jié)構(gòu)。為此,我開(kāi)始構(gòu)建一個(gè)POC Python腳本,該腳本可以在一個(gè)實(shí)時(shí)主機(jī)上運(yùn)行,該主機(jī)連接到進(jìn)程并為該結(jié)構(gòu)勾勒出內(nèi)存??梢栽谶@里找到此腳本的源代碼,它實(shí)際上工作得很好,并為找到的每個(gè)密鑰輸出一個(gè)json blob。因此,我演示了可以使用Python和ptrace從活動(dòng)主機(jī)中恢復(fù)session密鑰,但是我們?nèi)绾螐膬?nèi)存截圖中恢復(fù)session密鑰呢?這就是Volatility發(fā)揮作用的地方。Volatility是一個(gè)用Python編寫(xiě)的內(nèi)存取證框架,可以編寫(xiě)自定義插件。經(jīng)過(guò)一些努力,我能夠編寫(xiě)Volatility 2插件,并且能夠分析內(nèi)存截圖并轉(zhuǎn)儲(chǔ)session密鑰!對(duì)于Volatility 3 plugin contest,我還將該插件移植到了Volatility 3,并提交了該插件并進(jìn)行了研究。

2345截圖20200908083720.png

Volatility 2 SSH Session密鑰轉(zhuǎn)儲(chǔ)器的輸出結(jié)果

解密和解析流量

用于加密和解密通信的session密鑰的恢復(fù)是成功的,接下來(lái)是解密通信流量!我開(kāi)始用pynids(TCP解析和重組庫(kù))解析一些pcap。我使用內(nèi)部開(kāi)發(fā)的dissect.cstruct庫(kù)解析數(shù)據(jù)結(jié)構(gòu),并開(kāi)發(fā)了解析框架來(lái)解析ssh等協(xié)議。解析框架基本上以正確的順序?qū)?shù)據(jù)包送入?yún)f(xié)議解析器,因此,如果客戶端發(fā)送2個(gè)數(shù)據(jù)包,而服務(wù)器響應(yīng)3個(gè)數(shù)據(jù)包,則這些數(shù)據(jù)包也將以相同的順序提供給解析器。這對(duì)于保持整體協(xié)議狀態(tài)很重要,解析器基本上使用SSH框架,直到遇到NEWKEYS框架為止,這表明下一框架已加密?,F(xiàn)在,解析器從該源中窺視流中的下一框架,并迭代提供的session密鑰,以嘗試解密該框架。如果成功,解析器將以該狀態(tài)安裝session密鑰以解密session中的其余框架,解析器幾乎可以處理OpenSSH支持的所有加密算法,具體過(guò)程可以查看以下動(dòng)圖:

2345截圖20200908083720.png

SSH協(xié)議解析

最后是運(yùn)行中的解析器,你可以在其中看到解密和解析SSHsession的過(guò)程,還暴露了用戶用于身份驗(yàn)證的密碼:

2345截圖20200908083720.png

解密和解析的SSHsession示例

總結(jié)

本文我研究了SSH協(xié)議,以及如何將session密鑰存儲(chǔ)并保存在OpenSSH的內(nèi)存中,并找到了一種從內(nèi)存中提取它們并在網(wǎng)絡(luò)解析器中使用它們來(lái)解密SSH會(huì)話并將其解析為可讀輸出的方法。本研究中使用的腳本可以在以下鏈接中找到:

將Python POC轉(zhuǎn)儲(chǔ)為SSHsession密鑰;

Volatility 2插件;

Volatility 3插件;

SSH協(xié)議解析器;

更好的選擇將是在Wireshark中實(shí)現(xiàn)這個(gè)解密器和解析器。

有趣的是,在研究期間,我還在OpenSSH源代碼的ssh_set_newkeys函數(shù)中遇到了這些注釋行。其實(shí)這很諷刺,如果不對(duì)這些行進(jìn)行注釋并在OpenSSH二進(jìn)制文件中進(jìn)行編譯,那么這項(xiàng)研究就會(huì)困難得多。

2345截圖20200908083720.png

OpenSSH源代碼片段

本文翻譯自:https://research.nccgroup.com/2020/11/11/decrypting-openssh-sessions-for-fun-and-profit/

THEEND

最新評(píng)論(評(píng)論僅代表用戶觀點(diǎn))

更多
暫無(wú)評(píng)論