Jira未授权SSRF漏洞(CVE-2019-8451)

Posted by caiqiqi on 2019-11-03

原文:
https://mp.weixin.qq.com/s/_Tsq9p1pQyszJt2VaXd61A

漏洞背景

前一段时间Atlassian的bug跟踪里公开了一个Jira未授权SSRF漏洞,看一下官方的描述:

影响范围

< 8.4.0

官方说在7.6版本中引入,在8.4.0中修复。但是我经过测试发现至少6.4.14版本也受此漏洞影响。目前多数Jira是在8.4.0版本以下的。

漏洞分析

两个关键信息点:

  • 漏洞点在/plugins/servlet/gadgets/makeRequest
  • 原因在于JiraWhitelist这个类的逻辑缺陷

首先上直接去访问这个url,然而告诉我404:

有点绝望,都404了,还看啥!
然后开始按照以往Jira/Confluence的漏洞搜索方法,

grep -rn "makeRequest" *

然而通过这一点并没有搜出来直接到漏洞点的地方。
换另一条思路,搜索:JiraWhitelist

找到了这个类是在atlassian-jira/WEB-INF/classes目录下,于是在IDEA中直接将这个目录加到Library中(否则调试无法进入),然后在其可疑方法allows下断点:

发起一个/plugins/servlet/gadgets/makeRequest的请求,但是这个时候没能直接触发到断点。后来找到了一个跟这个比较像的url:/plugins/servlet/gadgets/dashboard-diagnostics深入跟进了一下,发现原来是所有/plugins/servlet开头的url会交给某一个类处理,而这是在web.xml中配置的:


这里url中的/plugins/servlet匹配到了servlet-module-container-servlet对应的servlet为:com.atlassian.jira.plugin.servlet.ServletModuleContainerServlet
然后后面通过request.getPathInfo()来获取url后面的内容。参考:https://blog.csdn.net/turkeyzhou/article/details/3270289

获取到之后,去一个Map里查找:


这个pathInfo对应的Servlet descriptor

然后根据这个descriptor找到具体的Servlet类:


这里显示已经找到了:


这个Servlet为com.atlassian.gadgets.shindig.servlet.XsrfMakeRequestServlet。至此终于定位到了处理具体请求的地方。
可以看到这里对请求中的请求头X-Atlassian-Token: no-check做了判断,如果请求中没有这个请求头,则直接响应404了。

这个请求头是官方提供的一种绕过Jira自身CSRF防御的方式,用于告诉Jira不对此请求进行CSRF防御,方便在自动化脚本中使用。具体介绍可以参考:
https://developer.atlassian.com/server/jira/platform/form-token-handling/

到这里就解释了为什么直接访问这个url会响应404了。
带上这个请求头,继续调试。
跟进其父类即org.apache.shindig.gadgets.servlet.MakeRequestServletdoGet方法。由于这个包我没有在Jira提供的jar包中找到,最后去这里:
https://repo1.maven.org/maven2/org/apache/shindig/shindig-gadgets/2.5.2/shindig-gadgets-2.5.2.jar

找了一个jar包作为Library供IDEA调试。
最后跟进到了atlassian-jira/WEB-INF/classes/com/atlassian/jira/dashboard/JiraWhitelist#allows方法中,对请求中的url参数进行判断。如果请求中的url满足以Jira服务的canonicalBaseUrl开头(比如我的Jira是http://cqq.com:8091),


若满足,则认为这个url符合白名单的规则:
这里应该就是漏洞描述中atlassian-jira/WEB-INF/classes/com/atlassian/jira/dashboard/JiraWhitelist#allows方法的逻辑缺陷了。

符合白名单的规则就接着使用atlassian-jira-6.4.14-standalone/atlassian-jira/WEB-INF/lib/httpclient-4.3.6.jar!/org/apache/http/client/utils/URIUtils这个工具类将url中的协议名、Host名、端口等提取出来


通过跟踪代码,发现它只判断了url是否以 <jira服务的协议://ip:port> 开头,所以这个poc中能进行SSRF的协议只能是HTTP(s)。

最终的结果:

漏洞修复

在8.4.0版本中,使用这里使用了java.net.URI#getHost,getPort等方法获取主机名和端口号,与Jira服务的协议、主机名、端口进行逐个对比。若不符合,返回False。

PoC

GET /plugins/servlet/gadgets/makeRequest?url=http%3A%2F%2Fjira.com%3A8080%40evil.com:port/path HTTP/1.1
Host: jira.com:8080
X-Atlassian-Token: no-check
Connection: close

https://github.com/shadowsock5/Poc/blob/master/Jira/CVE-2019-8451.py

参考