SpringBoot SpEL表达式注入漏洞-分析与复现

时间:2023-02-14 09:08:23

影响版本:

1.1.0-1.1.12

1.2.0-1.2.7

1.3.0

修复方案:升至1.3.1或以上版本

我的测试环境:SpringBoot 1.2.0

0x00前言

这是2016年爆出的一个洞,利用条件是使用了springboot的默认错误页(Whitelabel Error Page),存在漏洞的页面在:/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration.java

0x01触发原因

本次漏洞的触发点在SpringBoot的自定义错误页面,功能是页面返回错误,并提供详细信息,信息中包括错误status("status"->500)、时间戳("timestamp"->"Fri Dec.....")、错误信息("error"->"Internal Server Error")、和用户输入的参数("message"->"abcd"),这些参数在模板文件中以类似于以下形式存在:”Error 1234 ${status}---${timestamp}---${error}---${message}“。

后端进行渲染视图时,首先,解析错误页面模板中的参数名(status、timestamp、error、message),即判断模板中每个${的位置,然后再判断最近的}的位置,从而将参数名一个个读取出来,然而这里使用了递归,也就是说如果参数名中还包含${和}的话,这个解析引擎会再次递归一次,再次解析这个值,如,模板中有个值为${${abc}},由于使用了递归,解析引擎会对其解析两次,第一层去掉最外层的{}解析成${abc},然后将其作为参数进行第二次解析。在第二次解析中将里层的{}去掉,变成abc。

每次将一个参数名解析出来之后,就将参数名传入SpEL引擎,解析成context中对应参数名的值(如"status"->500),完成之后返回参数值给第一步中的解析引擎(返回500)。

解析引擎收到SpEL传回的参数值之后,再次进行递归,以防参数值中也存在${和},存在则去之,然后在递归过程中再次传入SpEL引擎进行解析。这里就是触发点了。假设用户的输入中包含${payload},则SpEL第一次message解析成${payload}之后,解析引擎进行递归,去掉${和}后将payload传入SpEL引擎,SpEL引擎将将直接对payload进行解析,从而触发了漏洞,触发点如下图所示。

SpringBoot SpEL表达式注入漏洞-分析与复现

0x02调试分析

先搭好存在漏洞的SpringBoot版本的环境,使用其自带的sample搭建一个服务器,然后自己写一个控制器,抛出异常即可。

SpringBoot SpEL表达式注入漏洞-分析与复现

开启调试,使用浏览器访问

http://127.0.0.1:8080/?payload=${new%20java.lang.ProcessBuilder(new%20java.lang.String(new%20byte[]{99,97,108,99})).start()}

首先,将context赋值到this.context中,然后以this.template和this.resolver为参数调用replacePlaceholders方法。

SpringBoot SpEL表达式注入漏洞-分析与复现

SpringBoot SpEL表达式注入漏洞-分析与复现

this.template="<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>${timestamp}</div><div>There was an unexpected error (type=${error}, status=${status}).</div><div>${message}</div></body></html>"

跟进replacePlaceholders方法,进入了PropertyPlaceholderHelper文件

SpringBoot SpEL表达式注入漏洞-分析与复现

继续跟进parseStringValue方法(这就是分析中说的存在递归的方法),strVal的值为之前的this.template,将之赋值给result,然后通过判断result中${和}的位置,开始解析result中的第一个参数名,并赋值给placeholder,本次的值为"timestamp",然后将placeholder作为第一个参数,再次调用本方法(递归,以防字符串placeholder中包含${})。

SpringBoot SpEL表达式注入漏洞-分析与复现

