前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security OAuth RCE (CVE-2016-4977) 漏洞分析

Spring Security OAuth RCE (CVE-2016-4977) 漏洞分析

作者头像
Seebug漏洞平台
发布2018-03-29 16:24:39
1.7K0
发布2018-03-29 16:24:39
举报
文章被收录于专栏:Seebug漏洞平台

Author: p0wd3r (知道创宇404安全实验室)

Date: 2016-10-17

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. 环境搭建

代码语言:javascript
复制
docker pull maven  
代码语言:javascript
复制
FROM maven

WORKDIR /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/mymaven

WORKDIR /usr/src/mymaven  
RUN mvn clean install

CMD ["java", "-jar", "./target/demo-0.0.1-SNAPSHOT.jar"]  
代码语言:javascript
复制
docker build -t mvn-spring .  
docker run --rm --name mvn-spring-app -p 8080:8080 mvn-spring  

2.漏洞分析

首先我们查看src/resources/application.properties的内容来获取clientid和用户的密码:

接着我们访问这个url:

代码语言:javascript
复制
http://localhost:8080/oauth/authorize?response_type=token&client_id=acme&redirect_uri=hellotom  

其中client_id就是我们前面获取到的,然后输入用户名user,密码填上面的password

点击登录后程序会返回这样一个页面:

可以看到由于hellotom对于redirect_uri来说是不合法的值,所以程序会将错误信息返回并且其中带着hellotom,那么这个不合法的值可不可以是一个表达式呢?我们再访问这个url:

代码语言:javascript
复制
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行:

代码语言:javascript
复制
@FrameworkEndpointpublic 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 XSS        
        String 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并开启动态调试:

代码语言:javascript
复制
http://localhost:8080/oauth/authorize?response_type=token&client_id=acme&redirect_uri=${2334-1}  

请求中的${2334-1}已经被带入了errorSummary中,然后errorSummary被装入model中,再用SpelView进行渲染。

我们跟进SpelViewspring-security-oauth/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/SpelView.java中第21-54行:

代码语言:javascript
复制
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行:

代码语言:javascript
复制
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以及更高的版本

0x03 参考

https://www.seebug.org/vuldb/ssvid-92474

http://secalert.net/#CVE-2016-4977

https://pivotal.io/de/security/cve-2016-4977

https://github.com/spring-projects/spring-security-oauth/commit/fff77d3fea477b566bcacfbfc95f85821a2bdc2d

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration.java

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Seebug漏洞平台 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x00 漏洞概述
    • 1.漏洞简介
      • 2.漏洞影响
        • 3.影响版本
        • 0x01 漏洞复现
          • 1. 环境搭建
            • 2.漏洞分析
              • 3.补丁分析
              • 0x02 修复方案
              • 0x03 参考
              相关产品与服务
              容器镜像服务
              容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档