はじめに
Web アプリケーションの入力フィルタは、
シングルクォート '、OR / AND などのキーワード、スペースなどを禁止することで
簡易的に SQL Injection を阻止しようとすることがある。
しかし実際は、攻撃者が 複数の回避技術を組み合わせることで、
フィルタをすり抜けてしまうケースは多い。
この記事では、以下のような “複合的なフィルタ回避文字列” を例に、
使われている技術を体系的に分解する。
1%27%0A||%0A1=1%0A--%27+
これは学習目的で分析するのに最適なサンプルだ。
1. まずは URL デコードして構造を把握する
URL エンコードを復号すると、こうなる:
1'
||
1=1
--'
これだけで、次のような意図が見える:
-
'← 既存の文字列を“閉じる”役割 -
||← OR の代替記法 -
1=1← 常に真になるロジック -
--← コメントアウトで後続の SQL を無効化
そして %0A(改行)により、スペースを使わずに SQL の区切りを作るという工夫が込められている。
2. この文字列が使っている「5つのフィルタ回避技術」
この 1 行には、WAF / フィルタをすり抜けるための技術が 5 つも詰まっている。
① URL エンコード(Encoding Bypass)
%27, %0A などを使い、
フィルタやログの表層チェックをすり抜ける。
例
-
%27→' -
%0A→ 改行(LF)
目的:
- そのまま
'を書くとブロックされる - ログや WAF の文字列一致をかわす
- デコード後に有効な SQL になる
② No-Space Bypass(スペース禁止回避)
改行 %0A を用いて、実質的なスペースとして扱わせる。
||
1=1
のように、改行をスペース代替として利用している。
多くのフィルタは “空白文字=スペース(0x20)” しか見ていないため、
改行・タブなどはすり抜けてしまう。
③ No-Quote(クォート禁止回避)
シングルクォート ' を 最低限使い、文字列比較を避けて論理式へ逃がす構造になっている。
― ' で文字列を閉じる
― 本来のパラメータから脱出
― その後は論理式(1=1)で条件を TRUE にする
目的:
-
'text'のような普通の文字列比較を使わない - クォート削除フィルタを回避
- 引数を数値・論理式として扱わせる
④ No-Keyword(OR 禁止回避)
OR を直接書かずに、データベースが OR と等価に解釈する構文を使っている。
例えば MariaDB では:
|| → OR(論理 OR)
目的:
- フィルタが
ORだけを見ていても逃げられる - 同等の動作を別表現で実現
⑤ コメントアウト(Query Truncation)
-- を用いて 後続の SQL を無効化する。
--'
これにより、本来実行されるべき構文(パスワード比較など)が
まるごとコメントになり、処理されなくなる。
目的:
- 構文エラーを防ぐ
- 不要な条件式(本来のクエリ)を無効にする
- 攻撃者が書いたロジックだけを有効にする
3. 「5つ全部」を組み合わせると何が起きるか?
この 1 行の意図は非常にシンプルで、
- 元の SQL から脱出し
- 自分の好きな TRUE 条件式を追加し
- 残りはコメントで潰す
という動きを、“スペースなし・quotes 最小・キーワードなし” の制約下で実現することにある。
つまりフィルタをいくつ重ねても、
複数のテクニックを組み合わせれば突破されうるという観察ができる。
4. 防御側が学ぶべきポイント
この文字列は「攻撃方法」ではなく、
防御がどれだけ脆いかを理解する教材として非常に優秀。
学ぶべき教訓:
-
キーワード禁止では守れない
→ 大文字小文字混在、コメント挿入、代替記法で回避可能
-
スペース禁止では守れない
→ 改行、タブ、コメントなど無数の代替が存在
-
'をブロックしても守れない→ hex、CHAR、比較式、バイナリなど多数の代替がある
-
URL エンコードを正規化しない WAF は無力
→
%27や%0Aは必ずデコードされる
唯一の根本対策は「パラメータ化クエリ」
Prepared Statement / ORM を用いて
SQL を文字列連結で組み立てないこと。
まとめ
1%27%0A||%0A1=1%0A--%27+ という 1 行には、以下の 5 つの技術が組み合わさっている:
- URL エンコード
- No-Space(改行による区切り)
- No-Quote(論理式で逃げる)
- No-Keyword(OR禁止回避:
||) - コメントアウト(
--)
これは、フィルタが複数あっても突破されうる理由を理解する教材として最適なサンプル。