はじめに(この記事で分かること)#

サーバーのIPアドレスを変えても、サーバーが外に向けて発信する情報は変わらない。SSHのホスト鍵、TLS証明書、favicon.ico。これらはIPアドレスと切り離された識別子であり、ShodanやCensysが全世界を走査して収集している。

IPアドレスから個人を特定される仕組みで説明した「IPアドレスを変えても残る橋」のうち、サーバー側の橋をこの記事で掘り下げる。自分のサーバーが外からどう見えているかを自分で確かめる手順も示す。

前提: 脅威モデルの整理#

この記事の対策が有効な相手は、脅威モデル入門で整理した5種類の相手のうち、主に2者だ。

CensysやShodanのような走査エンジンは、全世界のサーバーを周期的に走査し、SSHのホスト鍵、TLS証明書、faviconのハッシュを収集する。この走査は、誰でもアクセスできる検索インタフェースを通じて公開されており、攻撃者でなくても使える。

対象を個人的に狙う攻撃者は、これらの公開データベースを起点に、自分の目標と関連するサーバー群を探す。サーバーがTorのonionアドレスで公開されていても、別のサーバーと鍵を共有していれば、相関によってホスティングIPが特定される。

SSHホスト鍵の相関#

鍵のフィンガープリントはIPと切り離された識別子だ#

SSHのホスト鍵は、サーバーがSSH接続を受ける際に自分自身を証明するための鍵ペアだ。この鍵のフィンガープリント(SHA256ハッシュ)は、IPアドレスが変わっても変化しない。

Censysの記事「Automated Hunting」は、この特性を攻撃側の視点から実演した。あるマルウェアの指令サーバーのSSHフィンガープリントを検索すると、同じ鍵を持つ別のホストが複数見つかった。検索結果から、攻撃者のインフラ全体を芋づる式にたどることができた。

実際の相関の例#

Censysの別の記事「Pivoting for Nosviak」では、ボットネット網が「共有SSHサーバ鍵、ほぼ同一のWebページ、再利用されたfavicon」で解明された。運営者が複数のサーバーで同じ鍵を使い回すと、それらのサーバーはチェーン上で別々に見えても、運営者としては同一のクラスタに束ねられる。

onionサービスとの相関#

Netlasの記事は、CARONTE(ACM CCS 2015)という研究を引用して、onionサービスのデアノニマイズ手法を説明している。論文によれば、CARONTEはonionサービスのページに含まれるURLや固有の文字列(解析タグのID、ビットコインのアドレス、ページタイトルなど)とHTTPS証明書を手がかりに、同じ内容や同じ証明書を出しているインターネット上のサーバーを探し、1,974件のうち101件(5%)で実IPを特定した。証明書の検索には、インターネット全体を走査したデータベース(Rapid7のSonar)を使っている。

鍵のフィンガープリントはIPを回転させても不変である。このため、onionバックエンドとclearnetサーバーが同じSSH鍵を使っていた場合、両者が同一マシンまたは同一運営者のインフラであると紐付けられる。

誤検知の可能性もある。Serv-Uなどのソフトウェアが既定のホスト鍵を共有する場合、鍵の一致は同じ運営者を必ずしも意味しない。ただし、ed25519鍵を新規生成した場合には、鍵の一致はほぼ確実に同一運営者を意味する。

TLS証明書の相関#

証明書の公開情報#

TLS証明書には、発行先のドメイン、発行者、有効期限、および公開鍵のフィンガープリントが含まれている。Certificate Transparencyログには、発行されたすべての証明書が記録され、crt.shやCensysで検索できる。

同一のLet's Encryptアカウントから発行された証明書は、アカウントURIで相関される。onionバックエンドとclearnetサーバーで同じACMEアカウントを使っていた場合、証明書のログから両者が紐付けられる。

証明書の鍵ペア#

証明書に含まれる公開鍵も識別子になる。証明書を更新しても鍵ペアを再利用していれば、subjectPublicKeyInfoのハッシュは不変である。IPを回転させても、鍵ペアが同じであれば相関される。

onionサービスではTLSを使う必要がない。Torプロトコル自体がEnd-to-End暗号化を提供しているため、証明書機関とのやり取り自体が匿名性の穴になる。

faviconハッシュによる相関#

