Atlassian简介
以下来自Atlassian中文官方微信公众号。
关于Atlassian:全球领先的软件开发和协作平台,为全球11万家企业提供创新的力量。全球前100强公司有超过90%的企业都在使用Atlassian的产品。其明星软件Jira Software为全球敏捷团队的首选软件开发工具,帮助开发团队规划、追踪和发布世界一流的软件。Atlassian的Marketplace拥有数千款不同功能的应用程序,可帮助您自定义和扩展Atlassian的功能。
Atlassian的全球客户包括:HSBC、摩根士丹利、耐飞、宝马、奔驰、耐克、Oracle、GSK,Airbnb、CSIRO、特斯拉、Autodesk、eBay、丰田等。
Atlassian的中国客户包括:百度、华为、联想、滴滴、京东、360企业安全、小米、顺丰、摩拜、招商银行、民生银行、中信银行、平安证券、泰康人寿、中华保险、众安保险等。
参考
- Atlassian:一家没有销售团队,不靠融资做到百亿美元市值的技术公司
- Atlassian 这家公司的产品为什么这么火?
- 协同软件供应商Atlassian估值超30亿美元
- 非典型硅谷式创业 科技公司Atlassian的奇迹
- 中国移动通信研究院:为什么选择Atlassian项目管理及协作工具
- Atlassian中国封面人物 | 李晓东,打造民生银行软件工程平台
- 拐点临近 – 美国国防部 Atlassian 应用程序的扩展之路
Atlassian核心产品简介
Atlassian服务端软件主要有
- Jira(缺陷跟踪管理系统。该系统主要用于对工作中各类问题、缺陷进行跟踪管理)
- Confluence(企业知识管理与协同软件,也可以用于构建企业WiKi)
- Bitbucket(Git代码托管解决方案)
其中最著名的是Jira和Confluence。很多大厂包括(Apache的issue)用Jira跟踪bug和漏洞,也有很多大厂用Confluence作为一个在线协作文档编写的工具。
Jira相关背景知识
背景知识主要内容翻译自官方文档。
WebWork
Jira使用MVC框架WebWork(不同于Struts 2)来处理用户发起的WEB请求。每个请求都是使用WebWork action来处理,在其中又使用了其他的utility and Manager classes来完成一个任务。
作为响应返回给客户端的HTML大部分都是View层的JSP生成的。
URL中的”.jspa”后缀标识其后端对应的是一个JSP文件。
在Jira中,URL到Java类的映射关系是通过Webwork 1.x框架来完成的。其文档可以参考:http://opensymphony.com/webwork_old/src/docs/manual
而在Confluence, Bamboo and Crowd中,已经被Webwork 2所取代。
classes和URL的对应关系在actions.xml文件中声明了
src/webapp/WEB-INF/classes/actions.xml
其典型的样子大概长这样:
<!-- Workflow Transitions -->
<action name="admin.workflow.ViewWorkflowTransition" alias="ViewWorkflowTransition" roles-required="admin">
<view name="success">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
<command name="moveWorkflowFunctionUp" alias="MoveWorkflowFunctionUp">
<view name="error">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
<view name="success">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
</command>
<command name="moveWorkflowFunctionDown" alias="MoveWorkflowFunctionDown">
<view name="error">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
<view name="success">/secure/admin/views/workflow/viewworkflowtransition.jsp</view>
</command>
</action>
详细参考:
https://developer.atlassian.com/server/jira/platform/webwork/
注意几点:
- 每个action都有一个
alias
属性,其实就是你在浏览器看到的URL的一部分。而name
属性就是这个alias对应的Java类。 - command元素的name属性可以在URL中加上
!commandName
作为其后缀,然后需要在对应的Action类中实现doCommandName()
方法。 - 如果action中没有指定
roles-required
的值,则此action需要自行处理其权限问题,否则此action可以被任意用户访问。
Command元素是可选的,如果同一个Action需要处理多个交互,就会用到command。一般带有command的URL长这样:
SomeAction!myCommand.jspa
然后其在Action类中是这样实现的。
public String doMyCommand() {
// implement the command logic here
return "someview";
}
当没有指定command的时候,Action中对应的处理方法是:doExecute
原文讲得很清楚,看原文就可以了。
Jira登录认证框架(Seraph)
Seraph是一个开源认证框架,主要由Atlassian开发和维护。
Jira、Confluence的登录认证是都由Seraph来负责的。
Seraph是通过Servlet的Filter实现的。
Seraph的功能只是用来在给定一个Web请求的情况下,将该请求与特定用户相关联。它支持多种认证方式:
- HTTP Basic认证
- 基于表单的认证:基于Cookie、(ie. redirect to an internal or external login form), and looking up credentials already stored in the user’s session (e.g. a cookie set by a SSO system).
Seraph本身并不进行用户管理,它只是检查请求中的登录凭证,然后将用户管理的功能(查找某用户,查看某用户的密码是否正确)指派给Jira的用户管理系统(内置的Crowd)处理。Crowd本来是Atlassian的身份管理及单点登录工具。而Jira and Confluence都内置了一部分Crowd的核心模块,用于统一的用户管理。
如果想将单点登录(SSO)功能集成到Jira中,需要实现一个自定义的Seraph authenticator。很多客户也都是这样做的,因为Jira本身并没有集成单点登录系统。如果将Crowd集成到Jira中,参考:https://confluence.atlassian.com/crowd/integrating-crowd-with-atlassian-jira-192625.html
Seraph 由几个核心元素组成:
- Security Service
Security services用于确定特定的HTTP请求需要哪些角色的权限。
Seraph有两个security services:thePath
service and theWebWork
service.
其中Path Service 用于对URL paths进行安全限定,可通过其自己的xm文件进行配置:seraph-paths.xml。
受限,在security-config.xml配置文件中需要有这样的配置:<service class="com.atlassian.seraph.service.PathService"> <init-param> <param-name>config.file</param-name> <param-value>/seraph-paths.xml</param-value> </init-param> </service>
然后seraph-paths.xml中定义了特定url请求所需要的对应角色:
<seraph-paths> <!-- You can configure any number of path elements --> <path name="admin"> <url-pattern>/admin/*</url-pattern> <role-name>myapp-administrators, myapp-owners</role-name> </path> </seraph-paths>
比如上面这个配置就定义了
/admin/*
这样的url就必须myapp-administrators,myapp-owners这样角色的用户可以访问。
另外WebWork Service需要用actions.xml配置文件来进行配置(前面已经提到了):
<action name="project.AddProject" roles-required="admin">
<view name="input">/secure/admin/views/addproject.jsp</view>
</action>
比如上面这个就表示/secure/admin/views/addproject.jsp
这个url请求的需要admin角色才能操作。
- Interceptor:用于在一些安全事件(登录、注销)的前后执行的一些代码。在Servlet规范下是不可能做的。比如用户登录之后,记录上次登录的日期;用户注销之后清理一些资源;记录用户登录失败的次数。
- Authenticator
Authenticator用于对用户进行认证(authenticate) , 对用户进行登录、注销等操作,以及检查他们的角色权限。 - Controller:进行全局的安全控制开关。
- Role Mapper
如何配置Seraph
可以在两个地方配置Seraph:
Seraph的核心是通过seraph-config.xml来进行配置的。通常放在web应用的WEB-INF/classes
目录下。
<security-config>
<parameters>
<init-param>
<!--
the URL to redirect to when the user tries to access a protected resource (rather than clicking on
an explicit login link). Most of the time, this will be the same value as 'link.login.url'.
- if the URL is absolute (contains '://'), then redirect that URL (for SSO applications)
- else the context path will be prepended to this URL
If '${originalurl}' is present in the URL, it will be replaced with the context-relative URL that the user requested.
This gives SSO login pages the chance to redirect to the original page
-->
<param-name>login.url</param-name>
<param-value>/login.jsp?os_destination=${originalurl}</param-value>
<!-- <param-value>http://example.com/SSOLogin?target=${originalurl}</param-value>-->
</init-param>
<init-param>
<!--
the URL to redirect to when the user explicitly clicks on a login link (rather than being redirected after
trying to access a protected resource). Most of the time, this will be the same value as 'login.url'.
- same properties as login.url above
-->
<param-name>link.login.url</param-name>
<param-value>/secure/Dashboard.jspa?os_destination=${originalurl}</param-value>
<!-- <param-value>http://mycompany.com/SSOLogin?target=${originalurl}</param-value>-->
</init-param>
<init-param>
<!-- URL for logging out.
- If relative, Seraph just redirects to this URL, which is responsible for calling Authenticator.logout().
- If absolute (eg. SSO applications), Seraph calls Authenticator.logout() and redirects to the URL
-->
<param-name>logout.url</param-name>
<param-value>/secure/Logout!default.jspa</param-value>
<!-- <param-value>http://mycompany.com/SSOLogout</param-value>-->
</init-param>
<!-- The key that the original URL is stored with in the session -->
<init-param>
<param-name>original.url.key</param-name>
<param-value>os_security_originalurl</param-value>
</init-param>
<init-param>
<param-name>login.cookie.key</param-name>
<param-value>seraph.os.cookie</param-value>
</init-param>
<!-- Specify 3 characters to make cookie encoding unique for your application, to prevent collisions
if more than one Seraph-based app is used.
<init-param>
<param-name>cookie.encoding</param-name>
<param-value>xYz</param-value>
</init-param>
-->
<!-- Basic Authentication can be enabled by passing the authentication type as a configurable url parameter.
With this example, you will need to pass http://mycompany.com/anypage?os_authType=basic in the url to enable Basic Authentication -->
<init-param>
<param-name>authentication.type</param-name>
<param-value>os_authType</param-value>
</init-param>
</parameters>
<!-- Determines what roles (permissions) a user has. -->
<rolemapper class="com.atlassian.myapp.auth.MyRoleMapper"/>
<!-- A controller is not required. If not specified, security will always be on
<controller class="com.atlassian.myapp.setup.MyAppSecurityController" />
-->
<!-- Logs in users. Must be overridden for SSO apps -->
<authenticator class="com.atlassian.seraph.auth.DefaultAuthenticator"/>
<services>
<!-- Specifies role requirements for accessing specified URL paths -->
<service class="com.atlassian.seraph.service.PathService">
<init-param>
<param-name>config.file</param-name>
<param-value>/seraph-paths.xml</param-value>
</init-param>
</service>
<!-- Specifies role requirements to execute Webwork actions -->
<service class="com.atlassian.seraph.service.WebworkService">
<init-param>
<param-name>action.extension</param-name>
<param-value>jspa</param-value>
</init-param>
</service>
</services>
<interceptors>
<!-- <interceptor class="com.atlassian.myapp.SomeLoginInterceptor"/> -->
</interceptors>
</security-config>
与Seraph相关的,有两个Filter(com.atlassian.seraph.filter.LoginFilter
,com.atlassian.seraph.filter.SecurityFilter
),和一个Servlet(com.atlassian.seraph.logout.LogoutServlet
)是必需放在WEB-INF/web.xml
中的。
<filter>
<filter-name>login</filter-name>
<filter-class>com.atlassian.seraph.filter.LoginFilter</filter-class>
</filter>
<filter>
<filter-name>security</filter-name>
<filter-class>com.atlassian.seraph.filter.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>login</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>security</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>logout</servlet-name>
<servlet-class>com.atlassian.seraph.logout.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>logout</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
Jira的认证(authentication)方式
The Jira Server platform, Jira Software Server, and Jira Service Desk Server REST APIs有以下几种认证方式:
使用Jira产生的Token来进行认证,虽然实现不太方便,但是比较安全。
具体参考:https://developer.atlassian.com/server/jira/platform/oauth/
其实就是在HTTP请求头中加上一个HTTP请求头,这种方式没那么安全,但是在脚本中或者命令行掉REST接口比较好用。
具体参考:https://developer.atlassian.com/server/jira/platform/basic-authentication/
比如CURL就可以这样用:
curl -u username:password -X GET -H "Content-Type: application/json" http://localhost:8080/rest/api/2/issue/createmeta
curl会自动帮你把提供的用户名密码计算加到Header中。
或者你也可以自己计算好之后,把它作为一个HTTP头来请求。
其实就是把username:password
进行base64编码,然后加到Authorization: Basic {base64}
即可。
对应到代码中是:
atlassian-jira-software-7.13.0-standalone/atlassian-jira/WEB-INF/lib/atlassian-seraph-3.0.3.jar!/com/atlassian/seraph/filter/HttpAuthFilter.class
继承自PasswordBasedLoginFilter
即先解码base64,然后传入username和password,返回一个UserPasswordPair对象。
new UserPasswordPair(creds.getUsername(), creds.getPassword(), false);
多次连续登陆失败之后,就会出现验证码。
就是用Cookie来进行认证。对应到代码中是:
atlassian-jira-software-7.13.0-standalone/atlassian-jira/WEB-INF/lib/atlassian-seraph-3.0.3.jar!/com/atlassian/seraph/filter/LoginFilter.class
继承自PasswordBasedLoginFilter
表单token的处理(防CSRF)
https://developer.atlassian.com/server/jira/platform/form-token-handling/
想要对某个Action进行 xsrf token验证,需要进行以下步骤:
1、首先定位到某个Action具体执行的方法,一般默认是doExecute()
2、在这个方法前加上注解:@com.atlassian.jira.security.xsrf.RequiresXsrfCheck
如果在自动化脚本中,可以使用以下HTTP头来绕过反CSRF校验机制:
X-Atlassian-Token: no-check
在Jira的java代码中生成token的方法为:
import com.atlassian.jira.security.xsrf.XsrfTokenGenerator;
XsrfTokenGenerator xsrfTokenGenerator = ComponentManager.getComponentInstanceOfType(XsrfTokenGenerator.class);
String token = xsrfTokenGenerator.generateToken(request);
Jira历史漏洞
[CVE-2019-8442]敏感信息泄露漏洞
问题在于CachingResourceDownloadRewriteRule
:
官方issues:
https://jira.atlassian.com/browse/JRASERVER-69241
官方描述:
The CachingResourceDownloadRewriteRule class in Jira before version 7.13.4, and from version 8.0.0 before version 8.0.4, and from version 8.1.0 before version 8.1.1 allows remote attackers to access files in the Jira webroot under the META-INF directory via a lax path access check.
CNNVD描述:
Atlassian Jira 7.13.4之前版本、8.0.4之前版本和8.1.1之前版本中的CachingResourceDownloadRewriteRule类存在安全漏洞。远程攻击者可利用该漏洞访问Jira webroot中的文件。
相应插件下载:
http://central.maven.org/maven2/org/tuckey/urlrewritefilter/4.0.3/urlrewritefilter-4.0.3.jar
其实在lib目录下有。
UrlRewriteFilter
It is a very powerful tool just like Apache’s mod_rewrite.
bug bounty作者描述漏洞细节:
the application takes input from the user, and uses it to build a file path to which the user is forwarded. Since the user controls a part of that path, they may be able to direct themselves to sensitive files, like /META-INF/*, application code, or configuration files, which may contain passwords.
只是把用户提供的url在服务端重写了一下,只能访问一些META-INF目录下的配置文件,不能访问jsp源码。
参考:https://www.cnblogs.com/dennisit/p/3177108.html
然而并不能访问WEB-INF
目录下的文件。
这个漏洞危害较低,看看就好。
confluence之前爆过这个urlrewrite.xml的任意配置文件读取漏洞:
https://www.exploit-db.com/exploits/39170
不过应该后来一起被修复了。
有人提供了一份源码,从注释里看,这里就是为了防止路径穿越的。
[CVE-2019-8444]存储型XSS
影响版本:version < 7.13.6、8.0.0 <= version < 8.3.2
出在评论的地方。
Demo:
更多信息参考Talos的博客:
https://blog.talosintelligence.com/2019/09/vuln-spotlight-atlassian-jira-sept-19.html
[CVE-2018-13404]VerifyPopServerConnection功能SSRF
需要管理员权限才能触发。
这个功能是为了验证邮件服务器的连接的开放性,但是没有对可访问的IP和端口进行限制。这里/secure/admin/VerifySmtpServerConnection!add.jspa
接收了serverName
和port
参数,服务端可以向用户指定的serverName
和port
发起TCP请求,导致了SSRF。
参考了一下Jira的开发文档,知道了一般url后缀对应的是do某方法,然后url前面的是对应的Java的类,所以可以在atlassian-jira-software-7.13.0-standalone/atlassian-jira/WEB-INF/atlassian-bundled-plugins/jira-mail-plugin-10.0.13.jar!/com/atlassian/jira/plugins/mail/webwork/VerifySmtpServerConnection#doAdd
下断点。
最终在atlassian-jira-software-7.13.0-standalone/atlassian-jira/WEB-INF/atlassian-bundled-plugins/base-hipchat-integration-plugin-7.10.3.jar!/javax/mail/Service#connect
调用
connected = this.protocolConnect(host, port, user, password);
完成TCP请求。
[CVE-2019-11581]未授权服务端模板注入漏洞
这个漏洞是Jira爆出的影响力较大的漏洞,是未授权RCE。但是由于这个出漏洞的功能并不是Jira默认开启的,所以影响有限。
详情参考:https://mp.weixin.qq.com/s/d2yvSyRZXpZrPcAkMqArsw
[CVE-2019-8451]未授权SSRF漏洞
在漏洞的利用方面主要是利用了Jira在检查用户提供的url时可以通过@
符进行绕过。在调试方面的困难点在于漏洞的触发需要加上特殊请求头X-Atlassian-Token: no-check
。
详情参考:https://mp.weixin.qq.com/s/_Tsq9p1pQyszJt2VaXd61A
还有一个早前的比较著名的SSRF漏洞,一些bug hunters用这个漏洞攻击AWS获取其meta敏感信息。
[CVE-2017-9506]Atlassian OAuth插件的SSRF漏洞
影响范围:
Atlassian OAuth插件1.3.0 < version < 1.9.12以及2.0.0 < version < 2.0.4
Jira和Confluence中都有这个插件。
Demo:
官方修复commit:
https://bitbucket.org/atlassian/atlassian-oauth/commits/cacd1a118fdc3dc7562d48110340b3de4f0b0af9
调试:
根据文章中的描述,漏洞点在:IconUriServlet
。
从jar包中找字符串:
grep -irn "iconuri" `find .|grep .jar`
然后定位到atlassian-jira-6.4.14-standalone/atlassian-jira/WEB-INF/atlassian-bundled-plugins/atlassian-oauth-service-provider-plugin-1.9.8.jar!/com/atlassian/oauth/serviceprovider/internal/servlet/user/IconUriServlet.class的doGet()
下断点。
可以看到,这里接收了consumerUri
参数之后,直接对该url发起了请求。
参考:http://dontpanic.42.nl/2017/12/there-is-proxy-in-your-atlassian.html
Confluence
Confluence相关背景知识
背景知识主要内容翻译自官方文档。
Confluence的Home目录以及重要目录说明
https://confluence.atlassian.com/doc/confluence-home-and-other-important-directories-590259707.html
-
bin/setenv.bat
或者bin/setenv.sh
文件:
可用来编辑一些CATALINA_OPTS
变量、内存设置、gc变量等系统属性。 -
confluence/WEB-INF/classes/confluence-init.properties
:
在这里指定confluence的home目录。
Confluence的Home目录是Confluence存储其配置信息、搜索索引和附件的目录。 “Home目录”也叫“数据目录”。
其他文件及目录的介绍:
-
confluence.cfg.xml
: 包含confluence的各种属性。
-
attachments/
: confluence上的所有附件都存在这里。如果想要更改,可以编辑confluence.cfg.xml
文件的这个属性attachments.dir
-
backups/
: 每日自动备份(或手动备份)的内容会存放在这里,文件名大概是:daily-backup-YYYY_MM_DD.zip
这个样子。想要更改这个位置,可以编辑confluence.cfg.xml
的这个属性daily.backup.dir
。 -
bundled-plugins/
: 每次confluence重启的时候,都会重新从数据库中读取。所以,删除这个目录下的文件并不能卸载这个插件! -
database/
:主要是用于存储h2数据库文件。 如果使用外部数据库,比如mysql,就不会用到这个目录。
-
index/
: 应用程序大量使用Confluence索引进行内容搜索和最近更新的列表,这对于正在运行的Confluence实例至关重要。 如果此目录中的数据丢失或损坏,可以通过从Confluence中运行完整重新索引来恢复它。 此过程可能需要很长时间,具体取决于Confluence数据库存储的数据量。
-
journal/
: [暂时不太清楚] -
logs/
: confluence的应用日志。 -
plugin-cache/
: Confluence所有的插件都存放在数据库中,但为了能快速访问插件JARs中的类,于是把插件缓存到了这个目录下。当系统安装或者卸载插件的时候会更新这个目录。每次confluence重启的时候,都会重新从数据库中读取。所以,删除这个目录下的文件并不能卸载这个插件!
-
temp/
: 用于一些运行时的功能,比如exporting, importing, file upload and indexing。此目录中的文件是临时文件,可在Confluence关闭时被安全地删除。 Confluence中的daily job会删除不再需要的文件。也可以在confluence.cfg.xml
文件中定义不同的temp目录,然后在webwork.multipart.saveDir
属性中设置新的值 -
thumbnails/
: 存放图片文件的缩略图。 -
shared-home/
: 某些功能的缓存文件,比如Office文件以及PDF预览也放在这个目录下。也用于迁移到Data Center,。
所有其他的数据,包括页面的内容,都是存放在数据库中的。
当Confluence启动的时候,会去confluence-init.properties
文件中寻找Home目录的位置。想要更改Home目录,需要编辑confluence-init.properties
文件的confluence.home
属性。
Confluence的License写在其Home目录(也叫confluecne安装目录)的这个文件里
confluence.cfg.xml
到时候更新这里就行了。
当试用Confluence的时候,默认会使用内嵌的H2 Database
参考:https://confluence.atlassian.com/doc/embedded-h2-database-145098285.html
是以一个home目录下的database/h2db.mv.db
文件形式存在。
Confluence历史漏洞
Confluence的漏洞最早引起国内安全研究者的较大关注应该是那次Confluence的未授权RCE CVE-2019-3396
。
这个功能“小工具连接器”是Confluence自带的。在对某些链接的预览功能的请求中存在一个隐藏参数_template
,攻击者可插入payload造成文件读取,某些版本可以加载指定的任意模板造成代码执行。
深入的分析可以参考Lucifaer大佬的博文:https://lucifaer.com/2019/04/16/Confluence%20%E6%9C%AA%E6%8E%88%E6%9D%83RCE%E5%88%86%E6%9E%90%EF%BC%88CVE-2019-3396%EF%BC%89/
搭建Confluence漏洞环境的过程中发现还是比较方便的,界面风格也比较喜欢,于是我熟悉了它家产品的环境搭建流程,申请license的过程中注册了Atlassian的账号,没想到一两个星期之后的一个晚上凌晨1点,我刚准备睡觉,睡前看了一眼我的Gmail,发现Atlassian给我发了一封邮件通知说Confluence有一个严重漏洞CVE-2019-3398
的安全公告:
于是连夜起来用前几天刚搭好还热乎的环境调试到第二天早上终于把PoC调试出来了。
这个漏洞的触发和payload插入是分开了。需要先通过上传附件的功能将webshell的内容和希望上传到的地方(通过路径穿越)设置好,然后再通过“下载全部附件”的功能把webshell复制到预先设置好的路径下,加载webshell执行任意命令。由于附件文件是存在于Confluence的Home目录下,上传webshell成功的前提是需要知道Confluence的自带Tomcat路径和Confluence的Home路径之间的相对关系,这样才能准确地通过../
把webshell复制到Tomcat路径下被加载。
详情参考:https://xz.aliyun.com/t/4854
Confluence有一个”导出到Word”的功能。而导出的文件内容是基于当前被导出的文档内容的。而这个文档中可以包含文字也可以包含图片。当包含图片时,这个图片的路径可以由用户通过路径穿越指定,导致了这个漏洞的产生。(其实这个导出的文件并不是标准的doc格式,只是微软的Office刚好可以打开而已,如果是用其他客户端可能出错打不开。)
这个漏洞跟CVE-2019-3398有两点类似。第一点,都是需要两次请求才能完成漏洞利用。都是需要先设置好payload,然后再通过下载操作或者导出操作触发漏洞。第二点是payload都是通过路径穿越指定的。
详情参考:https://mp.weixin.qq.com/s/puRrvfqWFVKvQ0hOoVs8lQ
[CVE-2019-3395]WebDAV插件未授权SSRF漏洞
用一句话描述就是,当向受影响的Confluence请求/webdav
开头的url(这个功能是WebDAV插件提供的)时,用户可以指定任意Host请求头(如果Confluence在其与用户之间没有使用Nginx做反向代理验证这个Host头),然后Confluence会向这个Host发起请求,并将这个请求的响应返回给客户端。
详情参考:https://mp.weixin.qq.com/s/URDaO5xZISL0Bosh1nzM7A
以上就是今年Confluence爆出来的重要漏洞了,如果再往前追溯,还可以找到之前的这个信息泄露漏洞。
这个漏洞源于未对REST接口的页面diff功能做权限校验,匿名用户即可访问。
exploit:
https://github.com/allyshka/exploits/blob/c1f5f0dfa2494001e7c3cffabfbf0219b0e35e08/confluence/CVE-2017-7415/README.md
影响范围:
6.0.0 <= version < 6.0.7
cnnvd描述:
Atlassian Confluence 6.0.7之前的6.x版本中存在安全漏洞。远程攻击者可利用该漏洞绕过身份验证,读取任意日志或页面。
直接一个请求:
/rest/tinymce/1/content/<pageId>/draft/diff
可访问任意博客/Pages页面。
比如:
这个页面:http://cqq.com:8090/pages/viewpage.action?pageId=65546
本来需要登录才能访问
而如果通过这个url去访问:
http://cqq.com:8090/rest/tinymce/1/content/65546/draft/diff
可以直接访问到
查看代码:confluence-6.0.6/plugins-osgi-cache/transformed-plugins/confluence-editor-6.0.6_1487721990000.jar!/com/atlassian/confluence/tinymceplugin/rest/PageResource#getDraftDiff
可以发现这个路径是允许匿名用户访问的:
使用6.0.7版本进行测试。
不带Cookie的情况下,发现页面404了。
跟到对应的代码atlassian-confluence-6.0.7/confluence/WEB-INF/atlassian-bundled-plugins/confluence-editor-6.0.7.jar!/com/atlassian/confluence/tinymceplugin/rest/PageResource#getDraftDiff
:
增加了权限校验。若当前用户没有编辑当前页面的权限,则直接响应404。
Bitbucket
Bitbucket历史漏洞
Bitbucket最近比较重要的是以下两个漏洞。CVE-2019-15000 git的参数注入漏洞,和CVE-2019-3397。
Bitbucket最近的漏洞不多,而且我对它也不是很熟悉。最近出的比较严重的漏洞还是CVE-2019-15000
, 由于REST接口的diff功能未对--
这种对于git命令有特殊意义的字符进行过滤,导致了git diff的参数注入,至少可以读取敏感文件的效果。详情参考:https://mp.weixin.qq.com/s/3J-lA0CQylrq2ZY3ZEESiQ
这个漏洞是由rips发现并分析的。利用这个漏洞需要管理员权限。
详情参考:https://blog.ripstech.com/2019/bitbucket-path-traversal-to-rce/
Bitbucket的漏洞可以跟gitlab等git服务解决方案的漏洞进行对比。如果今后它出漏洞很可能还是跟git参数命令相关的。
下面提供一些git参数注入漏洞的例子:
比如Jenkins的Git Client插件的命令执行漏洞CVE-2019-10392
,
git ls-remote -h --upload-pack=calc.exe HEAD
这个也是git ls-remote命令的参数注入漏洞:
https://snyk.io/vuln/npm:git-ls-remote:20160923
git grep --open-files-in-pager=calc.exe master
参考:https://www.leavesongs.com/PENETRATION/escapeshellarg-and-parameter-injection.html
感觉好几个是跟pager相关的。pager是用户指定的一个外部的执行diff、cat等功能的可执行文件的路径。
但是我在git log和git diff命令下没找到。
另外又看到几个git的参数注入的:
https://staaldraad.github.io/post/2019-07-16-cve-2019-13139-docker-build/
使用docker build命令的时候:
PoC:
docker build "git@g.com/a/b#--upload-pack=sleep 5;:"
实际上执行的命令是:
$ git init
$ git remote add git@g.com/a/b
$ git fetch origin "--upload-pack=sleep 5; git@g.com/a/b"
另外还有一个git submodule的命令执行:
https://staaldraad.github.io/post/2018-06-03-cve-2018-11235-git-rce/
利用git hooks实现路径穿越。
less读取文件:
shift + e
,然后输入文件名即可读取这个文件。
less执行命令:
参考:
https://docs.ioin.in/writeup/evi1cg.me/_archives_CVE_2017_8386_html/index.html
比如git-receive-pack --help
命令就用到了less命令,可以用来读取文件和执行命令。
这个产品的漏洞挖掘需要对git的各种参数及其使用场景非常熟悉或有过深入的研究。可以从以下资料展开研究:
Atlassian产品环境搭建
Atlassian家产品的环境搭建都比较类似。会自带一个Tomcat,然后具体产品作为其一个webapp存在。Github上有一份带dockerfile的环境,基本上Atlassian产品的环境都有了。
如果自己在Mac上或者Linux上搭建环境,可以用以下方式,以Jira为例,Confluence类似。找到具体的产品和版本号即可。
$ wget https://product-downloads.atlassian.com/software/jira/downloads/atlassian-jira-software-7.13.0.tar.gz
$ tar zxf atlassian-jira-software-7.13.0.tar.gz
$ cd atlassian-jira-software-7.13.0-standalone/
$ vi atlassian-jira/WEB-INF/classes/jira-application.properties #设置jira的Home目录,这里我设置为
#/home/cqq/jiraHome
$ mkdir /home/cqq/jiraHome # 作为jira的安装目录(不手动创建目录也行,jira会自动创建)
$ conf/server.xml #修改端口,这里我改成8091,与Confluence的8090接近
$ bin/start-jira.sh #启动jira
若想调试,需要修改bin/setenv.sh
:
CATALINA_OPTS="-Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=12346 ${CATALINA_OPTS}" # for debug
CATALINA_OPTS="${GC_JVM_PARAMETERS} ${CATALINA_OPTS}"
export CATALINA_OPTS
如果觉得卡可以把允许的内存设置的大一些:
JVM_MINIMUM_MEMORY="4096m"
JVM_MAXIMUM_MEMORY="4096m"
安装时会选择数据库,如果图方便可以选择内置的h2数据库,也可以自己创建好对应的数据库之后,让Jira连接它即可。我尝试使用了postgresql数据库,可以参考:https://blog.csdn.net/caiqiiqi/article/details/89021367
Bitbucket的设置调试和环境变量稍微有点区别:
下载:https://product-downloads.atlassian.com/software/stash/downloads/atlassian-bitbucket-6.1.1.zip
解压之后设置好JAVA_HOME
环境变量,以及BITBUCKET_HOME
环境变量,
这个是到时候bitbucket的数据被安装到的目录。
vi bin/set-bitbucket-home.sh #设置JAVA_HOME,以及BITBUCKET_HOME环境变量
vi bin/_start-webapp.sh
# DEBUG="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=12346"
bin/start-bitbucket.sh # 启动Bitbucket
Jira、Confluence、Bitbucket的历史版本下载:
- https://www.atlassian.com/software/jira/download-archives
- https://www.atlassian.com/software/confluence/download-archives
- https://www.atlassian.com/software/bitbucket/download-archives
可以选择安装程序进行安装,也可以选择压缩文件解压到本地。
在安装过程中需要输入相应的licnese,如果只是用于测试,可以到Atlassian选择对应的产品,申请试用的license,有效期是一个月。
https://my.atlassian.com/license/evaluation
Atlassian产品最新漏洞获取方式
Atlassian产品主要发布在官方公告和issues页面中。
官方公告一般发高危及以上的漏洞,其他的漏洞会先在issues里提交然后分配CVE编号(安全公告一般也是从issues中来的)。一般监控官方公告页面就可以了。如果想获取最新的可能的漏洞信息,而又不担心误报的话,可以监控issues页面,或者跟着NVD的邮件列表看看有没有Atlassian产品相关的。
- Jira官方公告页面:
https://confluence.atlassian.com/jira/security-advisories-112853939.html - Confluence官方公告页面:
https://confluence.atlassian.com/doc/confluence-security-overview-and-advisories-134526.html - Bitbucket官方公告页面:
https://confluence.atlassian.com/bitbucketserver/bitbucket-server-security-advisories-776640597.html
issues页面:
Atlassian产品漏洞应急
根据这段时间跟进Atlassian产品的漏洞的经验,当一个jira或者confluence的cve出来的时候,可能当时只有漏洞描述,没有复现步骤,需要自己定位到漏洞点。
我一般是通过在相应产品目录下各种文本文件(包括jar包)搜索关键词(忽略大小写)
grep -rni "<关键词>或者关键<path>或者<类名>或者<方法名>" *
或者在其各种jar包中搜索关键字:
grep -rni "关键词" `find . -name *.jar`
或者通过strings工具判断某二进制文件中是否包含某关键词字符串。
可能在WEB-INF/web.xml
中找到url对应的处理类:
比如我通过官方的描述,知道了CVE-2019-8446的触发点是/rest/issueNav/1/issueTable
,那我就搜/rest/issueNav
,然后在WEB-INF/web.xml
中找到了对应的处理类/过滤器名
然后根据过滤器的名字搜索类
再根据类名定位到具体的文件中,可能是jar包形式,也可能是.class文件形式。
然后再去IDEA中下断点。
还有一个办法就是直接去日志里查调用栈(如果有报错的话)
如果只知道一个关键方法的名字,可以先搜它在哪个jar包中
确定jar包之后, 再用反编译工具将jar包反编译你成java代码,再搜索,确定其具体的路径,定位到具体的文件。
参考
- Confluence中文版文档
- There is a proxy in your Atlassian Product! (CVE-2017-9506)
- Jira Architecture overview
- Jira相关背景知识
- Confluence相关背景知识
- Bitbucket相关
- Vulnerability Spotlight: Multiple vulnerabilities in Atlassian Jira
- BitBucket服务器参数注入漏洞(CVE-2019-15000)
- Jira未授权SSRF漏洞(CVE-2019-8451)
- Jira未授权服务端模板注入漏洞(CVE-2019-11581)
- Confluence路径穿越漏洞(CVE-2019-3398)
- Confluence未授权模板注入/代码执行(CVE-2019-3396)
- Confluence 未授权RCE分析(CVE-2019-3396)
- Confluence Pre-Auth SSRF(CVE-2019-3395)
- Confluence敏感信息泄露漏洞(CVE-2019-3394)
- Atlassian products in Docker
- http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-201909-897
- http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-201908-2216
- http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-201909-903
- CVE-2017-9506 – SSRF