Java代码审计之SSRF
字数 1249 2025-08-12 11:33:52
Java代码审计之SSRF漏洞详解
1. SSRF漏洞概述
SSRF(Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者构造请求,由服务端发起请求的安全漏洞。SSRF攻击的目标通常是从外网无法访问的内部系统。
关键特征:
- 由服务端发起请求
- 能够访问与服务器相连的内部系统
- 常出现在从其他服务器获取数据的功能中
2. SSRF漏洞原理
SSRF形成的主要原因:
- 服务端提供了从其他服务器应用获取数据的功能
- 没有对目标地址做充分的过滤与限制
- 常见场景:获取网页文本内容、加载图片、下载文件等
本质:利用存在缺陷的web应用作为代理攻击远程和本地的服务器
3. Java中常见的网络请求协议
Java网络请求支持多种协议,包括:
file:///- 本地文件系统ftp://- FTP协议http://- HTTP协议https://- HTTPS协议jar://- JAR文件mailto://- 邮件协议netdoc://- 网络文档
4. SSRF漏洞实例分析
4.1 URLConnection漏洞示例
漏洞代码:
@GetMapping("/urlConnection/vuln")
public String URLConnectionVuln(String url) {
return HttpUtils.URLConnection(url);
}
// HttpUtils.URLConnection方法
public static String URLConnection(String url) {
try {
URL u = new URL(url);
URLConnection urlConnection = u.openConnection();
BufferedReader in = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream()));
String inputLine;
StringBuilder html = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
html.append(inputLine);
}
in.close();
return html.toString();
} catch (Exception e) {
logger.error(e.getMessage());
return e.getMessage();
}
}
攻击方式:
http://localhost:8080/ssrf/urlConnection/vuln?url=file:///c:/windows/win.ini
漏洞点分析:
- 直接使用用户提供的URL构造URL对象
- 调用
openConnection()方法发起请求 - 无任何协议限制或过滤
- 可以读取本地文件(
file:///协议)或访问内部网络资源
4.2 openStream漏洞示例
漏洞代码:
URL u = new URL(url);
inputStream = u.openStream();
攻击方式:
http://localhost:8080/ssrf/openStream?url=file:///c:/windows/win.ini
漏洞点分析:
openStream()方法内部调用了openConnection().getInputStream()- 同样会根据传入的协议进行处理
- 可以用于探测内网或文件下载
5. SSRF防御方案
5.1 基础防御方案
协议白名单:
public static boolean isHttp(String url) {
return url.startsWith("http://") || url.startsWith("https://");
}
@GetMapping("/urlConnection/sec")
public String URLConnectionSec(String url) {
// 拒绝非http/https协议
if (!SecurityUtil.isHttp(url)) {
return "[-] SSRF check failed";
}
// ...
}
局限性:
- 仅限制协议不足以防止对内网的探测
- 攻击者仍可能使用
http://127.0.0.1或http://内网IP进行攻击
5.2 高级防御方案
Hook机制:
@GetMapping("/urlConnection/sec")
public String URLConnectionSec(String url) {
// 拒绝非http/https协议
if (!SecurityUtil.isHttp(url)) {
return "[-] SSRF check failed";
}
try {
SecurityUtil.startSSRFHook(); // 开启SSRF Hook
return HttpUtils.URLConnection(url);
} catch (SSRFException | IOException e) {
return e.getMessage();
} finally {
SecurityUtil.stopSSRFHook(); // 关闭SSRF Hook
}
}
Hook机制优势:
- 可以监控和限制网络请求行为
- 防止对内网资源的访问
- 提供更细粒度的控制
6. 完整防御建议
- 协议限制:只允许http/https协议
- 域名/IP白名单:限制可访问的域名或IP范围
- 禁用重定向:防止通过重定向访问内部资源
- URL解析:严格解析URL,防止使用特殊字符绕过
- 请求内容检查:检查返回内容是否符合预期
- 网络层限制:服务器网络配置限制对内部系统的访问
- 认证机制:对内部服务启用认证
7. 关键Java API风险点
需要特别注意的Java API:
URL.openConnection()URL.openStream()HttpClient.execute()HttpURLConnection.connect()Request.Get/Post.execute()
这些API都可能成为SSRF漏洞的入口点,使用时必须进行严格的输入验证和过滤。