[【通过】] CVE-2016-4977 Spring Security OAuth代码执行学习过程

[复制链接]
fuckironman 发表于 2017-9-18 13:20:26 | 显示全部楼层 |阅读模式

|主题 |帖子 |积分

CVE-2016-4977 Spring Security OAuth代码执行学习过程

背景描述
Spring Security OAuth 2016年以前有出一个CVE,这里写一个记录学习的东西。
漏洞详细
Spring Security OAuth官网有CVE-2016-4977的介绍,但是讲的不怎么清楚,就只是说了一下漏洞原理,我们就只知道是因为执行一个SpEL表达式https://pivotal.io/de/security/cve-2016-4977而产生的。看看利用的poc,大概了解一下整个过程。
http://localhost:8080/oauth/authorize?responsetype=token&clientid=acme&redirect_uri=${1-65535}
复现截图
图一.jpg
在这里表达式被成功执行了。
漏洞分析
对比一下补丁的前后,
图二.jpg
可以看到在org.springframework.security.oauth2.provider.endpoint.SelView.java这里是问题之所在。
在程序里断点调试运行,然后发现位于代码String result = this.helper.replacePlaceholders(this.template, this.resolver)运行之后,${1-65535}就执行了
接着在此处来一个断点,里面是spring框架定义的模版
图三.jpg
,然后的全部异常,网页上都是根据该模版来修改的,看这函数定位org.springframework.util.PropertyPlaceholderHelper中,parseStringValue函数为全部异常网页制造函数。
然后给整个函数进行调试,大概理出函数的流程:
图四.jpg
protected String parseStringValue(String strVal, PropertyPlaceholderHelper.PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {
        StringBuilder result = new StringBuilder(strVal);/////////////////// 新建string buffer ,先默认的 <html><body><h1>OAuth Error</h1><p>${errorSummary}</p></body></html>**/
        int startIndex = strVal.indexOf(this.placeholderPrefix);/////////////得到result中${位置,然后后面全部流程就是把异常信息换掉${}中东西,接着把它封装为html流

        while(startIndex != -1) {
            int endIndex = this.findPlaceholderEndIndex(result, startIndex);////////得到}结束点
            if(endIndex != -1) {
                String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);////////提取${}之间字符串
                String originalPlaceholder = placeholder;
                if(!visitedPlaceholders.add(placeholder)) {
                    throw new IllegalArgumentException("Circular placeholder reference \'" + placeholder + "\' in property definitions");
                }

                placeholder = this.parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);///////////再解析一次通过递归调用把${}中的字符一次全部提取
                String propVal = placeholderResolver.resolvePlaceholder(placeholder);/////////////把以上提到${}之间字符串当作参数传递resolvePlaceholder产生异常
                if(propVal == null && this.valueSeparator != null) {
                    ...
                }

                if(propVal != null) {
                    propVal = this.parseStringValue(propVal, placeholderResolver, visitedPlaceholders);/////////////////然后把生成的异常信息再调用parseStringValue函数一次
                    result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
                    ...
        }

        return result.toString();
    }
图五.jpg
SpEL表达式,若函数error="invalid_grant", error_description="Invalid redirect: ${1-65535} does not match one of the registered values: [http://google.com]"里1-65535取出来然后解析。接着1-65535就运行了。这一点和官方补丁描述相同。
总结流程:

第一次进入,系统用默认模版<html><body><h1>OAuth Error</h1><p>${error Summary}</p></body></html>作为函数parseStringValue参数。

函数再把参数里被${}包裹的字符串换成具体异常信息,然后再展现到web前端,具体异常信息就在函数resolvePlaceholder中。
先通过resolvePlaceholder处理,报错信息如下error="invalid_grant", error_description="Invalid redirect: ${1-65535} does not match one of the registered values: [http://google.com]"
系统接着调用parseStringValue函数,把error="invalid_grant", error_description="Invalid redirect: ${1-65535} does not match one of the registered values: [http://google.com]"当作参数交给parseStringValue函数。
函数然后解析${} 的东东1-65535,在传送到resolvePlaceholder函数,resolvePlaceholder就是 SpEL表达式,然后被解析,最终展示到到web前端。
补丁理解:
图六.jpg
它把this.helper = new PropertyPlaceholderHelper("${", “}”);转换成 this.helper = new PropertyPlaceholderHelper( new RandomValueStringGenerator().generate() + “{”, “}”)也就是将$先转换为一个随机数,然后${1-65535}不能解析成SpEL,但RandomValueStringGenerator().generate()就是随机六位数的可以被爆破。比如我们爆出来198232然后http://x.x.x.x:80/oauth/authoriz ... redirect_uri=198232{1-65535}就执行命令了

评分

参与人数 2酒票 +6 收起 理由
管理05 + 5 欢迎加入90!
Admin_CC + 1 欢迎加入90!

查看全部评分

Bsmali4 发表于 2017-9-25 11:18:16 | 显示全部楼层

正式成员|主题 |帖子 |积分 393

本帖最后由 Bsmali4 于 2017-9-25 11:19 编辑

这这么和我之前写的这么像,http://www.codersec.net/2017/09/ ... %E5%88%86%E6%9E%90/
管理05 发表于 2017-9-25 11:23:38 | 显示全部楼层

管理|主题 |帖子 |积分 936

RE: CVE-2016-4977 Spring Security OAuth代码执行学习过程

Bsmali4 发表于 2017-9-25 11:18
这这么和我之前写的这么像,http://www.codersec.net/2017/09/ ... %E5%88%86%E6%9E%90/

已处理
注册邮箱:[email protected]
记录黑名单
删除该用户处理

百里长苏 发表于 2017-9-28 15:39:05 | 显示全部楼层

正式成员|主题 |帖子 |积分 144

RE: CVE-2016-4977 Spring Security OAuth代码执行学习过程

Bsmali4 发表于 2017-9-25 11:18
这这么和我之前写的这么像,http://www.codersec.net/2017/09/ ... %E5%88%86%E6%9E%90/

哥们厉害了。
Blck 发表于 2017-12-5 17:40:38 | 显示全部楼层

正式成员|主题 |帖子 |积分 180

误打误撞,遇到原作者。
快速回复 返回顶部 返回列表