Linux

known_hosts ファイル内のハッシュ化されたホスト名(IPアドレス)を自分で算出する

投稿日:

1. はじめに

Linux では /etc/ssh/ssh_config ファイルに、「HashKnownHosts yes」と記述してある場合、known_hosts ファイル内のホスト名(IPアドレス)部分がハッシュ化されます。

/etc/ssh/ssh_config ファイルの例

(省略)
Host *
  (省略)
  HashKnownHosts yes
  (省略)

known_hosts ファイル内の行の例(ハッシュされていない場合)

192.30.253.113 ssh-rsa {公開鍵を表す文字列}

この行がハッシュ化されると以下に変化します。

|1|8V1J9OVTw6LucO4ldA8vUzfBJaE=|kmv/2pGp40XQR7CCuvxqKb3IgnM= ssh-rsa {公開鍵を表す文字列}
  • IPアドレスだった部分が、別の文字列になっています。それ以降の部分に変化はありません。

本記事では、この文字列を自分で算出する方法を紹介します。

2. 実験

とある ~/.ssh/known_hosts ファイルの内容をハッシュ化してみます。

ハッシュ化する前は、以下の行が存在していました。

github.com,192.30.253.113 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==

以下のコマンドを実行することによって、known_hosts ファイル(のホスト名部分)をハッシュ化することができます。

$ ssh-keygen -H -f ~/.ssh/known_hosts

先程の行は以下のようになりました。

|1|R0yjBY6jpUzgTmJU82oSOUjIBLQ=|HCaWOPa5tIlXcNV5Ja99BEd53RA= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
  • github.com,192.30.253.113」だった部分が「|1|R0yjBY6jpUzgTmJU82oSOUjIBLQ=|HCaWOPa5tIlXcNV5Ja99BEd53RA=」に変化しています。
  • この部分は「|」で区切られており、最初の「1」はハッシュ化されていることを表します。
  • 次の「R0yjBY6jpUzgTmJU82oSOUjIBLQ=」はハッシュを算出する際に使うキーで、ソルトとして使われているようです。
  • 最後の「HCaWOPa5tIlXcNV5Ja99BEd53RA=」がハッシュ化された文字列です。

では、ホスト名(IPアドレス)である「github.com,192.30.253.113」と「R0yjBY6jpUzgTmJU82oSOUjIBLQ=」から、「HCaWOPa5tIlXcNV5Ja99BEd53RA=」を求めてみます。

いろいろ調べた結果、SSH HashKnownHosts File FormatA guide and tool for cracking ssh known_hosts files with hashcat に必要なコマンドが記載されていました。

これらの情報を元にして、以下の内容を記述したファイルを作成し、実行権限を与えて実行しました。

#!/usr/bin/sh
set -eu

hexkey=$(echo 'R0yjBY6jpUzgTmJU82oSOUjIBLQ=' | base64 --decode | xxd -p)
echo -n 'github.com' | openssl sha1 -binary -mac HMAC -macopt hexkey:$hexkey | base64
  • ハッシュのアルゴリズムとして HMAC-SHA-1 が利用されているようなので、openssl sha1 コマンドに、-mac HMAC-macopt オプションを指定して実行しています。
  • まず、ハッシュ化する際のキーである文字列を Base64 でデコードし、それを16進数表現にした文字列を変数 hexkey にセットしています。
  • 次の行では、その hexkey をキーとして HMAC-SHA-1 アルゴリズムを利用し、’github.com’ のハッシュを算出して、それを Base64 でエンコードしています。
  • 元の行には、github.com というホスト名だけでなく IPアドレスもありましたが(‘github.com,192.30.253.113’ の部分) 、ここではホスト名しか利用していません。実は IPアドレスをハッシュ化した行は別に生成されています。つまり、ssh-keygen -H コマンドによって、1行が2行になっています。上記の「echo -n ‘github.com’」の部分を「echo -n ‘192.30.253.113’」にすると、生成されるハッシュ値が元の文字列と一致しないので、その行は ‘github.com’ の行だと分かりました(キーも違います)。
  • 元の行のホスト名(IPアドレス)の部分が、「[IPアドレス]:ポート番号」となっている場合は、上記の「echo -n ‘github.com’」の部分を「echo -n ‘[IPアドレス]:ポート番号’」とします。
  • -binary, -mac, -macopt ,プションについては /docs/manmaster/man1/openssl-dgst.html で説明されています。

ここでは calc_hash.sh というファイル名にして実行してみました。

$ ./calc_hash.sh
HCaWOPa5tIlXcNV5Ja99BEd53RA=

想定通りの文字列が出力されました。

3. メモ

  • この仕様はかなり古いために、脆弱な HMAC-SHA-1 というハッシュアルゴリズムが採用されているようです。
  • 本文でもリンクを貼った chris408/known_hosts-hashcat: A guide and tool for cracking ssh known_hosts files with hashcat には、hashcat を使って known_hosts ファイルのハッシュ文字列からIPアドレスを割り出す方法が紹介されています。
  • known_hosts ファイルのホスト名(IPアドレス)がハッシュ化されていると、シェル上でホスト名の補完が効かないために HashKnownHosts を no と設定している環境もあるようです。

4. 参考

📂-Linux
-

執筆者:labo


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

Linux

lessコマンド(バージョン608)を Ubuntu 22.04.1 LTS (WSL) にインストールする

lessコマンド(バージョン608)を Ubuntu 22.04.1 LTS (WSL) にインストールする

Google App Engine

Ubuntu 18.04 (WSL) に、Google Cloud SDK をインストールする

Ubuntu 18.04 (WSL) に、Google Cloud SDK をインストールする手順を紹介します。

Linux

du コマンドのエイリアスをメモ

du コマンドのエイリアスをメモ。

Vim

Vim でファイルを編集した後、sudo でそのファイルを保存する

目次1. 困った状況2. 対応方法3. ~/.vimrc にキーマップを登録する4. 参考 1. 困った状況 Vim でファイルを編集した後に、sudo で開いていないことに気付いた場合の対処法です。 …

Linux

tree コマンドの結果を適切に表示する

tree コマンドの結果を適切に表示する方法を紹介します。