當(dāng)前位置:首頁 >  IDC >  服務(wù)器 >  正文

SSH中的安全 | 從SSH協(xié)議看身份驗證底層原理

 2022-09-19 12:28  來源: 互聯(lián)網(wǎng)   我來投稿 撤稿糾錯

  域名預(yù)訂/競價,好“米”不錯過

前言

前置關(guān)鍵詞:SSH 客戶端/服務(wù)器,Linux/Unix 系統(tǒng)的用戶賬戶,TCP/IP,Socket。

本文撰于 2022 年 9 月,若相關(guān)內(nèi)容有更新請按照引用鏈接內(nèi)的內(nèi)容為準(zhǔn)。

本文介紹了 SSH 協(xié)議在驗證用戶身份過程中的實現(xiàn)細(xì)節(jié),想幫助讀者更加深入的了解 SSH 客戶端與服務(wù)器的工作過程。也因此,本文可能不適用于指導(dǎo) SSH 服務(wù)器或客戶端的配置。

本文在撰寫中參考了下列內(nèi)容。

SSH 架構(gòu) RFC 4251 The Secure Shell (SSH) Protocol Architecture

SSH 傳輸層協(xié)議 RFC 4253 The Secure Shell (SSH) Transport Layer Protocol

SSH 身份驗證協(xié)議 RFC 4252 The Secure Shell (SSH) Authentication Protocol

SSH 連接協(xié)議 RFC 4254 The Secure Shell (SSH) Connection Protocol

SSH 交互式身份驗證 RFC 4256 Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)

SSH 協(xié)議的結(jié)構(gòu)

SSH 協(xié)議的基本框架

建立一個 SSH 連接,將會經(jīng)過下面幾個過程。

(明文通信)建立 TCP 連接

(明文通信)協(xié)商 SSH 協(xié)議版本 (本質(zhì)上是相互發(fā)送包含版本號的字符串)

服務(wù)器將自己的 SSH 協(xié)議版本發(fā)送到客戶端,格式為:SSH-protoversion(版本號)-softwareversion(自定義) SP(空格一個,可選) comments(注釋,可選) CR(回車) LF(換行)

客戶端將自己的 SSH 協(xié)議版本發(fā)送到服務(wù)器,格式為:SSH-protoversion(版本號)-softwareversion(自定義) SP(空格一個,可選) comments(注釋,可選) CR(回車符) LF(換行符)

(明文通信)協(xié)商密鑰

服務(wù)器發(fā)送公鑰

客戶端和服務(wù)器相互發(fā)送支持的相關(guān)加密算法列表、MAC 算法列表

使用 D-H 算法 生成此后通訊中使用的對稱加密密鑰(會話密鑰)

(密文通信)身份認(rèn)證

(密文通信)正式進(jìn)入應(yīng)用 (如打開 Shell、SFTP、端口轉(zhuǎn)發(fā))

從上面的流程中可以看出,身份驗證過程實際上發(fā)生在 SSH 連接建立之后,此后客戶端與服務(wù)器之間傳輸?shù)拿艽a、密鑰、信息都已經(jīng)受到 SSH 協(xié)議生成的「會話密鑰」加密。

關(guān)于「安全」

SSH 的全稱是「Secure Shell」,安全 Shell。其中的「安全」不是指使用 SSH 就能進(jìn)入一個絕對的安全世界,而是包含了傳輸安全和身份安全。

假設(shè),我正在打電話給身在公司的朋友,詢問一些機(jī)要信息。此時攻擊者就可以剪斷我屋外的電話線,分別接上兩個電話聽筒對聽筒放在一起。我和我的朋友都不會注意到問題,而攻擊者可以從中得知我們之間傳輸?shù)男畔?。這是網(wǎng)絡(luò)中存在的中間人攻擊。

