SSHambleの調査

このブログはアルバイトのseigo2016が書いています。 あるもりすぶろぐの内容は個人の意見です。

検証には自身で管理する環境を使用し、自己責任でお願いします。また、この情報を悪用することは絶対に行わないでください。

1. はじめに

今回は、runZeroが公開した SSH セキュリティ検査ツールSSHambleについて検証を行いました。

2. ツール概要

runZeroが公開している、SSHの認証まわりの予期せぬ状態遷移や認証後攻撃、認証タイミングの解析、ポストセッション列挙などを調査するためのツールで、Goで実装されています。 SSHの設定不備や脆弱性に関するスキャン・分析・対話型シェルツールなどが備わっており、状態遷移や認証タイミングについても検証できることが大きな特徴です。
GitHubリポジトリ: https://github.com/runZeroInc/sshamble

3. 機能解説

SSHambleには、スキャン・解析・対話型ポストセッションシェルの大きく3つの機能が備わっています。

3.1 スキャン

各ホストに対して、指定したオプションに従って複数のチェックを実行できます。 出力はJSONファイル等に保存でき、後段の解析に回せる設計となっています。

オプション

  • 認証スキップ・認証バイパス
    • skip-auth / skip-auth-none / skip-auth-method-empty / skip-auth-method-null / skip-auth-pubkeyany / auth=success
  • 公開鍵認証関連
    • pubkey-any / pubkey-any-half / half-auth-limit / user-key / pubkey-hunt
  • パスワード認証
    • password-any / password-empty / password-null / password-user / password-change-empty / password-change-null
  • キーボードインタラクティブ
    • kbd-any / kbd-empty / kbd-null / kbd-user
  • GSSAPI認証
    • gssapi-any
  • ユーザー列挙・タイミング解析
    • 応答時間差によるユーザー推定。
    • timing-none / timing-pass / timing-pubkey
  • 既知の脆弱性チェック
    • vuln-tcp-forward / vuln-generic-env / vuln-gogs-env / vuln-ruckus-password-escape / vuln-softserve-env / vuln-exec-skip-auth / vuln-exec-skip-userauth
  • 弱い鍵の利用の検知・ブロックリスト
  • 既知の弱鍵をブロックリストと照合
    • badkeys-blocklist

3.2 解析

先述のスキャン結果ファイルを読み込み、得られた情報ごとに集約・分類し、問題の有無やホスト毎のリスクをレポートにすることが可能です。

3.3 対話型ポストセッションシェル

また、より柔軟で詳細な認証状態の遷移に関する調査のために、認証後に生の SSH リクエストを送信し、環境変数、pty、ポートフォワーディングなども検証可能です。

4. 検証

4.1. 検証環境

ubuntu:22.04のベースイメージを利用したDockerコンテナを用意し、OpenSSHやSoftServeをインストールして検証しました。

5.2. 基本的なスキャン

まず、デフォルトのオプションで、特に追加の設定をしていないSSHサーバーを起動したコンテナにスキャンを行いました。

  • コンテナベースイメージ: ubuntu:22.04
  • OpenSSH: SSH-2.0-OpenSSH_8.9p1 (aptでインストール)
sshamble scan -p 2205 localhost -o scan.jsonl

出力(抜粋)

{
  "host": "localhost",
  "port": 2205,
  "user": "gated",
  "banner": "Ubuntu 22.04.5 LTS\n",
  "version": "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.13",
  "methods": ["publickey", "password", "keyboard-interactive"],
  "authNoneResult": "auth-failed",
  "sessionOutput": "=== Custom App Login (post-session demo) ===\r\nUsername: Password: \r\nAccess denied by post-auth gate.",
  "sessionMethod": "keyboard-user",
  "vulns": [
    {
      "id": "vuln-tcp-forward",
      "proof": "vulnerable to port forwarding (127.0.0.1:22)",
      "ref": "https://cwe.mitre.org/data/definitions/183.html"
    }
  ]
}

