以小白视角进行JAVA代码审计——SSRF漏洞
字数 1269 2025-11-07 08:41:54

Java代码审计入门:SSRF漏洞详解与实战指南

一、SSRF漏洞基础概念

1.1 什么是SSRF漏洞

SSRF(Server-Side Request Forgery,服务端请求伪造)是一种Web安全漏洞,攻击者能够诱使服务器端应用程序向非预期目标发起请求。该漏洞的主要危害在于可以攻击从外网无法直接访问的内网系统。

1.2 SSRF漏洞的危害范围

  • 探测内网服务:通过响应差异判断服务存活状态
  • 端口扫描:识别内网开放端口
  • 文件读取:利用file协议读取本地文件
  • 协议利用:配合gopher协议攻击Redis等内网服务
  • 内网系统攻击:访问和攻击内部网络中的敏感系统

1.3 常见出现场景

  1. 社交分享功能(获取超链接标题)
  2. 网页转码服务(移动端适配)
  3. 在线翻译功能
  4. 图片加载/下载功能
  5. 内容采集功能
  6. 云服务存活检测
  7. 邮件系统接收处理
  8. 文件处理功能(FFmpeg、ImageMagick等)

二、Java网络请求支持的协议

Java原生支持以下协议:

  • http / https
  • file(文件读取)
  • ftp
  • mailto
  • jar
  • netdoc

三、SSRF漏洞代码实例分析

3.1 HttpClient方式漏洞示例

Maven依赖:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.12</version>
</dependency>

漏洞代码:

@RestController
@RequestMapping("/ssrfvul")
public class HttpClientController {
    
    @GetMapping("/httpclient/vul")
    public String HttpClientDemo(@RequestParam String url) throws IOException {
        StringBuilder result = new StringBuilder();
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url); // 直接使用用户输入
        HttpResponse httpResponse = client.execute(httpGet);
        // ... 处理响应
        return result.toString();
    }
}

攻击向量:

http://127.0.0.1:8088/ssrfvul/httpclient/vul?url=http://www.baidu.com
http://127.0.0.1:8088/ssrfvul/httpclient/vul?url=file:///c:/windows/win.ini

3.2 HttpURLConnection方式漏洞示例

漏洞代码:

@RestController
@RequestMapping("/ssrfvul")
public class UrlConnectionController {
    
    @GetMapping("/urlconnection/vul")
    public String UrlConnectionDemo(@RequestParam String url) throws IOException {
        StringBuilder result = new StringBuilder();
        URL url1 = new URL(url); // 直接使用用户输入
        URLConnection urlConn = url1.openConnection();
        urlConn.connect();
        // ... 处理响应
        return result.toString();
    }
}

四、实战漏洞案例分析

4.1 环境搭建与漏洞定位

  • 搭建目标系统环境(数据库+Maven配置)
  • 全局搜索关键函数:openConnection
  • 定位漏洞触发点:ueditorCatchImage方法

4.2 漏洞代码分析

protected void ueditorCatchImage(Site site, HttpServletRequest request,
                                 HttpServletResponse response) throws IOException {
    String[] source = request.getParameterValues("source[]"); // 用户可控输入
    for (int i = 0; i < source.length; i++) {
        String src = source[i];
        // 格式验证(仅检查扩展名,存在绕过可能)
        String extension = FilenameUtils.getExtension(src);
        if (!gu.isExtensionValid(extension, Uploader.IMAGE)) {
            continue;
        }
        // 设置不跟随重定向(但存在其他绕过方式)
        HttpURLConnection.setFollowRedirects(false);
        // 漏洞触发点
        HttpURLConnection conn = (HttpURLConnection) new URL(src).openConnection();
    }
}

4.3 漏洞利用方式

触发URL:

http://127.0.0.1:8080/cmscp/core/ueditor.do?action=catchimage&source[]=http://www.baidu.com/

内网探测:

  • 开放端口(3306):正常响应
  • 关闭端口(3307):异常响应(500错误)

五、高级利用技巧

5.1 Gopher协议利用

配合Redis进行RCE攻击:

curl -v 'http://target/xx.php?url=gopher://172.21.0.2:6379/_*1%250d%250a%248%250d%250aflushall%250d%250a...'

攻击流程:

  1. 通过SSRF访问内网Redis服务
  2. 发送特定格式的Redis命令
  3. 实现命令执行和权限获取

5.2 文件读取利用

  • 读取系统配置文件:file:///c:/windows/win.ini
  • 读取应用配置文件(如向日葵配置)
  • 结合信息泄露进一步渗透

六、SSRF漏洞修复方案

6.1 白名单域名校验(推荐)

public static boolean checkSSRFByWhitehosts(String url) {
    return SSRFChecker.checkURLFckSSRF(url);
}

public static boolean isHttp(String url) {
    return url.startsWith("http://") || url.startsWith("https://");
}

public static String gethost(String url) {
    try {
        URI uri = new URI(url);
        return uri.getHost().toLowerCase();
    } catch (URISyntaxException e) {
        return "";
    }
}

6.2 内网IP检测

public static boolean isIntranet(String url) {
    Pattern reg = Pattern.compile("^(127\\.0\\.0\\.1)|(localhost)|(10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})|(172\\.((1[6-9])|(2\\d)|(3[01]))\\.\\d{1,3}\\.\\d{1,3})|(192\\.168\\.\\d{1,3}\\.\\d{1,3})$");
    Matcher match = reg.matcher(url);
    return match.find();
}