SSH 避免了這個問題,客戶端與服務(wù)器之間的數(shù)據(jù)傳輸經(jīng)過了上面的過程而加密(SSH 傳輸層協(xié)議 RFC 4253)。這個加密是無關(guān)于用戶的賬號密碼的,在事前就完成。無論是網(wǎng)絡(luò)中的交換機(jī)還是跳板機(jī)都無法直接獲取加密前的明文。SSH 保護(hù)了傳輸時的安全。

SSH 也同樣提供了驗證用戶身份的方式,客戶端可以將用戶的密碼發(fā)送至服務(wù)器,以此讓服務(wù)器確認(rèn)用戶的身份,只允許被授權(quán)的訪問連接到服務(wù)器。

SSH 的安全不是絕對的。比如攻擊者拿起剪斷的電話線(中間人攻擊),他依舊可以通過客戶端與服務(wù)器之間的通訊內(nèi)容推測出這是 SSH 連接。SSH 協(xié)議并不能保證連接不被偵測到特征。

身份驗證方式

密碼(Password)

使用密碼登錄是常用且較為便捷的認(rèn)證方式。在配置文件 /etc/ssh/sshd_config 中添加 PasswordAuthentication yes 以開啟密碼登錄。

使用 ssh 命令時提示輸入密碼

通常也認(rèn)為使用密碼登錄是一種較為脆弱的認(rèn)證方式。這不是說使用密碼會造成傳輸時的不安全,而是對密碼本身保存的擔(dān)憂。一般的用戶密碼都是十位或數(shù)十位字符,可能被記錄與紙上或記事本中。即使不是如此,有意義的密碼也容易遭到社會工程攻擊而泄露。

在 /etc/ssh/sshd_config 文件中有時會設(shè)置 PermitRootLogin prohibit-password ,要求系統(tǒng)管理用戶 root 不得使用密碼登錄。

根據(jù) RFC 中的描述,用戶認(rèn)證過程是在連接握手之后的。此時客戶端與服務(wù)器之間已經(jīng)建立起了加密的連接。雙方都會使用握手時交換好的密鑰加密所有傳輸內(nèi)容。后文中的 SSH 數(shù)據(jù)樣式都是被加密傳輸?shù)摹?/p>

登錄時,登錄請求由客戶端發(fā)起。一個名稱為 SSH_MSG_USERAUTH_REQUEST 的消息從客戶端發(fā)出,包含了登錄的用戶名與密碼。

C: byte SSH_MSG_USERAUTH_REQUEST

C: string user name

C: string service name

C: string "password"

C: boolean FALSE

C: string plaintext password in ISO-10646 UTF-8 encoding [RFC3629]

S: byte SSH_MSG_USERAUTH_SUCCESS

若登錄認(rèn)證失敗,服務(wù)器將回復(fù) SSH_MSG_USERAUTH_FAILURE。

基本上,這樣的消息往復(fù)就完成了平時常見的登錄過程。

除此之外,在 RFC 標(biāo)準(zhǔn)中還有一個用于服務(wù)器響應(yīng)密碼登錄請求的消息。

通常,服務(wù)器會成功或失敗地響應(yīng)此消息。但是,如果密碼已過期,服務(wù)器應(yīng)通過 SSH_MSG_USERAUTH_PASSWD_CHANGEREQ 響應(yīng)來指示這一點。在任何情況下,服務(wù)器都不得允許使用過期密碼進(jìn)行身份驗證。

后文介紹的 keyboard-interactive 登錄方式也可以做出密碼過期提示。

公鑰私鑰(Publickey)

在 RFC 標(biāo)準(zhǔn)中,公鑰驗證方式是唯一必須實現(xiàn)的驗證方式(The only REQUIRED authentication)。所有實現(xiàn)都必須(MUST, RFC2119)支持這種方法。在 /etc/ssh/sshd_config 文件中使用 PubkeyAuthentication yes 開啟公鑰驗證方式。

此驗證方式需要用戶先準(zhǔn)備一個非對稱加密的密鑰對,將公鑰保存至 SSH 服務(wù)器的 ~/.ssh/authorized_key 文件中。客戶端登錄時,在本地用私鑰加密某個信息,并將結(jié)果發(fā)送給服務(wù)器,服務(wù)器將通過公鑰驗證收到的密文是否來自指定的用戶。

