SSH接続を行う際、~/.ssh/known_hosts
ファイルは重要な役割を果たします。このファイルには、過去に接続したリモートホストの公開鍵が保存されており、中間者攻撃(Man-in-the-Middle attack)を防ぐのに役立ちます。しかし、このファイル自体が攻撃者の手に渡った場合、どのような情報が漏洩する可能性があるのでしょうか?特に、ホスト名がハッシュ化されている場合、known_hosts2john
というツールがその解読を試みるために使用されます。
このブログ記事では、John the Ripper スイートに含まれる known_hosts2john
の機能、使い方、そして関連するセキュリティ上の考慮事項について詳しく解説します。
1. known_hosts ファイルとは? 🤔
SSH (Secure Shell) を使用してリモートサーバーに初めて接続すると、通常、次のようなメッセージが表示されます。
The authenticity of host 'example.com (192.168.1.100)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
ここで yes
と応答すると、接続先サーバーの公開鍵(この例では ECDSA 鍵)がローカルマシンの ~/.ssh/known_hosts
ファイルに記録されます。次回以降、同じサーバーに接続する際には、サーバーが提示する公開鍵がこのファイルに記録されているものと一致するかどうかをSSHクライアントが検証します。もし鍵が異なっていた場合、警告が表示され、接続が中間者によって傍受されている可能性を示唆します。
known_hosts の形式
known_hosts
ファイルの各行は、通常以下の形式で記述されます。
[マーカー] ホスト名パターン[,ホスト名パターン...] 鍵タイプ ベース64エンコードされた公開鍵 [コメント]
- マーカー (オプション):
@cert-authority
や@revoked
など、特定の意味を持つマーカーが付くことがあります。 - ホスト名パターン: 接続先のホスト名、IPアドレス、またはワイルドカードを含むパターン。カンマ区切りで複数指定できます。
- 鍵タイプ:
ssh-rsa
,ecdsa-sha2-nistp256
,ssh-ed25519
など、公開鍵のアルゴリズムを示します。 - ベース64エンコードされた公開鍵: サーバーの公開鍵本体です。
- コメント (オプション): 通常は空です。
例:
example.com,192.168.1.100 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBB...
2. HashKnownHosts オプションとホスト名のハッシュ化 🔒
known_hosts
ファイルには接続先のホスト名やIPアドレスが平文で記録されるため、このファイルが漏洩すると、ユーザーがどのサーバーにアクセスしているかが第三者に知られてしまう可能性があります。これを防ぐために、SSHクライアントの設定 (~/.ssh/config
または /etc/ssh/ssh_config
) に HashKnownHosts
というオプションがあります。
Host *
HashKnownHosts yes
この設定を有効にすると、known_hosts
ファイルに新しいホストエントリを追加する際、ホスト名とIPアドレスがハッシュ化されて保存されます。ハッシュ化されたエントリは以下のような形式になります。
|1|base64(salt)|base64(hash) ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA...
|1|
: ハッシュ形式のマーカー。base64(salt)
: ハッシュ計算時に使用されたソルト(ランダムな値)。base64(hash)
: ソルトとホスト名/IPアドレスから計算されたHMAC-SHA1ハッシュ値。
このハッシュ化により、ファイルの内容を見ただけでは元のホスト名を特定することが困難になります。SSHクライアントは接続時に、指定されたホスト名と保存されているソルトを使ってハッシュ値を計算し、ファイル内のハッシュ値と一致するかどうかを確認します。
3. known_hosts2john の登場 ✨
known_hosts2john
は、パスワードクラッキングツールである John the Ripper (JtR) スイートの一部として提供されるユーティリティスクリプトです。その主な目的は、HashKnownHosts yes
によってハッシュ化された known_hosts
ファイルのエントリから、John the Ripper が解読できる形式のハッシュ値を抽出することです。
これにより、攻撃者やペネトレーションテスターは、漏洩した known_hosts
ファイルから元のホスト名やIPアドレスを特定しようと試みることができます。これは、ターゲットとなる可能性のある内部ネットワークのサーバーや、ユーザーが頻繁にアクセスする重要なシステムを明らかにするのに役立つ場合があります。
入手方法と場所
known_hosts2john
は通常、John the Ripper をインストールすると、そのディレクトリ内の run
(または ../run
) ディレクトリに配置されます。John the Ripper の “bleeding-jumbo” ブランチ (GitHub などで開発中の最新版) に含まれていることが多いです。
John the Ripper がインストールされていれば、以下のコマンドでツールの一覧を確認でき、その中に known_hosts2john
が含まれているか確認できます。
cd /path/to/john/run
./john --list=tools
もし見つからない場合は、John the Ripper (bleeding-jumbo) をソースからコンパイルするか、パッケージマネージャー(例: Kali Linux の apt install john
)で提供されているバージョンを確認してください。
4. known_hosts2john の使い方 ⚙️
known_hosts2john
の使い方は非常にシンプルです。基本的には、対象となる known_hosts
ファイルを引数として与えるだけです。
基本構文
/path/to/john/run/known_hosts2john [path/to/known_hosts] > output_hashes.txt
/path/to/john/run/known_hosts2john
:known_hosts2john
スクリプト(通常はPythonスクリプト)へのパスを指定します。環境によっては単にknown_hosts2john
で実行できる場合もあります。[path/to/known_hosts]
: ハッシュを抽出したいknown_hosts
ファイルのパスを指定します。省略した場合、標準入力から読み込もうとします。> output_hashes.txt
: 抽出されたハッシュ値をoutput_hashes.txt
というファイルに保存します。このファイル名を John the Ripper に渡します。
実行例
まず、ハッシュ化されたエントリを含む known_hosts
ファイルの例を見てみましょう (~/.ssh/my_known_hosts_hashed
という名前だとします)。
# ~/.ssh/my_known_hosts_hashed
|1|abcdefghijklmnop==|qrstuvwxyzabcdef== ssh-rsa AAAAB3...
|1|ABCDEFGHIJKLMNOP==|QRSTUVWXYZABCDEF== ssh-ed25519 AAAAC3...
# 通常の(ハッシュ化されていない)エントリも混在可能
server1.example.com ssh-rsa AAAAB3...
次に、このファイルに対して known_hosts2john
を実行します。
cd /path/to/john/run
./known_hosts2john ~/.ssh/my_known_hosts_hashed > known_hosts_hashes.txt
実行後、known_hosts_hashes.txt
ファイルには以下のような内容が出力されます。
$known_hosts$1*abcdefghijklmnop==*qrstuvwxyzabcdef==
$known_hosts$1*ABCDEFGHIJKLMNOP==*QRSTUVWXYZABCDEF==
各行は John the Ripper が認識できるハッシュ形式になっています。
$known_hosts$
: ハッシュタイプを示すプレフィックス。1
: ハッシュ形式のバージョン(現在は1のみ)。abcdefghijklmnop==
: Base64エンコードされたソルト。qrstuvwxyzabcdef==
: Base64エンコードされたハッシュ値 (HMAC-SHA1)。
known_hosts2john
は、ハッシュ化されていない行は無視し、ハッシュ化された行のみを処理して出力します。
5. John the Ripper によるハッシュ解読 🔓
known_hosts2john
によって抽出されたハッシュファイル (例: known_hosts_hashes.txt
) ができたら、いよいよ John the Ripper を使って元のホスト名/IPアドレスの解読を試みます。
解読には、辞書ファイル(ホスト名やIPアドレスのリスト)やブルートフォース(総当たり攻撃)が用いられます。SSHの HashKnownHosts
は HMAC-SHA1 を使用しており、比較的計算が高速なため、適切な辞書があれば解読できる可能性があります。
辞書攻撃
一般的なホスト名、ドメイン名、よく使われるIPアドレス範囲などをリスト化した辞書ファイル (例: hostlist.txt
) を用意し、John the Ripper に指定します。
/path/to/john/run/john --wordlist=hostlist.txt --format=known_hosts known_hosts_hashes.txt
--wordlist=hostlist.txt
: 使用する辞書ファイルを指定します。--format=known_hosts
: John the Ripper に、処理するハッシュの形式がknown_hosts
であることを明示的に伝えます。これにより、他の形式のハッシュと混同するのを防ぎます。known_hosts_hashes.txt
:known_hosts2john
で生成したハッシュファイル。
インクリメンタルモード(ブルートフォース)
特定の文字種(例: IPアドレスなら数字とドット)で総当たり攻撃を試みることもできますが、ホスト名の場合は組み合わせが膨大になるため、現実的な時間で成功する可能性は低いです。IPアドレスに限定する場合などは有効かもしれません。
# 例: IPv4アドレス形式を試す場合 (設定が複雑な場合があります)
/path/to/john/run/john --incremental=Digits --mask='?d.?d.?d.?d' --format=known_hosts known_hosts_hashes.txt
--mask
オプションは John the Ripper の高度な機能であり、特定のパターンに合致する文字列を生成するために使用します。上記の例は単純化したもので、実際にはより複雑な設定が必要になる場合があります。
解読結果の表示
John the Ripper がハッシュの解読に成功すると、その結果は内部のポットファイル (john.pot
) に保存されます。解読されたハッシュとその元の値(ホスト名/IPアドレス)を確認するには、--show
オプションを使用します。
/path/to/john/run/john --show --format=known_hosts known_hosts_hashes.txt
出力例:
$known_hosts$1*abcdefghijklmnop==*qrstuvwxyzabcdef==:192.168.1.1
$known_hosts$1*ABCDEFGHIJKLMNOP==*QRSTUVWXYZABCDEF==:internal.corp.local
2 password hashes cracked, 0 left
この例では、2つのハッシュが解読され、それぞれ元のIPアドレス 192.168.1.1
とホスト名 internal.corp.local
が判明したことを示しています。 🎉
6. セキュリティ上の考慮事項と対策 🛡️
known_hosts2john
と John the Ripper を組み合わせることで、ハッシュ化されたホスト名を解読できる可能性があることは、セキュリティ上のリスクとなり得ます。
リスク
- 情報漏洩: 攻撃者が
known_hosts
ファイルを入手し、ハッシュを解読できた場合、ユーザーが接続しているサーバー(特に内部ネットワークのサーバーや機密性の高いサーバー)のリストが露呈する可能性があります。これは、さらなる攻撃の足がかりとなる情報を与えることになります。 - 推測の容易さ: ホスト名やIPアドレスは、パスワードほど複雑でない場合が多く、特に内部ネットワークのIPアドレスや一般的なホスト名(例:
server1
,test
,backup
など)は、比較的推測されやすい可能性があります。
対策
~/.ssh
ディレクトリの保護: 最も基本的な対策は、~/.ssh
ディレクトリと、その中のファイル(known_hosts
,id_rsa
など)へのアクセス権を適切に設定することです。通常、所有者のみが読み書きできるように設定します (chmod 700 ~/.ssh
,chmod 600 ~/.ssh/*
)。HashKnownHosts yes
の利用: 平文でホスト名を保存するよりは、ハッシュ化する方が安全です。これにより、ファイルが漏洩した場合でも、即座に接続先リストが判明することを防ぎます。ただし、上記のように解読される可能性は残ります。- 強力な秘密鍵パスフレーズの使用:
known_hosts
のハッシュ解読とは直接関係ありませんが、~/.ssh
ディレクトリ全体のセキュリティを高める上で、SSH秘密鍵に強力なパスフレーズを設定することは非常に重要です。 - 不要なエントリの削除: 定期的に
known_hosts
ファイルを見直し、もう接続しない古いサーバーのエントリを削除することも、リスクを低減する一助となります。 - アクセス制御と監視: サーバーやワークステーションへの不正アクセスを防ぐための一般的なセキュリティ対策(ファイアウォール、侵入検知システム、ログ監視など)も、
known_hosts
ファイルを含む機密情報へのアクセスを困難にします。
7. まとめ 📝
known_hosts2john
は、John the Ripper スイートに含まれるツールで、SSH の known_hosts
ファイルにハッシュ化されて保存されたホスト名やIPアドレスを抽出し、John the Ripper で解読可能な形式に変換します。これは主に、HashKnownHosts yes
設定が有効になっている環境で、漏洩した known_hosts
ファイルから接続先情報を得るために、ペネトレーションテストやセキュリティ監査の文脈で使用されます。
ホスト名のハッシュ化は、平文で保存するよりもセキュリティを高めますが、万能ではありません。適切な辞書と John the Ripper を用いれば、元のホスト名を解読できる可能性があります。したがって、~/.ssh
ディレクトリのアクセス権管理や、不要なエントリの削除といった基本的なセキュリティ対策が依然として重要です。
known_hosts2john
のようなツールとその目的を理解することは、SSH環境のセキュリティを評価し、潜在的なリスクに対処する上で役立ちます。🛡️
参考情報
-
John the Ripper official website: https://www.openwall.com/john/
-
John the Ripper bleeding-jumbo (GitHub): https://github.com/openwall/john (
known_hosts2john
はこのリポジトリのrun
ディレクトリ内にあります) -
ssh_config man page (HashKnownHosts): (オンラインで `man ssh_config` を検索するか、システムで `man ssh_config` コマンドを実行してください)
コメント