6.3 完整安全校验方案

public static String checkURL(String url) {
    if (null == url) return null;
    
    ArrayList<String> safeDomains = WebConfig.getSafeDomains();
    ArrayList<String> blockDomains = WebConfig.getBlockDomains();
    
    try {
        String host = gethost(url);
        
        // 协议校验
        if (!isHttp(url)) return null;
        
        // 黑名单检测
        if (blockDomains.contains(host)) return null;
        for(String blockDomain: blockDomains) {
            if(host.endsWith("." + blockDomain)) return null;
        }
        
        // 白名单检测(支持多级域名)
        if (safeDomains.contains(host)) return url;
        for(String safedomain: safeDomains) {
            if(host.endsWith("." + safedomain)) return url;
        }
        return null;
    } catch (NullPointerException e) {
        return null;
    }
}

6.4 其他防护措施

  1. 禁用重定向
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setInstanceFollowRedirects(false);
  1. Socket Hook监控
// 开启监控
SecurityUtil.startSSRFHook();
// 业务逻辑
// 关闭监控
SecurityUtil.stopSSRFHook();
  1. 输入过滤
public static String replaceSpecialStr(String str) {
    StringBuilder sb = new StringBuilder();
    str = str.toLowerCase();
    for(int i = 0; i < str.length(); i++) {
        char ch = str.charAt(i);
        if ((ch >= 48 && ch <= 57) ||  // 数字
            (ch >= 97 && ch <= 122) || // 字母
            ch == '/' || ch == '.' || ch == '-') {
            sb.append(ch);
        }
    }
    return sb.toString();
}

七、代码审计要点总结

7.1 关键函数识别

  • URL.openConnection()
  • HttpClient.execute()
  • Request.Get().execute()
  • 其他HTTP客户端库的请求方法

7.2 参数追踪

  • 关注用户可控的URL参数
  • 检查参数是否经过严格校验
  • 验证重定向处理逻辑

7.3 测试验证

  • 尝试不同协议(http、file、gopher等)
  • 测试内网地址访问
  • 验证防护措施的有效性

通过以上详细的代码审计指南,安全人员可以系统性地识别、验证和修复Java应用中的SSRF漏洞,有效提升应用程序的安全性。

Java代码审计入门:SSRF漏洞详解与实战指南 一、SSRF漏洞基础概念 1.1 什么是SSRF漏洞 SSRF(Server-Side Request Forgery,服务端请求伪造)是一种Web安全漏洞,攻击者能够诱使服务器端应用程序向非预期目标发起请求。该漏洞的主要危害在于可以攻击从外网无法直接访问的内网系统。 1.2 SSRF漏洞的危害范围 探测内网服务 :通过响应差异判断服务存活状态 端口扫描 :识别内网开放端口 文件读取 :利用file协议读取本地文件 协议利用 :配合gopher协议攻击Redis等内网服务 内网系统攻击 :访问和攻击内部网络中的敏感系统 1.3 常见出现场景 社交分享功能(获取超链接标题) 网页转码服务(移动端适配) 在线翻译功能 图片加载/下载功能 内容采集功能 云服务存活检测 邮件系统接收处理 文件处理功能(FFmpeg、ImageMagick等) 二、Java网络请求支持的协议 Java原生支持以下协议: http / https file(文件读取) ftp mailto jar netdoc 三、SSRF漏洞代码实例分析 3.1 HttpClient方式漏洞示例 Maven依赖: 漏洞代码: 攻击向量: 3.2 HttpURLConnection方式漏洞示例 漏洞代码: 四、实战漏洞案例分析 4.1 环境搭建与漏洞定位 搭建目标系统环境(数据库+Maven配置) 全局搜索关键函数: openConnection 定位漏洞触发点: ueditorCatchImage 方法 4.2 漏洞代码分析 4.3 漏洞利用方式 触发URL: 内网探测: 开放端口(3306):正常响应 关闭端口(3307):异常响应(500错误) 五、高级利用技巧 5.1 Gopher协议利用 配合Redis进行RCE攻击: 攻击流程: 通过SSRF访问内网Redis服务 发送特定格式的Redis命令 实现命令执行和权限获取 5.2 文件读取利用 读取系统配置文件: file:///c:/windows/win.ini 读取应用配置文件(如向日葵配置) 结合信息泄露进一步渗透 六、SSRF漏洞修复方案 6.1 白名单域名校验(推荐) 6.2 内网IP检测 6.3 完整安全校验方案 6.4 其他防护措施 禁用重定向 : Socket Hook监控 : 输入过滤 : 七、代码审计要点总结 7.1 关键函数识别 URL.openConnection() HttpClient.execute() Request.Get().execute() 其他HTTP客户端库的请求方法 7.2 参数追踪 关注用户可控的URL参数 检查参数是否经过严格校验 验证重定向处理逻辑 7.3 测试验证 尝试不同协议(http、file、gopher等) 测试内网地址访问 验证防护措施的有效性 通过以上详细的代码审计指南,安全人员可以系统性地识别、验证和修复Java应用中的SSRF漏洞,有效提升应用程序的安全性。