私鑰通常以加密的形式存儲在客戶主機(jī)上,用戶必須在生成簽名之前提供一個口令(passphrase)。 即使不是這樣,簽名操作也涉及一些昂貴的計算。 為了避免不必要的處理和用戶互動,提供以下信息來查詢使用 "公鑰 "方法的認(rèn)證是否可以接受。

C: byte SSH_MSG_USERAUTH_REQUEST

C: string user name in ISO-10646 UTF-8 encoding [RFC3629]

C: string service name in US-ASCII

C: string "publickey"

C: boolean FALSE

C: string public key algorithm name

C: string public key blob

任何公鑰算法都可以被提供給認(rèn)證使用,如果請求中的算法不被服務(wù)器支持,它必須直接拒絕該請求。

服務(wù)器必須以 SSH_MSG_USERAUTH_FAILURE 或以下方式回應(yīng)該消息。

S: byte SSH_MSG_USERAUTH_PK_OK

S: string public key algorithm name from the request

S: string public key blob from the request

之后,客戶端會使用私鑰加密一個消息(消息的構(gòu)成方式參見 RFC 4252),將結(jié)果發(fā)送給服務(wù)器。下面消息中的 signature 即為加密運算后的內(nèi)容。

C: byte SSH_MSG_USERAUTH_REQUEST

C: string user name

C: string service name

C: string "publickey"

C: boolean TRUE

C: string public key algorithm name

C: string public key to be used for authentication

C: string signature

使用公鑰方式登錄的優(yōu)點是,密鑰對基本不可能被寫在紙上(密鑰是很長的隨機(jī)文本,社會工程攻擊中只能通過更困難的間接方式竊取這么長的內(nèi)容);在網(wǎng)絡(luò)上傳輸、保存的通常是密鑰對的公鑰文件,而非私鑰文件。

更加顯而易見的好處是,私鑰文件是保存在客戶端的計算機(jī)上的。使用 SSH 命令時就無需再反復(fù)輸入密碼。因此網(wǎng)絡(luò)上很多教程使用此方式作為免密碼登錄的方式。與此同時,因為需要預(yù)先將公鑰放在服務(wù)器上(通常是通過網(wǎng)絡(luò)上傳),其也確實不便于配置。

交互式(keyboard-interactive)

在 RFC 文檔中,這個驗證方式被視作是前述方案的一種擴(kuò)展。允許 SSH 客戶端和服務(wù)器在獲取身份驗證信息時進(jìn)行一些交互。如要啟用此方式需在 /etc/ssh/sshd_config 文件中添加 ChallengeResponseAuthentication yes 。通常情況下,這個驗證模式會與系統(tǒng)內(nèi)的 PAM 模塊一同啟用。以此來支持谷歌驗證器(多因素驗證),或其他內(nèi)部身份校驗?zāi)K。

NextSSH 在連接需要交互式驗證的服務(wù)器時的提示

使用交互式驗證可以允許用戶輸入更多的信息,獲得更多的提示內(nèi)容。

從 RFC 中來看,此驗證模式也是從客戶端發(fā)起身份驗證請求開始。

C: byte SSH_MSG_USERAUTH_REQUEST

C: string user name (ISO-10646 UTF-8, as defined in [RFC-3629])

C: string service name (US-ASCII)

C: string "keyboard-interactive" (US-ASCII)

C: string language tag (as defined in [RFC-3066])

C: string submethods (ISO-10646 UTF-8)

當(dāng)服務(wù)器得知客戶端準(zhǔn)備使用 keyboard-interactive 為驗證方式后,服務(wù)器會向客戶端發(fā)出用戶信息請求。在這個來自服務(wù)器的請求中,服務(wù)器將提供提示文本(instruction, prompt)并且為每一個字段(或者稱為詢問)標(biāo)記一個序號(num-prompts)。

