Java SSRF案例

wen java案例 3

Java SSRF案例深度解析:从理论到实战的完整指南

文章导读

  • 什么是SSRF漏洞:理解服务器端请求伪造的核心原理
  • Java应用中的SSRF风险:为什么Java项目容易中招
  • 真实案例剖析:5个企业级Java SSRF漏洞实例
  • 攻击手法详解:从URL伪造到内网渗透
  • 防御方案与最佳实践:开发人员必须掌握的防护策略
  • FAQ问答环节:解答常见疑惑

什么是SSRF漏洞

SSRF(Server-Side Request Forgery,服务器端请求伪造) 是一种利用服务器作为跳板发起请求的安全漏洞,攻击者通过控制服务器上的某些功能,让服务器向攻击者指定的内部或外部地址发送请求。

Java SSRF案例

正常的请求流程是:用户 -> 服务器 -> 目标资源,而SSRF攻击则是:攻击者 -> 服务器(伪装成正常请求)-> 恶意目标(如内网数据库)

在Java开发中,以下场景尤其容易引入SSRF漏洞:

  • 文件下载/预览功能
  • API代理转发
  • 图片处理服务
  • 数据采集爬虫
  • 回调地址验证

Java应用中的SSRF风险

为什么Java开发者需要特别警惕SSRF?因为Java的标准库和常用框架都提供了强大的网络请求能力,但同时也带来了更多攻击面。

String url = request.getParameter("url");
URL obj = new URL(url);
BufferedReader in = new BufferedReader(new InputStreamReader(obj.openStream()));
// 危险!以上代码直接使用用户输入的URL,未做任何校验

当开发者使用HttpURLConnectionHttpClientRestTemplate等工具时,如果不对请求的目标地址进行限制,就可能导致SSRF漏洞。


真实案例剖析

案例1:文件预览功能的SSRF

漏洞描述: 某企业级文档系统提供"通过URL预览文档"功能,用户输入http://example.com/doc.pdf,服务器下载并展示文档内容。

攻击过程: 攻击者输入http://127.0.0.1:8080/admin/secret.txt,服务器错误地请求了本地管理接口,暴露了敏感文件。

漏洞代码

public Document previewFile(String urlString) {
    URL url = new URL(urlString);
    // 未做任何IP/域名校验
    return readDocument(url.openStream());
}

案例2:图片处理服务的SSRF

漏洞描述: 某博客系统的头像上传功能,支持通过URL拉取图片并生成缩略图。

攻击过程: 攻击者构造请求:http://10.0.0.1:3306,服务器竟然尝试连接内部数据库,导致连接信息泄露。

漏洞代码

BufferedImage image = ImageIO.read(new URL(urlString));
// ImageIO会尝试连接到任何URL,包括内网IP

案例3:API网关代理的SSRF

漏洞描述: 微服务架构中的API网关提供请求转发功能,用户可指定目标服务地址。

攻击过程: 攻击者利用file:///etc/passwd协议读取服务器本地文件。

技术细节: Java的URL类默认支持多种协议,包括fileftpgopher等,攻击者甚至可以利用gopher://协议构造复杂的HTTP请求包。

案例4:Spring Boot Actuator的SSRF

漏洞描述: 某应用使用Spring Boot Actuator的/actuator/gateway/routes接口动态添加路由。

攻击过程: 攻击者通过POST请求添加一条指向内网Redis服务的路由,随后访问该路由获取敏感数据。

案例5:回调URL验证绕过

漏洞描述: 支付系统在处理回调时,会验证"通知URL"是否属于支付服务商。

攻击过程: 攻击者使用DNS重绑定技术(如1e100.cn0.0.1的短时间映射),绕过域名白名单验证,成功让服务器请求内网接口。


攻击手法详解

常见攻击向量:

  1. 内网资源探测:扫描127.0.0.1/8、10.0.0.0/8等私有IP段
  2. 本地文件读取:使用file:///etc/passwd读取服务器文件
  3. 云元数据攻击:请求http://169.254.169.254/latest/meta-data/获取云服务凭证
  4. 协议转换攻击:利用gopher://redis:6379/_*...直接操作Redis
  5. DNS重绑定:利用DNS解析的时间差绕过URL校验

高级技巧:

  • URL解析差异:利用http://google.com#@evil.com在Java和浏览器中解析结果不同
  • 编码绕过:使用URL编码、Unicode编码混淆目标地址
  • 302跳转滥用:让服务器先访问白名单域名,再跳转到恶意地址

防御方案与最佳实践

输入验证(必须做!)

public boolean isValidUrl(String urlString) {
    try {
        URL url = new URL(urlString);
        String host = url.getHost();
        // 禁止内网IP
        InetAddress addr = InetAddress.getByName(host);
        if (addr.isSiteLocalAddress() || addr.isLoopbackAddress()) {
            return false;
        }
        // 仅允许HTTP/HTTPS
        String protocol = url.getProtocol();
        if (!"http".equals(protocol) && !"https".equals(protocol)) {
            return false;
        }
        return true;
    } catch (Exception e) {
        return false;
    }
}

白名单策略

推荐做法:维护一个可访问的域名/IP白名单,而不是黑名单。

限制网络访问

// 使用禁止重定向的HttpClient
HttpClient client = HttpClient.newBuilder()
    .followRedirects(HttpClient.Redirect.NEVER)
    .build();

禁用危险协议

// 设置URLStreamHandler过滤器
URL.setURLStreamHandlerFactory(protocol -> {
    if ("file".equals(protocol) || "jar".equals(protocol)) {
        throw new UnsupportedOperationException("Protocol not allowed");
    }
    return null;
});

网络隔离

  • 使用防火墙限制服务器对外部网络的访问
  • 配置iptables规则禁止访问内网地址段
  • 使用容器化技术限制请求范围

安全审计

定期扫描代码中的网络请求逻辑,使用Fortify、CodeQL等工具进行自动化检测。


FAQ问答环节

Q1:SSRF和CSRF有什么区别? A:SSRF是服务器向攻击者指定的地址发起请求,而CSRF是攻击者诱导用户在自己的已登录状态下执行操作,SSRF更危险,因为它可以触及内网资源。

Q2:Java中HttpURLConnection默认会跟随重定向吗? A:是的,HttpURLConnection.setFollowRedirects(true)是默认设置,攻击者可以利用这个特性进行SSRF攻击。

Q3:为什么DNS重绑定能绕过白名单校验? A:因为DNS查询结果有TTL缓存时间,攻击者可以让域名在前一次查询时返回白名单IP,后一次查询时返回内网IP,Java在连接建立和域名解析之间存在时间差,导致校验失效。

Q4:如何处理第三方CDN或服务商的合法回调? A:可以使用签名验证机制(如HMAC)代替简单的IP白名单,同时配合日志审计,检测异常的回调来源。

Q5:有没有好的开源工具检测Java SSRF? A:推荐使用FindSecBugs(SpotBugs插件)和OWASP ZAP,代码层面可以使用Spring SecurityRequestDataValueProcessor进行统一校验。


你应该对Java SSRF漏洞有了全面认识。修复SSRF的核心原则是"最小权限"——只给必要的访问权限,并且永远不要相信用户输入的网络地址。 在实际开发中,建议结合代码审查和安全测试,建立多层防护体系。

上一篇Java XXE案例

下一篇SpEL注入案例

抱歉,评论功能暂时关闭!