faviconハッシュの仕組み#

favicon.icoのバイナリデータをMurmurHash3でハッシュ化した値がfaviconハッシュだ。Shodanはhttp.favicon.hash:クエリで、このハッシュが一致する全サーバーを検索できる。

Hive Securityの分析では、ある組織のfaviconハッシュから、その組織の全インフラ(363ホスト、373 IP、5,091開放ポート)が一括で特定された。faviconは開発環境、ステージング、内部ポータル、クラウドインスタンスなど、すべてのサーバーに同一のファイルが配置されることが多い。

faviconハッシュの検索は受動的な手法である。攻撃者はポートスキャンを行わずに、Shodanのデータベースを検索するだけで、組織のインフラ全体を特定できる。

候補の確かめ方: 応答の比較#

CARONTEは、見つけた候補が本当にonionサービスの置き場所かを、候補のサーバーに実際に接続して確かめた。onionサービスから返るHTTP応答と、候補のサーバーから返る応答を並べ、中身とWebサーバーの種類が似ていれば位置の漏れと判定する。論文の手法は応答時間の相関ではない。

この確かめ方から言えるのは、onionサービスと同じページ・同じ設定のWebサーバーがインターネット側からも見えていると、候補に挙がった時点で一致を確かめられてしまうということだ。onion側のWebサーバーはローカルアドレスだけで待ち受け、インターネット側から同じ応答が返らないようにしておくのが合理的である。

自己監査の手順(SelfCheck)#

自分のサーバーが外からどう見えているかを、自分で確かめる手順を7ステップで示す。

ステップ1: SSHホスト鍵のフィンガープリントを確認する#

ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

出力されるフィンガープリントをCensysで検索し、他のサーバー・他のサービスと重複していないかを確認する。重複があれば、その鍵は新しいものに置き換える。

ステップ2: SSHホスト鍵の新規生成#

複数サーバーで鍵を使い回している場合、各サーバーで新しい鍵ペアを生成する。Debian/Ubuntuではssh-keygen -Aで再生成できるが、確実に新規生成するには既存の鍵を削除してから再生成する。

ステップ3: faviconハッシュを確認する#

自分のサイトのfavicon.icoを取得し、MurmurHash3でハッシュ化してShodanで検索する。ハッシュの計算はPythonで行える。

import mmh3, requests, base64
r = requests.get('https://example.com/favicon.ico')
favicon = base64.encodebytes(r.content)
print(mmh3.hash(favicon))

検索結果に自分が意図していないサーバーが含まれていれば、faviconをサーバーごとに別物にする。

ステップ4: 証明書ログを確認する#

crt.shで自分のドメインを検索し、発行済みの全証明書を確認する。見覚えのないドメインがSANに含まれていたり、originサーバーのIPと紐付いた証明書が過去に発行されていたりしないかを確認する。

ステップ5: DNS履歴を確認する#

SecurityTrailsなどのDNS履歴サービスで、自分のドメインの過去のAレコードを確認する。CDN導入前のIPアドレスが履歴に残っている場合、そのIPはすでに公開されている。CDNを導入する前のIPが露出している場合は、サーバーのIPを変更する。

ステップ6: サーバーの開放ポートを確認する#

ShodanのInternetDB(https://internetdb.shodan.io)で自分のサーバーのIPを検索し、開放ポート、サービスのバナー、ソフトウェアのバージョンを確認する。意図していないポートが開いていないかを確認する。

ステップ7: メールヘッダを確認する#

自分のサーバーからテストメールを送信し、受信側でヘッダを確認する。Received:ヘッダにoriginサーバーのIPアドレスが含まれていないかを確認する。含まれていれば、SMTPの設定を修正し、外部のメール送信サービス経由に変更する。

まとめ#

SSHホスト鍵、TLS証明書、faviconハッシュは、IPアドレスが変わっても残る識別子だ。ShodanとCensysはこれらを全世界で収集し、誰でも検索できる形で公開している。

自分のサーバーを保護するには、これらの識別子が複数のサーバーで重複していないかを定期的に確認する。確認の手順はこの記事の7ステップに従えばよい。

サーバー側の匿名化をさらに進める手法は、踏み台サーバーとWireGuardでSSHを公開しないとIPアドレスを出さずにonionサイトを運営するで扱う。

出典#