WAFの「死角」を突き破る:SQLインジェクションと正規化の深淵
多くのエンジニアが「WAFを導入しているから大丈夫だ」と安堵する瞬間、攻撃者はその背後にある「解釈のギャップ」を冷笑している。SQLインジェクション(SQLi)の戦場において、WAFは万能な盾ではない。それは単なる「文字列パターンのフィルタ」に過ぎず、攻撃者が送り込むペイロードが、WAFとバックエンドのデータベース間で「異なる解釈」をされた瞬間、防衛線は紙屑同然に崩壊する。
今回は、WAFの検知ロジックを無効化する「正規化の不一致」という盲点について、実戦的な観点から掘り下げる。
1. 攻撃者が操る「解釈の多重性」
WAFを回避する手法の根底にあるのは、「WAFが見ているデータ」と「DBが実行するデータ」の齟齬だ。これを引き起こすのが、多重エンコーディングや、データベース固有のコメントアウト記法の悪用である。
ペイロードの変奏曲
攻撃者は、UNION SELECTといった明白なキーワードを避け、次のような手法でWAFの正規表現をすり抜ける。
- 多重URLエンコーディング:
%2553%2545%254c%2545%2543%2554(SELECTの二重エンコード) - コメントによる分断:
UN//ION SEL//ECT - データベース特有の空白文字: MySQLにおける
%0a(改行) や%0b(垂直タブ) を利用し、トークナイザーを混乱させる。
WAFがHTTPリクエストをパースする際、一重のデコードしか行わなければ、この「難読化された毒」は見逃される。しかし、バックエンドのアプリケーション層、あるいはDBドライバーがこれを再帰的にデコード(または正規化)した瞬間、クリーンなSQLクエリとして実行されてしまうのだ。
2. 正規化(Normalization)こそが真の防衛線
多くのアーキテクトが犯す過ちは、WAFに「正規化」の処理を丸投げすることだ。だが、最高峰のセキュリティを求めるならば、「入力を受け取った瞬間に、正規化された単一の形式へ強制的に変換する」という設計をアプリケーションの境界(API Gateway層)で完結させる必要がある。
実装の指針:防御的アーキテクチャ
単純な置換処理では不十分だ。再帰的なデコードを行い、正規化された後の文字列に対してバリデーションを行う必要がある。
import urllib.parse
import html
def normalize_input(input_str):
“””
再帰的なデコードを行い、正規化された単一の形式を返す。
WAFの回避を許さないための「正規化レイヤー」の実装例。
“””
prev_str = None
curr_str = input_str
# ループ回数を制限し、無限再帰によるDoSを防ぐ(セキュリティの基本)
for _ in range(3):
prev_str = curr_str
# URLデコード -> HTMLエンティティデコード
curr_str = html.unescape(urllib.parse.unquote(curr_str))
if curr_str == prev_str:
break
# この時点で正規化された文字列に対し、ホワイトリスト形式のバリデーションを実行する
return curr_str
使用例:
入力: %2553%2545%254c%2545%2543%2554 -> SELECT へ正規化される
3. なぜ「静的な防御」では勝てないのか
現代のサイバー脅威において、パケット構造の解析はもはや基本だ。今、私たちが対峙しているのは、LLM(生成AI)が自動生成する、未知の難読化パターンを用いたSQLiである。
プロンプトインジェクションと同様、SQLiにおいても「入力の型」を厳密に定義し、SQLクエリそのものを動的に生成させない設計(プリペアドステートメントの強制)が唯一の解となる。
アーキテクトへの提言
1. 疎結合な正規化層の設置: API Gatewayあるいはプロキシ層で、入力値を完全に正規化してからアップストリームへ流すこと。このプロセスは、アプリケーションのビジネスロジックから完全に分離しなければならない。
2. 型安全なインターフェース: ORMの生SQL実行機能(raw query)の使用を、CI/CDパイプラインの静的解析(SAST)で完全に禁止せよ。
3. データベースの特権最小化: 万が一SQLiが成功したとしても、DBユーザーには「そのテーブルを読み取る権限」しかない状態(最小権限の原則)を徹底する。
最後に:防御は「不信」から始まる
世界中のインシデントを見ていて痛感するのは、技術的な欠陥以上に「防御側がWAFやクラウド側のマネージドサービスを過信している」という心理的な脆弱性だ。
SQLインジェクションは、技術的には「枯れた脆弱性」と言われるが、攻撃者の視点から見れば「最も手軽に、かつ確実にシステムを掌握できる入り口」だ。パケットの深部にあるバイト列の揺らぎにまで目を凝らし、アプリケーションの正規化プロセスを自ら設計する。その泥臭い執念こそが、テックリードとして、そしてホワイトハッカーとして備えるべき「真の防御姿勢」である。
次回のブログでは、この正規化処理をバイパスする、さらに高度な「メモリ上の文字コード変換の不整合」について深く踏み込む予定だ。セキュリティの探求に終わりはない。
コメント