結果概要

スキャン結果を読むと、以下のことがわかります。

  • ホスト: localhost
  • ポート: 2205
  • OS バナー: Ubuntu 22.04.5 LTS
  • SSH バージョン: SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.13
  • 認証方式: publickey, password, keyboard-interactive
  • 検出された脆弱性: TCPポートフォワーディングの不適切な設定 (CWE-183)

分析

sshamble analyzeコマンドを用いることで、このスキャン結果を統計的に分析できます。

sshamble analyze -i scan.jsonl -o results/

生成されるCSVファイル

5.3. auth-none による匿名セッションの検知

Docker環境

  • コンテナベースイメージ: ubuntu:22.04
  • OpenSSH: SSH-2.0-OpenSSH_8.9p1 (aptでインストール)
  • testerユーザーを作成し、passwd -dで空パスワードに設定
  • sshd_configでPermitEmptyPasswords yesを有効化

スキャン実行

sshamble scan -p 2201 localhost -o results/2201/scan.jsonl --users root,admin,tester,weak,validuser,gated,fwder

出力

スキャン結果は次のようになりました。(検証に関係するところのみ抜粋)

{
  "host": "localhost",
  "port": 2201,
  "user": "tester",
  "version": "SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.13",
  "methods": ["password"],
  "authNoneResult": "auth-failed",
  "sessionMethod": "password-empty",
  "sessionSecret": "",
  "vulns": []
}

この結果より、testerユーザーは空パスワード(password-empty)で認証が可能であることがわかります。
これはsshd_configのPermitEmptyPasswords yes設定により、パスワードなしでのログインが許可されていることによる問題です。
本来であればSSHサーバーは空パスワードを拒否すべきですが、設定ミスにより脆弱な状態となっているということがチェックできました。

5.4 SoftServe環境へのスキャン

Soft Serve v0.7.4以前には、環境変数の不適切なハンドリングにより、リモートコード実行(RCE)の可能性がある脆弱性が存在します。SSHambleにはこれをスキャンするオプションがあるので、それを使った検証を行います。

環境

softserve-vulnのDocker環境

  • コンテナベースイメージ: debian:bookworm-slim マルチステージビルドでSoft Serve v0.7.4をコンパイルし、Gitリポジトリサーバーとして動作させます。

スキャン実行

sshamble scan -p 2208 localhost -o results/softserve.jsonl

出力

スキャン結果(抜粋):

{
  "host": "localhost",
  "port": 2208,
  "user": "admin",
  "version": "SSH-2.0-OpenSSH_7.6p1",
  "methods": ["publickey", "keyboard-interactive"],
  "authNoneResult": "auth-failed",
  "sessionMethod": "keyboard-null",
  "sessionSecret": "\u0000",
  "vulns": [
    {
      "id": "vuln-softserve-env",
      "proof": "ld.so error in output (ERROR: ld.so: object '/' from LD_PRELOAD cannot be preloaded)",
      "ref": "CVE-2024-41956",
      "url": "https://github.com/charmbracelet/soft-serve/security/advisories/GHSA-m445-w3xr-vp2f"
    }
  ]
}

想定通り、LD_PRELOAD環境変数のインジェクションにより、ld.soエラーが発生し、CVE-2024-41956が存在することが確認できました。

6. ログ解析と特徴的なパターン

SSHambleは認証状態の遷移の確認や情報収集のためのスキャンなどを行うため、スキャンされたサーバーではいくつか特徴的なログが見られます。

6.1 dispatch_protocol_error

dispatch_protocol_error は SSH デーモン (sshd) がプロトコル仕様外のメッセージをクライアントから受信した際に出力するログです。
通常のSSHクライアント(OpenSSH, PuTTY等)では発生しませんが、SSHambleでは主に以下の認証スキップ系・バイパス系チェックで発生します。

