站長資訊網
最全最豐富的資訊網站

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

前言

前置關鍵詞:SSH 客戶端/服務器,Linux/Unix 系統的用戶賬戶,TCP/IP,Socket。

本文撰于 2022 年 9 月,若相關內容有更新請按照引用鏈接內的內容為準。

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

本文在撰寫中參考了下列內容。

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

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

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

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

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

SSH 協議的結構

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

SSH 協議的基本框架

建立一個 SSH 連接,將會經過下面幾個過程。

(明文通信)建立 TCP 連接

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

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

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

(明文通信)協商密鑰

服務器發送公鑰

客戶端和服務器相互發送支持的相關加密算法列表、MAC 算法列表

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

(密文通信)身份認證

(密文通信)正式進入應用 (如打開 Shell、SFTP、端口轉發)

從上面的流程中可以看出,身份驗證過程實際上發生在 SSH 連接建立之后,此后客戶端與服務器之間傳輸的密碼、密鑰、信息都已經受到 SSH 協議生成的「會話密鑰」加密。

關于「安全」

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

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

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

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

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

身份驗證方式

密碼(Password)

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

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

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

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

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

根據 RFC 中的描述,用戶認證過程是在連接握手之后的。此時客戶端與服務器之間已經建立起了加密的連接。雙方都會使用握手時交換好的密鑰加密所有傳輸內容。后文中的 SSH 數據樣式都是被加密傳輸的。

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

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

若登錄認證失敗,服務器將回復 SSH_MSG_USERAUTH_FAILURE。

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

除此之外,在 RFC 標準中還有一個用于服務器響應密碼登錄請求的消息。

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

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

公鑰私鑰(Publickey)

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

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

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

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

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

服務器必須以 SSH_MSG_USERAUTH_FAILURE 或以下方式回應該消息。

S: byte SSH_MSG_USERAUTH_PK_OK

S: string public key algorithm name from the request

S: string public key blob from the request

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

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

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

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

交互式(keyboard-interactive)

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

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

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

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

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

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)

當服務器得知客戶端準備使用 keyboard-interactive 為驗證方式后,服務器會向客戶端發出用戶信息請求。在這個來自服務器的請求中,服務器將提供提示文本(instruction, prompt)并且為每一個字段(或者稱為詢問)標記一個序號(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 服務器的請求后,客戶端即可開始向用戶展示界面獲取信息。在使用 ssh 命令時,通常會在終端內等待用戶輸入,具有 GUI 的軟件將會展示提示界面。

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

使用 ssh 命令時提示輸入質詢信息

當用戶完成輸入后,客戶端即可發送用戶信息響應。

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)

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

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

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

第二個例子是一個標準的密碼認證。但在此例子中,用戶的密碼已經過期。

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

申請創業報道,分享創業好點子。點擊此處,共同探討創業新機遇!

贊(0)
分享到: 更多 (0)
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
亚洲精品黄色视频在线观看免费资源| 国产精品国产三级专区第1集| 精品一久久香蕉国产线看播放 | 精品视频国产狼人视频| 精品无码久久久久久尤物| 日本精品中文字幕| 中文国产成人精品久久水| 最新国产精品无码| 日韩国产成人精品视频| 麻豆精品不卡国产免费看| 91麻豆国产福利精品| 国产视频精品免费视频| 国内精品九九久久精品| 亚洲精品中文字幕乱码影院| 99re视频精品全部免费| 久9热免费精品视频在线观看| 久久福利青草精品资源站| 97久久精品午夜一区二区| 精品国产一区二区三区2021| 亚洲精品tv久久久久| 四虎国产精品永久地址入口| 日韩福利视频一区| 日韩毛片基地一区二区三区| 日韩亚洲AV无码一区二区不卡| 依依成人精品视频在线观看| 日韩免费高清一级毛片| 国产AV一区二区精品凹凸| 国产亚洲精品美女久久久久| 午夜国产精品久久久久| 亚洲区日韩区无码区| 日韩电影免费在线观看网站 | 国产精品网址在线观看你懂的 | 亚洲AV日韩精品久久久久久| 午夜精品视频在线观看| 99热在线观看精品| 911精品国产亚洲日本美国韩国| 67194老司机精品午夜| 亚洲精品免费在线视频| 四虎精品视频在线永久免费观看| 国产成人精品日本亚洲专一区| 国产精品高清视亚洲精品|