【转载】漏洞分析Jira未授权SSRF漏洞(CVE-2019-8451)

漏洞背景

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

Jira 的/plugins/servlet/gadgets/makeRequest资源存在SSRF漏洞,原因在于JiraWhitelist这个类的逻辑缺 陷,成功利用此漏洞的远程攻击者可以以Jira服务端的身份访问内网资源。经分析,此漏洞无需任何凭据即可触发。

影响范围

< 8.4.0

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

修复建议 

升级到8.4.0及以上版本。

漏洞分析

两个关键信息点:

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

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

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

然而通过这一点并没有搜出来直接到漏洞点的地方。换另一条思路,搜索: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

至此终于定位到了处理具体请求的地方。

跟 进这个类atlassian-jira/WEB-INF/atlassian-bundled-plugins/atlassian-gadgets- opensocial-plugin-4.3.9.jar!/com/atlassian/gadgets/shindig/servlet /XsrfMakeRequestServlet的doGet方法。

可以看到这里对请求中的请求头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)。

漏洞利用

 利用POC:

#coding:utf-8
import requests

host = ‘http://xx.xx.xx.xx:8080’
header = Unknown macro: { ‘X-Atlassian-Token’}

url = host + ‘/plugins/servlet/gadgets/makeRequest?url=’host’@oa.cnsuning.com/’
html = requests.get(url = url,headers = header)
print html.text

漏洞修复

1、升级至8.4.0或其以后版本

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

2、如无法升级版本,建议可从nginx 配置禁止访问路径  

     /plugins/servlet/gadgets/makeRequest

参考

本博主佛系人生,不喜勿喷

Leave a Reply

Your email address will not be published. Required fields are marked *