跟进递归,由于placeholder的值为"timestamp",其中不包含${,导致startIndex为-1,故不进入while语句,直接到了return,因此可以发现,在递归时,如果第一个参数中不包含${,则直接将第一个参数返回。

SpringBoot SpEL表达式注入漏洞-分析与复现

SpringBoot SpEL表达式注入漏洞-分析与复现

再次回到之前的点,下一步是调用resolvePlaceholder方法,此函数的作用是查找this.context中对应参数的值并返回,跟进看一下

SpringBoot SpEL表达式注入漏洞-分析与复现

SpringBoot SpEL表达式注入漏洞-分析与复现

首先看一下this.context,发现"timestamp" -> "Sat Dec 15 10:49:02 CST 2018"

SpringBoot SpEL表达式注入漏洞-分析与复现

继续跟进,发现value被赋值成SpEL解析后的值,然后return

SpringBoot SpEL表达式注入漏洞-分析与复现

回到parseStringValue方法,将经过SpEL解析后return的值赋值给propVal,由于propVal != null,故跳过第一个if语句,进入第二个语句,将propVal作为第一个参数再次递归。通过上一次递归我们发现,如果第一个参数中没有${,则直接返回第一个参数的值,因此这次就不再跟进了。

SpringBoot SpEL表达式注入漏洞-分析与复现

递归回来后propVal的值没变,使用replace将propVal替换到result中的对应的参数位。接着寻找template中的下一个参数位,赋值给startIndex,用于下一次while条件判断。

SpringBoot SpEL表达式注入漏洞-分析与复现

SpringBoot SpEL表达式注入漏洞-分析与复现

进入第二次循环,这次的参数是error,和之前的timestamp过程一样,就不具体分析了

SpringBoot SpEL表达式注入漏洞-分析与复现

第三次while循环,参数是status,同上,不具体分析

SpringBoot SpEL表达式注入漏洞-分析与复现

进入第四次循环,重头戏来啦,这次的参数是message,其值是用户输入的值。

SpringBoot SpEL表达式注入漏洞-分析与复现

跟进到第一次递归,防止参数名中含有${},由于参数名士message,故略过这一步。然后到了resolvePlaceholder方法,用于使用SpEL表达式引擎解析message的值,再跟进一下。

SpringBoot SpEL表达式注入漏洞-分析与复现

SpringBoot SpEL表达式注入漏洞-分析与复现

发现value的值为用户传入的payload

SpringBoot SpEL表达式注入漏洞-分析与复现

其中包含${},是一个SpEL表达式。继续跟进,返回到parseStringValue方法。

SpringBoot SpEL表达式注入漏洞-分析与复现

可以发现,为了防止propVal中包含${},再次进行一次递归。下面就是漏洞关键点了,跟进这次递归。

SpringBoot SpEL表达式注入漏洞-分析与复现

此时placeholder的值为去掉${}的payload,即:"new java.lang.ProcessBuilder(new java.lang.String(new byte[]{99,97,108,99})).start()"。将placeholder作为第一个参数传入SpEL解析函数(147行)

SpringBoot SpEL表达式注入漏洞-分析与复现

可以发现,这里直接使用parseExpression(name),而name的值就是我们的payload。接着使用getValue解析payload:

Expression expression = this.parser.parseExpression("new java.lang.ProcessBuilder(new java.lang.String(new byte[]{99,97,108,99})).start()");

Object value = expression.getValue(this.context);

然后触发payload,漏洞利用完成。

SpringBoot SpEL表达式注入漏洞-分析与复现

0x03补丁分析

补丁创建了一个新的NonRecursivePropertyPlaceholderHelper类,用于防止parseStringValue进行递归解析。

SpringBoot SpEL表达式注入漏洞-分析与复现

SpringBoot SpEL表达式注入漏洞-分析与复现

0x04参考文章

Spring Boot框架Whitelabel Error Page SpEL注入漏洞分析

SpringBoot SpEL表达式注入漏洞-分析与复现的更多相关文章

  1. SpEL表达式注入漏洞学习和回显poc研究

    目录 前言 环境 基础学习和回显实验 语法基础 回显实验 BufferedReader Scanner SpEL漏洞复现 低版本SpringBoot中IllegalStateException CVE ...

  2. &lbrack;CVE-2014-3704&rsqb;Drupal 7&period;31 SQL注入漏洞分析与复现

    记录下自己的复现思路 漏洞影响: Drupal 7.31 Drupal是一个开源内容管理平台,为数百万个网站和应用程序提供支持. 0x01漏洞复现 复现环境: 1) Apache2.4 2) Php ...

  3. &lbrack;CVE-2017-5487&rsqb; WordPress &lt&semi;&equals;4&period;7&period;1 REST API 内容注入漏洞分析与复现

    记录下自己的复现思路 漏洞影响: 未授权获取发布过文章的其他用户的用户名.id 触发前提:wordpress配置REST API 影响版本:<= 4.7 0x01漏洞复现 复现环境: 1) Ap ...

  4. Nexus Repository Manager 3&lpar;CVE-2019-7238&rpar; 远程代码执行漏洞分析和复现

    0x00 漏洞背景 Nexus Repository Manager 3是一款软件仓库,可以用来存储和分发Maven,NuGET等软件源仓库.其3.14.0及之前版本中,存在一处基于OrientDB自 ...

  5. Beescms&lowbar;v4&period;0 sql注入漏洞分析

    Beescms_v4.0 sql注入漏洞分析 一.漏洞描述 Beescms v4.0由于后台登录验证码设计缺陷以及代码防护缺陷导致存在bypass全局防护的SQL注入. 二.漏洞环境搭建 1.官方下载 ...

  6. PHPCMS &bsol;phpcms&bsol;modules&bsol;member&bsol;index&period;php 用户登陆SQL注入漏洞分析

    catalog . 漏洞描述 . 漏洞触发条件 . 漏洞影响范围 . 漏洞代码分析 . 防御方法 . 攻防思考 1. 漏洞描述2. 漏洞触发条件 0x1: POC http://localhost/p ...

  7. PHPCMS V9&period;6&period;0 SQL注入漏洞分析

    0x01 此SQL注入漏洞与metinfo v6.2.0版本以下SQL盲注漏洞个人认为较为相似.且较为有趣,故在此分析并附上exp. 0x02 首先复现漏洞,环境为: PHP:5.4.45 + Apa ...

  8. Typecho 反序列化漏洞 分析及复现

    0x00 漏洞简介 CVE-2018-18753 漏洞概述: typecho 是一款非常简洁快速博客 CMS,前台 install.php 文件存在反序列化漏洞,通过构造的反序列化字符串注入可以执行任 ...

  9. DM企业建站系统v201710 sql注入漏洞分析 &vert; 新版v201712依旧存在sql注入

    0x00 前言 本来呢,这套CMS都不想审的了.下载下来打开一看,各种debug注释,排版烂的不行. 贴几个页面看看 感觉像是新手练手的,没有审下去的欲望了. 但想了想,我tm就是新手啊,然后就继续看 ...

