您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何進行OpenSSH用戶枚舉漏洞CVE-2018-15473分析,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
這個漏洞雖然不能生成有效用戶名列表,但是它可以允許攻擊者猜測用戶名。目前這個OpenSSH用戶枚舉漏洞(CVE-2018-15473)的詳細信息已經上傳至了GitHub,感興趣的同學可以自行查看【傳送門】。
在這篇文章中,我們將對該漏洞進行深入分析,并提供一些可行的緩解方案。
這個漏洞存在于OpenSSH所實現的一些認證功能之中,首先我們一起看一看Ubuntu OpenSSH的公共密鑰認證漏洞。
通過向一臺OpenSSH服務器發送惡意的公共密鑰認證消息,攻擊者將能夠獲取特定的用戶名信息。如果用戶不存在,服務器將會向客戶端發送認證失敗的消息。如果用戶存在,消息將無法解析并終止通信,即通信連接會在沒有任何消息回傳的情況下斷開。關于該漏洞的漏洞利用代碼可以從這個Python PoC腳本中獲取:【傳送門】。
這個漏洞之所以存在,是因為服務器在對消息完整解析之前,用戶查詢了不存在的用戶名。想要修復該漏洞也很簡單,按攻擊邏輯反著來就行了:首先對消息進行完整解析,然后再建立通信連接。
測試漏洞利用PoC的一種方法就是在調試模式下開啟OpenSSH服務器:
然后用已存在的有效用戶名運行PoC腳本:
在服務器端將會查看到錯誤提示:
相關錯誤信息還可以在/var/log/auth.log中找到:
如果無法正確解析消息,會導致客戶端跟服務器端之間的通信中斷,而且中斷時不會收到服務器發送的提示信息:
注意粉紅色標記的最后一個數據包(客戶端數據包),這里沒有后續的藍色數據包(服務器數據包)。
當PoC腳本以不存在的用戶名運行之后:
不會彈出“imcomplete message”錯誤提示:
注意通信數據結尾處的藍色服務器數據包。
這就是該漏洞(公共密鑰認證漏洞)暴露有效用戶名的整個流程了。
其中,userauth_pubkey函數是認證功能所實現的其中一個函數,專門用于根據公共密鑰來完成身份驗證。如果認證失敗,則返回“0”,成功則返回“1”。當服務器端接收到了SSH2_MSG_USERAUTH_REQUEST請求后,便會調用該函數,之后的結果會用來給客戶端回傳SSH2_MSG_USERAUTH_FAILURE或SSH2_MSG_USERAUTH_SUCCESS消息。
該函數的運行邏輯為:
1. 如果用戶名不存在:返回“0”;
2. 如果用戶名存在但密鑰錯誤:返回“0”;
3. 如果用戶名存在且密鑰正確:返回“1”;
但是有人發現,我們竟然可以在第一步和第二步中間終止userauth_pubkey函數的運行。第一步執行完后,userauth_pubkey函數會從客戶端獲取消息字符串,如果獲取失敗(惡意字符串導致),整個過程都會終止,并在不發送任何回傳消息的情況下關閉連接。
packet_get_string所導致的情況如下:
如果用戶名存在,第一步會在程序從消息域中提取完數據后進行。
第一個提取的數據域是一個布爾值(1字節),對應函數為packet_get_char()。如果認證類型為publickey,返回值就是“1”。后續跟著的是兩個字符串:算法和密鑰。在SSH消息中,字符串會以一個“長度-值“鍵值對進行編碼,一個字符串為4個字節。
函數packet_get_string可以從消息中提取字符串,并對其進行驗證,這個函數還需要依賴另一個函數:ssh_ssh_packet_get_string。
ssh_packet_get_string函數會調用sshpkt_get_string函數,如果返回的值不是“0”,它還會調用fatal函數。函數fatal會記錄致命的錯誤事件,然后終止生成的OpenSSH進程(不回傳任何錯誤信息)。
接下來會執行sshpkt_get_string函數并調用sshbuf_get_string函數:
然后sshbuf_get_string函數會調用sshbuf_get_string_direct:
然后sshbuf_get_string_direct會調用sshbuf_peek_string_direct:
最后,sshbuf_peek_string_direct會進行字符串驗證:
如果消息中剩余數據小于4字節,或者說消息中的剩余數據小于字符串長度,則會返回SSH_ERR_MESSAGE_INCOMPLETE 錯誤消息。這就是我們之前那個Python PoC腳本所要觸發的東西。首先,它會跟OpenSSH服務器建立一條加密的通信鏈接,然后向其發送惡意的SSH2_MSG_USERAUTH_REQUEST消息。通過重定義add_boolean函數,消息中的布爾值域會被忽略。
當函數userauth_pubkey解析了惡意消息之后,首先會讀取布爾值域,由于這個域其實是不存在的,因此讀取的會是下一個域(函數packet_get_char):加密算法字符串的4字節長度值。然后調用下一個函數packet_get_string來讀取加密算法字符串。
下面是解析合法消息的過程:
下面是解析惡意消息的過程:
結果就是,代碼解析了一個1907字節的字符串(十六進制為0x00000773),這比整個消息的長度還要長,這會導致ssh_packet_get_string調用fatal函數,并中斷OpenSSH進程。
這是一個非常隱蔽的漏洞,它不是一個緩沖區溢出漏洞,也不是遠程代碼執行漏洞,更不是錯誤輸入驗證漏洞。這里不存在任何的緩沖區溢出問題,所有的輸入都在使用之前進行了驗證。問題就是,輸入驗證是在進行了一些函數處理之后完成的。
問題的解決方法也比較簡單:更換函數的調用順序即可,也就是首先進行輸入驗證,然后再進行函數處理就可以了。
上述內容就是如何進行OpenSSH用戶枚舉漏洞CVE-2018-15473分析,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。