1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SSTI(server-side template injection)

Last updated at Posted at 2025-04-23

SSTI

webアプリケーションを効率的に開発を行うためにサーバーサイドでテンプレートエンジンを採用することがあります。

脆弱性対策を怠っていると、SQLインジェクションのように悪意のある入力によって、意図しない操作やファイルの改ざん・閲覧などがされる可能性があります。

テンプレートエンジン

以下のようにテンプレートエンジンがいくつか存在します。

テンプレートエンジン 特徴
Jinja2(Python) Flaskでよく使われる
Twing(PHP) Symfonyなど
ERB(Ruby) Railsなど

今回はJinja2の脆弱性について解説します。

Jinja2

まず、このテンプレートエンジンが使われていることを確認する必要があります。

{{7*7}} --->49

{{"a"*5}} --->aaaaa

などの戻り値になれば、Jinja2と言えるでしょう。

攻撃方法を探す

{{ [].__class__.__mro__[1].__subclasses__() }}

これは、現在使用できるクラスの一覧が出力されます。そのクラスの中には、ディレクトリを見たり、ユーザ情報を取得できるものがあります。

ただ、何をやっているかさっぱりだと思うので、順を追って説明します。

クラスを調べる

[].__class__---> <class 'list'>

まず、'[]'のクラスを調べています。<class 'list'>と「'[]'はlistクラスですよ~」と教えてくれます。
ここで調べるのはリスト以外でも問題ありません。
重要なのは、クラスの種類を出力させることです。

そのクラスの親を導く

[].__class__.__mro__[1] ---> <class 'object'>

次に、リストの親クラスのobjectクラスを出力させます。
リスト以外のクラスを調べたとしても、すべてのクラスは最終的にobjectクラスに辿りつくきます。
ただ、objectクラスにたどり着くことが重要です。

__mor__[1]というのは、直接の親クラスを指します。
__mor__[2]とすると、親の親(祖先)を指しますが、今回は存在しないのでエラーになります。

すべてのクラスをリストしよう

[].__class__.__mro__[1].__subclasses__()

__subclasses__()objectクラスの特別なメソッドです。
現在メモリ上にロードされている、すべてのクラスのリストを返します。

実行時に Python がロードしている全てのクラス(内部クラス、標準ライブラリクラス、ユーザー定義クラスを含む)が表示されます。
その中でも重要そうなクラスをまとめます。

クラス名 使い道 解説
subprocess.popen コマンド実行 任意のOSコマンドを実行可能
warning.catch_warnings __grobals__へのアクセス os open evalの実行経路

subprocess.popen

{{ [].__class__.__mro__[1].__subclasses__()[IDX]("id", shell=True, stdout=-1).communicate()[0].decode() }}

ちょっと長いですが、[IDX]から追加されたコードになります。
[IDX]はsubprocess.popenのリスト番号です。
リスト番号がわからない場合は、F3でpopoenと調べるとsubprocess.popenに誘導されます。
その状態でF3で,(クラスを羅列するときの区切り)を調べると、subprocess.popenが何番目にあるのかある程度特定することができます。

{{ [].__class__.__mro__[1].__subclasses__()[350] }}
{{ [].__class__.__mro__[1].__subclasses__()[351] }}

などで特定できます。

("id", shell=True, stdout=-1)は、shell経由で"id"というコマンドを実行するコードです。
"id""ls -a "にすればすべてのファイルが表示されます。CTFなどではここにflagがあったりします。
cat flag.txtなどで中身を読みましょう。

communicate()[0]は、出力とエラーを表示するためのメソッドです。
[0]にすることで、返り値から標準出力(バイト列)を取り出します。

decode()は取り出したバイト列を文字列に変換しています。

まとめ

テンプレートエンジンの脆弱性を突いた攻撃手法でした。
悪用禁止です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?