随机推荐

  1. &lbrack;2015hdu多校联赛补题&rsqb;hdu5297 Y sequence

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5297 题意:给你一个所有正整数的序列,然后去掉满足x^(2~r)的所有数(x为所有正整数,r>= ...

  2. android--HttpURLConnection&lpar;转载&rpar;

    android之HttpURLConnection 1.HttpURLConnection连接URL1)创建一个URL对象 URL url = new URL(http://www.baidu.com ...

  3. Python全栈开发记录&lowbar;第七篇(模块&lowbar;time&lowbar;datetime&lowbar;random&lowbar;os&lowbar;sys&lowbar;hashlib&lowbar;logging&lowbar;configparser&lowbar;re)

    这一篇主要是学习python里面的模块,篇幅可能会比较长 模块的概念:在Python中,一个.py文件就称之为一个模块(Module). 模块一共三种: python标准库 第三方模块 应用程序自定义 ...

  4. android studio 运行项目时waiting for target device to come online

    cmd进入命令行,进入adb所在的目录下: 或者在Terminal中输入命令: adb kill-server adb start-server

  5. 转&colon;Redis 3&period;2&period;1集群搭建

    Redis 3.2.1集群搭建   一.概述 Redis3.0版本之后支持Cluster. 1.1.redis cluster的现状 目前redis支持的cluster特性: 1):节点自动发现 2) ...

  6. Oracle数据库select语句

    select * from EMp--all data in EMP table select * from EMP where ename in('SMITH')--the data where e ...

  7. mongodb安装教程

    MongoDB 下载及安装 MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制包,你可以从MongoDB官网下载安装,MongoDB 预编译二进制包下载地址:https://www. ...

  8. luogu P3383 【模板】线性筛素数

    题目描述 如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内) 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示查询的范围和查询的个数. 接下来M行每行 ...

  9. &lbrack;Jmeter并发报错解决方案&rsqb;org&period;apache&period;http&period;NoHttpResponseException&colon; 10&period;0&period;4&period;147&colon;8000 failed to respond

    背景:公司模型框架是Nginx+uwsgi+Django+nginx,一开始使用Jmeter进行高并发请求测试,发现成功率只有50%,换用postman,成功率100%,代码进行高并发一样不会报错. ...

  10. &lbrack;知识库&colon;python-tornado&rsqb;异步调用中的上下文控制Tornado stack context

    异步调用中的上下文控制Tornado stack context https://www.zouyesheng.com/context-in-async-env.html 这篇文章真心不错, 非常透彻 ...