データベース権限の「最小化」という名の聖域:インジェクション攻撃への最終防衛線
多くのエンジニアが「SQLインジェクション対策はプリペアドステートメントで十分」と信じている。だが、現実はどうか。CVEデータベースを覗けば、アプリケーション層のバグ一つで、DBサーバー全体の管理者権限(DBA)を奪取され、OSコマンド実行へとエスカレーションされる事例は後を絶たない。
我々が向き合うべきは、「脆弱性がないコード」という幻想ではなく、「脆弱性が存在することを前提とした、被害を最小化するアーキテクチャ」だ。今回は、セキュリティの基本中の基本でありながら、現場で最も疎かにされがちな「DBユーザーの権限分離」について、防御側の深層心理を紐解いていく。
—
なぜ「アプリケーションユーザー」に権限を与えすぎるのか
インジェクション攻撃の真の恐怖は、クエリの改竄そのものではない。攻撃者がSQL文を注入した瞬間、そのDBユーザーが持つ「権限の範囲」で何ができるかという点だ。
多くの現場では、接続文字列にDB管理者(rootやsaなど)を指定している。これでは、攻撃者がUNION SELECTやstacked queriesを使ってテーブルを列挙した瞬間、ゲームオーバーだ。DROP TABLEでデータが消滅し、最悪の場合はxp_cmdshellのような拡張機能を通じてサーバーのシェルを掌握される。
権限分離の基本設計:ホワイトリストアプローチ
データベースの権限設計は、OSのファイアウォール設定と同じだ。「デフォルト拒否」を徹底する。
例えば、Webアプリがusersとproductsテーブルしか触らないのであれば、それ以外のテーブル(sys.tablesやinformation_schemaへのアクセス含む)は厳格に制限すべきだ。
— 1. アプリ専用のロールを作成
CREATE ROLE app_web_role;
— 2. 必要な操作のみを許可(SELECT, INSERT, UPDATEのみ。DELETEは論理削除で対応し、物理削除は禁止)
GRANT SELECT, INSERT, UPDATE ON schema_name.users TO app_web_role;
GRANT SELECT ON schema_name.products TO app_web_role;
— 3. DROP, TRUNCATE, GRANTなどの危険な操作は一切許可しない
— 4. ユーザーを作成し、ロールを割り当てる
CREATE USER ‘app_user’@’%’ IDENTIFIED BY ‘強固なパスワード’;
GRANT app_web_role TO ‘app_user’@’%’;
—
盲点:パケット構造とメタデータの保護
高度な攻撃者は、単にデータを取り出すだけではない。データベースのメタデータ(スキーマ情報)を漁り、バックエンドの構造を逆解析する。
多くのDBでは、information_schemaへのアクセス権を制限するだけで、インジェクション時の情報収集フェーズを大幅に遅延させることができる。また、MySQLのFILE権限や、PostgreSQLのCOPY FROM/TO PROGRAMなどは、DB経由でのOSコマンド実行の温床だ。これらは絶対に使用しない環境であっても、設定レベルでREVOKEしておく必要がある。
—
LLM時代の新たな脅威:プロンプトインジェクションとDB権限
現在、我々が対峙している最大の変数は「生成AI」だ。LLMを介してDBを操作するアプリケーションを設計する場合、従来のSQLインジェクションに加え、「プロンプトインジェクションによる意図しないクエリ実行」が加わる。
ガードレイルとして、LLMの推論結果が直接SQLを組み立てるのではなく、「権限を絞ったAPI層(中間層)」を介すアーキテクチャを推奨する。
- アーキテクチャの要点:
1. 分離: LLMが直接SQLを発行せず、関数呼び出し(Function Calling)を経由させる。
2. 検証: API層で入力パラメータを型チェックし、SQL生成前にホワイトリスト化されたストアドプロシージャのみを呼び出す。
3. 監視: DB側の監査ログ(Audit Log)をSIEMに流し込み、異常なクエリパターン(大量のテーブルスキャンなど)を検知する。
—
監査の観点:何が「侵害」を告げるのか
チーフセキュリティオフィサーの視点から言えば、権限分離は「侵入を防ぐ」ためのものだが、監査は「侵入を認める」ために存在する。
- 権限の定期棚卸し: 開発環境で作成した権限が本番に残っていないか。
- 不審なクエリの検知:
SELECTが頻発していないか、システムテーブルへのアクセス試行がないか。
これらを監視するために、データベース側のAudit機能(MariaDBのserver_auditやPostgreSQLのpgauditなど)を有効化し、GRANTやDROPといった危険なコマンドが実行された瞬間に、即時アラートを飛ばす仕組みを構築してほしい。
結びに:防御とは「静かなる設計」である
セキュリティエンジニアの腕の見せ所は、派手な防御策を並べることではない。アプリケーションが本来あるべき動作以外を「不可能」にするための、地味で静かな設定の積み重ねだ。
DBの権限分離は、アプリケーションが「信頼できない入力」を受け取ったとしても、被害を「データの閲覧」という範囲内に留めるための最後の防壁となる。君たちが設計するシステムが、たとえ侵入を許したとしても、攻撃者が「何もできない」と悟って立ち去るような、堅牢なアーキテクチャであることを期待している。
技術は常に進化する。しかし、この「最小権限」という原則だけは、量子暗号の時代になっても変わらぬ、サイバーセキュリティの不動の礎だ。
コメント