Try   HackMD

查詢 SSH 服務的公鑰指紋 | 維運猿的共同筆記

供登入人員於建立連線時進行驗證,避免遭受中間人攻擊(MitM attack)

https://hackmd.io/@ops-notes-tw/query-ssh-public-key-fingerprints

內容大綱

如服務基於 OpenSSH

檢查方式

伺服器server文字終端text terminal中執行下列任一命令有輸出內容:

  • ps aux | grep --color=always 'sshd: ' | grep --invert-match grep 2>/dev/null
    適用於 GNU Coreutils 之 ps 命令實作
  • ps w | grep 'sshd: ' | grep -v grep 2>/dev/null
    適用於 busybox 之 ps 命令實作。

操作流程

  1. 透過安全的方式(如臨機操作)取得伺服器的命令列操作界面command-line interface

  2. 切換使用者為 root

    附註: 此操作的目的為讓使用者可以存取 SSH 服務的私鑰,其僅對 root 使用者開放存取(您亦可以使用一般使用者身份存取 SSH 公鑰來得出其指紋,但是伺服器未必會建立 SSH 服務的公鑰檔案故其實行可能性非 100% 故未被本文章使用)。

  3. 執行下列命令查詢 SSH 服務的公鑰指紋:

    ​​​​# 如檔名展開(filename expansion)沒有任何結果則不產生輸出(預設行為:保留檔名展開的式樣(expression))
    ​​​​shopt -s nullglob
    ​​​​
    ​​​​for sshd_host_private_key in /etc/ssh/ssh_host_*_key; do
    ​​​​    for fingerprint_algorithm in md5 sha256; do
    ​​​​        ssh-keygen -l -E "${fingerprint_algorithm}" -f "${sshd_host_private_key}"
    ​​​​    done
    ​​​​done
    

    您應可以得到類似下列這樣的命令輸出:

    ​​​​256 MD5:1f:a4:6a:a6:36:f9:a0:0f:7f:64:5d:fe:63:c5:37:92 root@hostname (ECDSA)
    ​​​​256 SHA256:LWq4PlEus50uiiZd3JqCXPHijZX9UGW4L9h5OiBbfkE root@hostname (ECDSA)
    ​​​​256 MD5:93:b6:b5:d1:f8:a0:a3:cd:c1:64:bc:32:01:ac:55:6a root@hostname (ED25519)
    ​​​​256 SHA256:ohr++KpA/+M++vEVYlPDilzgaI8GFCyfykndomKoViQ root@hostname (ED25519)
    ​​​​3072 MD5:96:66:09:2b:ea:7d:eb:b6:28:a5:fa:cc:c7:07:f1:c5 root@hostname (RSA)
    ​​​​3072 SHA256:LLcUaU5fGofvvm6UG9VuOhQ8OjjpqaRTefYubb/c6dM root@hostname (RSA)
    

    每一行輸出的格式為:

    ​​​​_加密位元數_ _雜湊演算法_:_公鑰指紋_ _目標主機註解_ (_金鑰對(keypair)類型_)
    

如服務基於 Dropbear

檢查方式

伺服器server文字終端text terminal中執行下列命令有輸出內容:

ps w | grep 'dropbear' | grep -v grep 2>/dev/null

操作流程

  1. 透過安全的方式(如臨機操作)取得伺服器的命令列操作界面command-line interface

  2. 切換使用者至 root

  3. 執行下列命令查詢 SSH 服務的公鑰指紋:

    ​​​​for dropbear_host_private_key in /etc/dropbear/dropbear_*_host_key; do
    ​​​​    dropbearkey -y -f "${dropbear_host_private_key}"
    ​​​​done
    

    您應可以得到類似下列這樣的命令輸出:

    ​​​​Public key portion is:
    ​​​​ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMlsXJ23hs04RQm3kA4YfYQGqaNxsqfSjAIsy2MTdd01 root@reMarkable
    ​​​​Fingerprint: sha1!! a5:1f:71:ef:46:17:15:05:3f:53:42:8f:3e:1a:74:27:01:d9:ed:c5
    

    輸出的格式如下:

    ​​​​Public key portion is:
    ​​​​ssh-_金鑰對類型_ _公鑰的 Base64 編碼_ _服務註解_
    ​​​​Fingerprint: _產生指紋之雜湊演算法類型_!! _公鑰指紋_
    

    附註:

    如果您使用 OpenSSH 的客戶端軟體應會發現其提示之 SSH 服務端公鑰指紋與此步驟所列舉之指紋不同,這是因為 Dropbear(公鑰雜湊結果的以冒號分隔之十六進位表示法)與 OpenSSH(公鑰雜湊結果的 base64 編碼)軟體採用不同的公鑰指紋表示法之緣故。

    於前述之範例中 OpenSSH 所產生之 SHA-1 金鑰指紋(可使用 ssh-keyscan _SSH 服務主機地址_ 2>/dev/null | ssh-keygen -lf - -E sha1 命令產生)為:

    ​​​​pR9x70YXFQU/U0KPPhp0JwHZ7cU
    

    因其為 27 個字元非 4 的倍數故須根據 Base64 編碼要求後綴一個等號將其手動補完為 28 個字元:

    ​​​​pR9x70YXFQU/U0KPPhp0JwHZ7cU=
    

    然後即可使用下列流水線pipeline命令command將其轉換為 Dropbear 的輸出格式:

    ​​​​printf 'pR9x70YXFQU/U0KPPhp0JwHZ7cU=' \
    ​​​​  | base64 --decode \
    ​​​​  | xxd -plain \
    ​​​​  | sed 's/../&:/g; s/:$//'
    

    命令組成元件component說明:

    • base64 命令的 --decode (-d) 命令選項command option:進行解碼而非編碼操作。
    • xxd 命令的 -plain (-p) 命令選項command option:使用 plain hex dump 風格輸出輸入資料的十六進位表示法hexadecimal representation
    • sed 命令的 s/../&:/g; s/:$// 表達式expression
      • s/../&:/g 搜尋取代(s) sed 命令:從輸入的開頭將任意二字元(..)替換為其自身(&)並後綴一冒號(:);對所有比對到搜尋表達式(..)的字串都進行此操作(g)。
      • s/:$// 搜尋取代(s) sed 命令:將前命令輸出末端之冗餘冒號去掉(替換為空字串)。

    即會產生與 Dropbear 軟體一致之結果:

    ​​​​a5:1f:71:ef:46:17:15:05:3f:53:42:8f:3e:1a:74:27:01:d9:ed:c5
    

參考資料


本作品為《維運猿的共同筆記》的一部分
頁面連結:https://hackmd.io/@ops-notes-tw/query-ssh-public-key-fingerprints
授權條款:https://hackmd.io/@ops-notes-tw/licensing
參與協作視同將您的貢獻內容以相同的授權條款釋出