spring security oauth rce (cve-2016-4977) 漏洞分析
0x00 漏洞概述
1.漏洞简介
Spring Security OAuth是为Spring框架提供安全认证支持的一个模块,在7月5日其维护者发布了这样一个升级公告,主要说明在用户使用Whitelabel views
来处理错误时,攻击者在被授权的情况下可以通过构造恶意参数来远程执行命令。漏洞的发现者在10月13日公开了该漏洞的挖掘记录。
2.漏洞影响
授权状态下远程命令执行
3.影响版本
2.0.0 to 2.0.9
1.0.0 to 1.0.5
0x01 漏洞复现
1. 环境搭建
docker pull maven
FROM mavenWORKDIR /tmp/
RUN wget http://secalert.net/research/cve-2016-4977.zip
RUN unzip cve-2016-4977.zip
RUN mv spring-oauth2-sec-bug/* /usr/src/mymavenWORKDIR /usr/src/mymaven
RUN mvn clean installCMD ["java", "-jar", "./target/demo-0.0.1-SNAPSHOT.jar"]
docker build -t mvn-spring .
docker run --rm --name mvn-spring-app -p 8080:8080 mvn-spring
2.漏洞分析
首先我们查看src/resources/application.properties
的内容来获取clientid
和用户的密码:
接着我们访问这个url:
http://localhost:8080/oauth/authorize?response_type=token&client_id=acme&redirect_uri=hellotom
其中client_id
就是我们前面获取到的,然后输入用户名user,密码填上面的password
。
点击登录后程序会返回这样一个页面:
可以看到由于hellotom
对于redirect_uri
来说是不合法的值,所以程序会将错误信息返回并且其中带着hellotom
,那么这个不合法的值可不可以是一个表达式呢?我们再访问这个url:
http://localhost:8080/oauth/authorize?response_type=token&client_id=acme&redirect_uri=${2334-1}
结果如下:
可以看到表达式被执行,触发了漏洞。
下面看代码,由于程序使用Whitelabel
作为视图来返回错误页面,所以先看/spring-security-oauth/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/WhitelabelErrorEndpoint.java
中第18-40行:
@FrameworkEndpoint
public class WhitelabelErrorEndpoint {private static final String ERROR = "<html><body><h1>OAuth Error</h1><p>${errorSummary}</p></body></html>";@RequestMapping("/oauth/error")public ModelAndView handleError(HttpServletRequest request) {Map<String, Object> model = new HashMap<String, Object>();Object error = request.getAttribute("error");// The error summary may contain malicious user input,// it needs to be escaped to prevent XSSString errorSummary;if (error instanceof OAuth2Exception) {OAuth2Exception oauthError = (OAuth2Exception) error;errorSummary = HtmlUtils.htmlEscape(oauthError.getSummary());}else {errorSummary = "Unknown error";}model.put("errorSummary", errorSummary);return new ModelAndView(new SpelView(ERROR), model);}
}
这里定义了Whitelabel
对错误的处理方法,可以看到程序通过oauthError.getSummary()
来获取错误信息,我们再次访问这个url并开启动态调试:
http://localhost:8080/oauth/authorize?response_type=token&client_id=acme&redirect_uri=${2334-1}
请求中的${2334-1}
已经被带入了errorSummary
中,然后errorSummary
被装入model
中,再用SpelView
进行渲染。
我们跟进SpelView
到spring-security-oauth/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java
中第21-54行:
class SpelView implements View {...public SpelView(String template) {this.template = template;this.context.addPropertyAccessor(new MapAccessor());this.helper = new PropertyPlaceholderHelper("${", "}");this.resolver = new PlaceholderResolver() {public String resolvePlaceholder(String name) {Expression expression = parser.parseExpression(name);Object value = expression.getValue(context);return value == null ? null : value.toString();}};}...public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)throws Exception {...String result = helper.replacePlaceholders(template, resolver);...}
}
可以看到在render
时通过helper
取${}
中的值作为表达式,再用parser.parseExpression
来执行,跟进一下replacePlaceholders
这个函数,在/org/springframework/util/PropertyPlaceholderHelper.class
第47-56行:
public String replacePlaceholders(String value, final Properties properties) {Assert.notNull(properties, "\'properties\' must not be null");return this.replacePlaceholders(value, new PropertyPlaceholderHelper.PlaceholderResolver() {public String resolvePlaceholder(String placeholderName) {return properties.getProperty(placeholderName);}});
}
这个函数是个递归,也就是说如果表达式的值中有${xxx}
这样形式的字符串存在,就会再取xxx
作为表达式来执行。
我们看动态调试的结果:
首先因为传入了${errorSummary}
,取errorSummary
作为表达式来执行,继续执行程序:
由于errorSummary
中存在${2334-1}
,所以又取出了2334-1
作为表达式来执行,从而触发了漏洞。所以从这里可以看出,漏洞的关键点在于这个对表达式的递归处理使我们可控的部分也会被当作表达式执行。
3.补丁分析
可以看到在第一次执行表达式之前程序将$
替换成了由RandomValueStringGenerator().generate()
生成的随机字符串,也就是${errorSummary} -> random{errorSummary}
,但是这个替换不是递归的,所以${2334-1}
并没有变。
然后创建了一个helper
使程序取random{}
中的内容作为表达式,这样就使得errorSummary
被作为表达式执行了,而${2334-1}
因为不符合random{}
这个形式所以没有被当作表达式,从而也就没有办法被执行了。
不过这个Patch有一个缺点:RandomValueStringGenerator
生成的字符串虽然内容随机,但长度固定为6,所以存在暴力破解的可能性。
0x02 修复方案
- 使用1.0.x版本的用户应放弃在认证通过和错误这两个页面中使用
Whitelabel
这个视图。 - 使用2.0.x版本的用户升级到2.0.10以及更高的版本
靶机平台:
https://vulhub.org/#/environments/spring/CVE-2016-4977/
spring security oauth rce (cve-2016-4977) 漏洞分析相关推荐
- Spring Security OAuth 2开发者指南译
Spring Security OAuth 2开发者指南译 介绍 这是用户指南的支持OAuth 2.0.对于OAuth 1.0,一切都是不同的,所以看到它的用户指南. 本用户指南分为两部分,第一部分为 ...
- Spring Security OAuth笔记
因为工作需要,系统权限安全方面可能要用到Spring Security OAuth2.0,所以,近几天了解了一下OAuth相关的东西.目前好像还没有系统的学习资料,学习主要是通过博客,内容都是大同小异 ...
- 单点登录(shiro与Spring Security OAuth 2.0的集成)
单点登录(shiro与Spring Security OAuth 2.0的集成) shiro项目采用ruoyi,OAuth采用pig 若依:https://gitee.com/y_project/Ru ...
- Spring Security——OAuth 2.0 Client自动配置源代码分析
基本概念 OAuth2.0:OAuth2.0是OAuth协议的延续版本,但不向前兼容OAuth 1.0(即完全废止了OAuth1.0). OAuth 2.0关注客户端开发者的简易性.要么通过组织在资源 ...
- Spring Security——OAuth 2.0登录——Google,GitHub,Facebook和Okta
基本概念 OAuth 2.0登录:OAuth 2.0登录功能为应用程序提供了使用户能够通过使用其在OAuth 2.0提供程序(例如GitHub)或OpenID Connect 1.0提供程序(例如Go ...
- java hipster!_通过Java Hipster升级Spring Security OAuth和JUnit测试
java hipster! "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权 ...
- 通过Java Hipster升级Spring Security OAuth和JUnit测试
"我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证. 使用单元 ...
- 将JWT与Spring Security OAuth结合使用
1.概述 在本教程中,我们将讨论如何使用Spring Security OAuth2实现来使用JSON Web令牌. 我们还将继续构建此OAuth系列的上一篇文章. 2. Maven配置 首先,我们需 ...
- Spring Cloud Gateway远程代码执行CVE-2022-22947漏洞分析及复现
0x01 漏洞描述 Spring Cloud Gateway 是基于 Spring Framework 和 Spring Boot 构建的 API 网关,它旨在为微服务架构提供一种简单.有效.统一的 ...
最新文章
- 博士申请 | ​英属哥伦比亚大学李霄霄助理教授招收全奖博士生、硕士生
- 缓存和数据库一致性问题,看这篇就够了
- java带参方法上机一_Java带参方法的总结
- 【Win32 API学习】模拟键盘输入和鼠标输入
- linux下mysql5.7的安装教程_linux下mysql 5.7.18安装教程 邯郸
- 曾遭闪电贷攻击的Origin将重新推出稳定币OUSD
- 闪耀在UNIX传奇往事中的启示,UNIX见证者带你一览究竟
- 怎么在Linux系统下使用NTFS的U盘或者是分区以及移动硬盘-使用工具NTFS-3G
- 如何快速成为一个运维工程师
- ITIL 2011服务管理与认证读书笔记一——IT服务管理与ITIL
- 讲讲MS08067红队培训班中的“毕业实战对抗”环节 + 视频
- 2020 IDEA插件无法安装问题
- VBA字典(详解,示例)
- 2022-Arch安装(详细)
- KEIL4 的操作技巧
- macbook pro 怎么打大写字母
- 安装Dev c++后,编译文件出现未编译的解决方法
- Python3 math模块以及运算优先级
- 全球及中国数字温度传感器行业商业模式分析及投资风险预测2022年版
- 让子盒子在父盒子中垂直居中的七个方法
热门文章
- mysql page header_MySQL系列:innodb源码分析之page结构解析
- FD.io/VPP — VPP 的配置与运行
- Kong APIGW — 基本操作
- DPDK — IGB_UIO,与 UIO Framework 进行交互的内核模块
- DPDK — 安装部署(CentOS 7)
- Python 笔试集(4):True + True == ?
- 博科300交换机不中断(non-disruptive)固件升级
- Docker swarm 集群搭建
- word标题文字居中浅谈
- promise-async-await