【Java 代码审计入门-04】SSRF 漏洞原理与实际案例介绍
字数 1263 2025-08-25 22:59:03

Java代码审计入门:SSRF漏洞原理与实际案例

0x00 前言

本教程是Java代码审计入门系列的第四篇,专注于SSRF(Server-Side Request Forgery)漏洞的原理分析和实际案例。SSRF是OWASP TOP 10中的常见漏洞,攻击者通过构造恶意请求,利用服务端发起非预期的网络请求,通常用于探测或攻击内网服务。

0x01 环境准备

测试源码可从GitHub获取:

https://github.com/cn-panda/JavaCodeAudit

项目结构是一个简单模拟HTTP请求的实现,可用于SSRF漏洞测试。

0x02 SSRF漏洞原理

基本概念

SSRF是攻击者构造恶意payload传给服务端,服务端执行后造成的漏洞。Java中网络请求支持多种协议:

  • http
  • https
  • file
  • ftp
  • mailto
  • jar
  • netdoc

相比PHP,Java中的SSRF利用有一定局限性,常见利用方式:

  1. 使用http/https协议探测端口、暴力穷举
  2. 使用file协议读取/下载任意文件

Java网络请求流程

典型的有漏洞代码示例:

String url = request.getParameter("url");
String htmlContent;
try {
    URL u = new URL(url);
    URLConnection urlConnection = u.openConnection();
    HttpURLConnection httpUrl = (HttpURLConnection)urlConnection;
    BufferedReader base = new BufferedReader(new InputStreamReader(httpUrl.getInputStream(), "UTF-8"));
    StringBuffer html = new StringBuffer();
    while ((htmlContent = base.readLine()) != null) {
        html.append(htmlContent);
    }
    base.close();
    print.println("<b>端口探测</b></br>");
    print.println("<b>url:" + url + "</b></br>");
    print.println(html.toString());
    print.flush();
} catch (Exception e) {
    e.printStackTrace();
    print.println("ERROR!");
    print.flush();
}

代码解析:

  1. URL对象用openConnection()打开连接,获得URLConnection类对象
  2. getInputStream()获取字节流
  3. InputStreamReader()将字节流转化成字符流
  4. BufferedReader()将字符流以缓存形式输出,快速获取网络数据流
  5. 最终输出到浏览器

0x03 SSRF漏洞利用

1. 端口探测

测试环境

  • 本机:127.0.0.1 (Java+Tomcat)
  • 虚拟机:192.168.159.134 (PHP+Apache)

攻击场景
假设外网可以访问本机地址,但不能直接访问虚拟机地址。利用本机的SSRF漏洞探测虚拟机开放的端口。

结果分析

  • 如果端口开放http/https服务,返回正常内容
  • 如果端口未开放http/https服务,返回错误信息

通过不同的返回结果,可以判断目标端口是否开放。

2. 任意文件读取/下载

修改上述代码,移除HttpURLConnection的强制转换:

String url = request.getParameter("url");
String htmlContent;
try {
    URL u = new URL(url);
    URLConnection urlConnection = u.openConnection();
    BufferedReader base = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
    StringBuffer html = new StringBuffer();
    while ((htmlContent = base.readLine()) != null) {
        html.append(htmlContent);
    }
    base.close();
    print.println(html.toString());
    print.flush();
} catch (Exception e) {
    e.printStackTrace();
    print.println("ERROR!");
    print.flush();
}

利用方式
使用file协议读取任意文件,例如:

file:///etc/passwd

0x04 实际案例

CVE-2019-9827

参考链接:

0x05 防御措施

  1. 输入验证

    • 对用户输入的URL进行严格校验
    • 使用白名单机制限制允许的协议和域名
  2. 网络层防护

    • 禁止访问内网IP段
    • 限制请求的目标端口
  3. 代码层防护

    • 避免直接使用用户输入构造URL
    • 使用安全的网络请求库
  4. 环境加固

    • 配置Java安全策略
    • 限制应用程序的网络访问权限

0x06 总结

SSRF漏洞在Java应用中危害严重,特别是能够访问内网资源的应用。审计时应重点关注:

  1. 直接使用用户输入构造URL的地方
  2. 网络请求是否有限制和过滤
  3. 是否使用了不安全的协议(如file)
  4. 是否有对内网地址的访问控制

通过本教程的学习,您应该掌握了Java中SSRF漏洞的基本原理、利用方式和防御措施,能够在代码审计中识别此类漏洞。

Java代码审计入门:SSRF漏洞原理与实际案例 0x00 前言 本教程是Java代码审计入门系列的第四篇,专注于SSRF(Server-Side Request Forgery)漏洞的原理分析和实际案例。SSRF是OWASP TOP 10中的常见漏洞,攻击者通过构造恶意请求,利用服务端发起非预期的网络请求,通常用于探测或攻击内网服务。 0x01 环境准备 测试源码可从GitHub获取: 项目结构是一个简单模拟HTTP请求的实现,可用于SSRF漏洞测试。 0x02 SSRF漏洞原理 基本概念 SSRF是攻击者构造恶意payload传给服务端,服务端执行后造成的漏洞。Java中网络请求支持多种协议: http https file ftp mailto jar netdoc 相比PHP,Java中的SSRF利用有一定局限性,常见利用方式: 使用http/https协议探测端口、暴力穷举 使用file协议读取/下载任意文件 Java网络请求流程 典型的有漏洞代码示例: 代码解析: URL 对象用 openConnection() 打开连接,获得 URLConnection 类对象 用 getInputStream() 获取字节流 InputStreamReader() 将字节流转化成字符流 BufferedReader() 将字符流以缓存形式输出,快速获取网络数据流 最终输出到浏览器 0x03 SSRF漏洞利用 1. 端口探测 测试环境 : 本机:127.0.0.1 (Java+Tomcat) 虚拟机:192.168.159.134 (PHP+Apache) 攻击场景 : 假设外网可以访问本机地址,但不能直接访问虚拟机地址。利用本机的SSRF漏洞探测虚拟机开放的端口。 结果分析 : 如果端口开放http/https服务,返回正常内容 如果端口未开放http/https服务,返回错误信息 通过不同的返回结果,可以判断目标端口是否开放。 2. 任意文件读取/下载 修改上述代码,移除 HttpURLConnection 的强制转换: 利用方式 : 使用file协议读取任意文件,例如: 0x04 实际案例 CVE-2019-9827 参考链接: CVE详情 技术分析 0x05 防御措施 输入验证 : 对用户输入的URL进行严格校验 使用白名单机制限制允许的协议和域名 网络层防护 : 禁止访问内网IP段 限制请求的目标端口 代码层防护 : 避免直接使用用户输入构造URL 使用安全的网络请求库 环境加固 : 配置Java安全策略 限制应用程序的网络访问权限 0x06 总结 SSRF漏洞在Java应用中危害严重,特别是能够访问内网资源的应用。审计时应重点关注: 直接使用用户输入构造URL的地方 网络请求是否有限制和过滤 是否使用了不安全的协议(如file) 是否有对内网地址的访问控制 通过本教程的学习,您应该掌握了Java中SSRF漏洞的基本原理、利用方式和防御措施,能够在代码审计中识别此类漏洞。