チェック名 概要 ログ例 意味
skip-ssh-userauth 認証サービス自体をスキップ dispatch_protocol_error: type 90 seq 0 [preauth] 認証前にチャネル開設試行 (SSH_MSG_CHANNEL_OPEN)
skip-auth 認証を実行せずセッション開設 同上 同上
skip-auth-pubkeyany Half-Auth後のチャネル開設試行 dispatch_protocol_error: type 90 seq 2 [preauth] 認証フロー逸脱
skip-auth-success クライアントが偽の認証成功メッセージ送信 dispatch_protocol_error: type 52 seq 2 [preauth] SSH_MSG_USERAUTH_SUCCESSをクライアント側から送信(libssh系脆弱性模倣)
pubkey-bulkhalf 大量のHalf-Auth試行 dispatch_protocol_error: type 90 seq X [preauth] 認証試行制限を確認中

検知のポイント

  • type 90 (SSH_MSG_CHANNEL_OPEN): 認証前チャネルオープン試行(認証スキップ)
  • type 52 (SSH_MSG_USERAUTH_SUCCESS): クライアントが偽の成功メッセージ送信(libssh脆弱性検査)
dispatch_protocol_error: type (90|52) seq [0-9]+ \[preauth\]

このログが1行でも出力されれば、SSHambleまたは類似のプロトコル逸脱攻撃の試行を意味します。
また、正常なクライアントでの試行時は出現しないため、誤検知リスクは低いと考えられます。

6.2 Half-Authおよび公開鍵列挙の痕跡

次に、SSHambleの pubkey-any や pubkey-bulkhalf チェックでは、署名を伴わないHalf-Authを多数送信し、サーバーの認証試行制限 (MaxAuthTries) や鍵受理ロジックを確認します。

代表的なログとしては

Failed publickey for invaliduser from 172.31.0.1 port 35214 ssh2: RSA SHA256:abcXYZ
error: maximum authentication attempts exceeded for invaliduser from 172.31.0.1 port 35214 ssh2 [preauth]

があります。

6.3 認証方式の切り替え試行

SSHambleは単一接続内または短時間で複数の認証方式を試行し、サーバーの認証設定や脆弱性を調査します。

代表的なログとしては

Failed none for root from 172.31.0.1 port 34412 ssh2
Failed publickey for root from 172.31.0.1 port 34412 ssh2
Failed password for root from 172.31.0.1 port 34412 ssh2

があります。
30秒以内に同一IPから複数の認証方式が試行された場合、SSHambleもしくは自動化スキャナの可能性が高いと考えられます。

6.4 その他の特徴的パターン

SSHambleスキャンでは、以下のような特徴的なログパターンも観測されることがあります。

ログパターン 意味 検知対象
authNoneResult":"auth-success" none認証成功 匿名セッション
keyboard-null accepted auth 空パスワード受理 PermitEmptyPasswords yes 設定ミス
vuln-tcp-forward 認証後フォワード許可 内部踏み台・CWE-183
ld.so error in output LD_PRELOADエラー SoftServe RCE (CVE-2024-41956)

6.5 fail2banやSnortでの検知可能性

SnortなどのネットワークIDSではSSHは暗号化セッションのため、dispatch_protocol_error や Failed publickey といったアプリケーション層メッセージは検知できません。
したがって、SSHambleのようなプロトコル異常検知は サーバーログ(auth.log)ベース の分析が必須であり、IDSではポート単位の接続頻度や異常切断数による挙動分析に限定されます。

7. おわりに

鍵管理やユーザ運用のちょっとした設定漏れもチェックすることができるほか、認証遷移やforwardingに関する挙動も確認でき、単なるスキャンツールより詳細に分析できることがわかりました。
これにより、従来のスキャンだけでは見過ごされがちな、認証手順やタイミング差、サーバー実装固有の処理といった挙動を丁寧に検証できます。
また、今回の検証を通じて、SSHは成熟したプロトコルといえる一方で、SSHサーバーには運用・実装の多様性があり、それが起因の脆弱性も存在するということも知ることができました。