S: byte SSH_MSG_USERAUTH_INFO_REQUEST

S: string name (ISO-10646 UTF-8)

S: string instruction (ISO-10646 UTF-8)

S: string language tag (as defined in [RFC-3066])

S: int num-prompts

S: string prompt[1] (ISO-10646 UTF-8)

S: boolean echo[1]

S: ...

S: string prompt[num-prompts] (ISO-10646 UTF-8)

S: boolean echo[num-prompts]

收到來自 SSH 服務(wù)器的請求后,客戶端即可開始向用戶展示界面獲取信息。在使用 ssh 命令時,通常會在終端內(nèi)等待用戶輸入,具有 GUI 的軟件將會展示提示界面。

使用 ssh 命令時提示輸入質(zhì)詢信息

當(dāng)用戶完成輸入后,客戶端即可發(fā)送用戶信息響應(yīng)。

C: byte SSH_MSG_USERAUTH_INFO_RESPONSE

C: int num-responses

C: string response[1] (ISO-10646 UTF-8)

C: ...

C: string response[num-responses] (ISO-10646 UTF-8)

這樣的過程(服務(wù)器請求-用戶輸入-客戶端響應(yīng))可能會重復(fù)多次。例如用戶輸入的密碼錯誤,或者服務(wù)器依據(jù)情況請求了更多的信息。

下面是來自 RFC 文檔中的,客戶端和服務(wù)器之間的兩個交換例子。 第一個例子是用需處理的 Token 進(jìn)行驗證的例子。這是一種其他認(rèn)證方法無法實現(xiàn)的方式。

C: byte SSH_MSG_USERAUTH_REQUEST

C: string "user23"

C: string "ssh-userauth"

C: string "keyboard-interactive"

C: string ""

C: string ""

S: byte SSH_MSG_USERAUTH_INFO_REQUEST

S: string "CRYPTOCard Authentication"

S: string "The challenge is ’14315716’"

S: string "en-US"

S: int 1

S: string "Response: "

S: boolean TRUE

[Client prompts user for password]

C: byte SSH_MSG_USERAUTH_INFO_RESPONSE

C: int 1

C: string "6d757575"

S: byte SSH_MSG_USERAUTH_SUCCESS

第二個例子是一個標(biāo)準(zhǔn)的密碼認(rèn)證。但在此例子中,用戶的密碼已經(jīng)過期。

C: byte SSH_MSG_USERAUTH_REQUEST

C: string "user23"

C: string "ssh-userauth"

C: string "keyboard-interactive"

C: string "en-US"

C: string ""

S: byte SSH_MSG_USERAUTH_INFO_REQUEST

S: string "Password Authentication"

S: string ""

S: string "en-US"

S: int 1

S: string "Password: "

S: boolean FALSE

[Client prompts user for password]

C: byte SSH_MSG_USERAUTH_INFO_RESPONSE

C: int 1

C: string "password"

S: byte SSH_MSG_USERAUTH_INFO_REQUEST

S: string "Password Expired"

S: string "Your password has expired."

S: string "en-US"

S: int 2

S: string "Enter new password: "

S: boolean FALSE

S: string "Enter it again: "

S: boolean FALSE

[Client prompts user for new password]

C: byte SSH_MSG_USERAUTH_INFO_RESPONSE

C: int 2

C: string "newpass"

C: string "newpass"

S: byte SSH_MSG_USERAUTH_INFO_REQUEST

S: string "Password changed"

S: string "Password successfully changed for user23."

S: string "en-US"

S: int 0

[Client displays message to user]

C: byte SSH_MSG_USERAUTH_INFO_RESPONSE

C: int 0

S: byte SSH_MSG_USERAUTH_SUCCESS

申請創(chuàng)業(yè)報道,分享創(chuàng)業(yè)好點子。點擊此處,共同探討創(chuàng)業(yè)新機(jī)遇!

相關(guān)標(biāo)簽
服務(wù)器

相關(guān)文章

熱門排行

信息推薦