当前位置: 首页 > news >正文

【Java代码审计 | 第十一篇】SSRF漏洞成因及防范

未经许可,不得转载。

文章目录

    • SSRF
    • 漏洞成因
    • Java中发送HTTP请求的函数
      • 1、HttpURLConnection
      • 2、HttpClient(Java 11+)
      • 3、第三方库
        • Request库漏洞示例
        • OkHttpClient漏洞示例
        • HttpClients漏洞示例
    • 漏洞代码示例
    • 防范
    • 标准代码

在这里插入图片描述

SSRF

SSRF(Server-Side Request Forgery,服务器端请求伪造) 是一种安全漏洞,攻击者可以利用该漏洞诱使服务器向内部或外部的任意系统发起请求。通过SSRF,攻击者可以绕过防火墙或访问限制,访问内部资源,甚至攻击内网中的其他服务。

常见的攻击场景包括:
1、访问内网中的敏感数据。
2、扫描内网端口和服务。
3、利用服务器作为跳板攻击其他系统。
4、访问云服务元数据(如AWS的元数据服务)。

漏洞成因

SSRF漏洞通常是由于应用程序在处理用户输入的URL时,未对其进行严格的验证和过滤,导致攻击者可以构造恶意URL,使服务器发起非预期的请求。

Java中发送HTTP请求的函数

在Java中,发送HTTP请求的常见方式有以下几种。

1、HttpURLConnection

这是Java标准库中的类,用于发送HTTP请求,示例代码如下:

import java.net.HttpURLConnection;  // 导入HttpURLConnection类
import java.net.URL;  // 导入URL类
import java.io.BufferedReader;  // 导入BufferedReader类
import java.io.InputStreamReader;  // 导入InputStreamReader类public class HttpExample {public static void main(String[] args) {try {// 创建URL对象并指定要访问的地址URL url = new URL("https://example.com");// 打开与目标URL的连接HttpURLConnection conn = (HttpURLConnection) url.openConnection();// 设置请求方法为GETconn.setRequestMethod("GET");// 创建BufferedReader读取响应内容BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));String inputLine;StringBuilder content = new StringBuilder();// 逐行读取响应并拼接while ((inputLine = in.readLine()) != null) {content.append(inputLine);}// 关闭输入流in.close();// 断开连接conn.disconnect();// 打印网页内容System.out.println(content.toString());} catch (Exception e) {e.printStackTrace();  // 捕获异常并打印错误信息}}
}

2、HttpClient(Java 11+)

Java 11引入的新的HTTP客户端API,功能更强大。

3、第三方库

如Apache HttpClient、OkHttp等。

Request库漏洞示例
String url = request.getParameter("url"); // 从用户输入中获取URL
return Request.Get(url).execute().returnContent().toString(); // 直接使用用户输入的URL发起请求

代码直接从用户输入中获取URL,未进行任何验证或过滤。

OkHttpClient漏洞示例
String url = request.getParameter("url"); // 从用户输入中获取URL
OkHttpClient client = new OkHttpClient();
com.squareup.okhttp.Request ok_http = new com.squareup.okhttp.Request.Builder().url(url).build();
client.newCall(ok_http).execute();  // 使用用户输入的URL发起请求

代码直接使用用户输入的URL构造请求,未对URL进行合法性检查。

HttpClients漏洞示例
String url = request.getParameter("url"); // 从用户输入中获取URL
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = client.execute(httpGet); // 使用用户输入的URL发起请求

代码未对用户输入的URL进行任何验证或限制,直接用于发起HTTP请求。

漏洞代码示例

import java.net.HttpURLConnection;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import javax.servlet.http.HttpServletRequest;public class SSRFExample {public static void main(String[] args) {HttpServletRequest request = getRequest();// 获取请求中的 URL 参数String userInput = request.getParameter("url");if (userInput == null || userInput.isEmpty()) {System.out.println("Please provide a URL as a parameter.");return;}try {// 创建URL对象URL url = new URL(userInput);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET"); //GET方法请求// 读取响应内容BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));String inputLine;StringBuilder content = new StringBuilder();while ((inputLine = in.readLine()) != null) {content.append(inputLine);}in.close();conn.disconnect();// 打印响应内容System.out.println(content.toString());} catch (Exception e) {e.printStackTrace();  // 捕获异常并打印错误信息}}
}

在这个示例中,用户输入的URL直接用于发起HTTP请求,如果攻击者输入一个指向内网服务的URL(如http://169.254.169.254/latest/meta-data/),服务器会访问到敏感的内部资源并返回给客户端。

防范

1、严格验证用户输入的 URL,确保其符合预期格式和范围。

2、合理处理 302 跳转,对跳转地址进行校验,而非直接禁止。

3、限制协议类型,仅允许 http/https,禁止跨协议访问。

4、采用白名单机制,仅允许访问特定域名或 IP 地址:

  • 准确识别内网 IP,并正确解析 Host 头信息。
  • 禁止访问内网 IP 地址及私有 IP 段(如 127.0.0.1、192.168.x.x、10.x.x.x 等)。
  • 拒绝访问敏感 URL(如云服务元数据地址)。

5、配置 Web 端口白名单,防止端口扫描(可能对业务有一定限制)。

标准代码

private static final int CONNECT_TIMEOUT = 5000; // 连接超时时间(毫秒)public static boolean checkSsrf(String url) {HttpURLConnection connection;String finalUrl = url;try {do {// 仅允许 http/https 协议,防止跨协议攻击if (!Pattern.matches("^https?://.+$", finalUrl)) {return false;}// 判断是否为内网 IP,避免 SSRF 访问内部服务if (isInnerIp(finalUrl)) {return false;}// 发起 HTTP 请求,不跟随跳转connection = (HttpURLConnection) new URL(finalUrl).openConnection();connection.setInstanceFollowRedirects(false); // 禁止自动跳转connection.setUseCaches(false); // 禁用缓存,确保每次请求都重新解析 DNSconnection.setConnectTimeout(CONNECT_TIMEOUT); // 设置超时时间,防止长时间阻塞connection.connect(); // 触发 DNS 解析,尝试建立连接int statusCode = connection.getResponseCode();// 检查 3xx 状态码(重定向),但排除 304(缓存)和 306(保留未使用)if (statusCode >= 300 && statusCode <= 307 && statusCode != 304 && statusCode != 306) {String redirectedUrl = connection.getHeaderField("Location");if (redirectedUrl == null) {break; // 若无重定向地址,则终止检查}finalUrl = redirectedUrl; // 继续检查跳转后的 URL} else {break; // 结束循环,URL 无需进一步检查}} while (connection.getResponseCode() != HttpURLConnection.HTTP_OK); // 仅当返回 200 时才终止检查connection.disconnect();} catch (Exception e) {return true; // 捕获异常,返回 true(默认安全策略)}return true;
}private static boolean isInnerIp(String url) throws URISyntaxException, UnknownHostException {URI uri = new URI(url);String host = uri.getHost(); // 提取 Host 部分// 解析 Host 对应的 IP 地址,并标准化为 IPv4 格式InetAddress inetAddress = InetAddress.getByName(host);String ip = inetAddress.getHostAddress();// 定义内网 IP 段(私有地址范围)String[] privateSubnets = {"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "127.0.0.0/8"};for (String subnet : privateSubnets) {SubnetUtils subnetUtils = new SubnetUtils(subnet); // 使用 commons-net 进行子网匹配if (subnetUtils.getInfo().isInRange(ip)) {return true; // IP 属于内网地址范围,返回 true}}return false;
}

说明:
1、return false → 发现安全问题时(如协议不合法、检测到内网 IP),返回 false,表示 URL 不安全。
2、return true → 没有发现明确安全问题,返回 true,允许执行。

相关文章:

【Java代码审计 | 第十一篇】SSRF漏洞成因及防范

未经许可&#xff0c;不得转载。 文章目录 SSRF漏洞成因Java中发送HTTP请求的函数1、HttpURLConnection2、HttpClient&#xff08;Java 11&#xff09;3、第三方库Request库漏洞示例OkHttpClient漏洞示例HttpClients漏洞示例 漏洞代码示例防范标准代码 SSRF SSRF&#xff08;S…...

RabbitMQ高级特性--消息确认机制

目录 一、消息确认 1.消息确认机制 2.手动确认方法 二、代码示例 1. AcknowledgeMode.NONE 1.1 配置文件 1.2 生产者 1.3 消费者 1.4 运行程序 2.AcknowledgeMode.AUTO 3.AcknowledgeMode.MANUAL 一、消息确认 1.消息确认机制 生产者发送消息之后&#xff0c;到达消…...

C++复试笔记(一)

Setw 是C中用于设置输出字段宽度的函数。当使用 setw(3) 时&#xff0c;它会设置紧接着的输出字段的最小宽度为3个字符。如果字段内容长度小于3&#xff0c;则会在左侧填充空格以达到指定宽度&#xff1b;如果内容长度大于或等于3&#xff0c;则全部内容将被输出&#xff0c;…...

K8s 1.27.1 实战系列(四)验证集群及应用部署测试

一、验证集群可用性 1、检查节点 kubectl get nodes ------------------------------------------------------ NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane 3h48m v1.27.1 k8s-node1 Ready <none> …...

基于Spring Boot的健美操评分管理系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

H5页面在移动端自动横屏

首先需要再head标签添加这样一段代码 <meta name="viewport" content="width=device-width,height=device-width,initial-scale=1.0,user-scalable=no">因为需求是为了满足WEB端和手机端都可以查看整体效果 但由于UI没有设计移动端的样式 所以我想说…...

【从0到1搞懂大模型】神经网络的实现:数据策略、模型调优与评估体系(3)

一、数据集的划分 &#xff08;1&#xff09;按一定比例划分为训练集和测试集 我们通常取8-2、7-3、6-4、5-5比例切分&#xff0c;直接将数据随机划分为训练集和测试集&#xff0c;然后使用训练集来生成模型&#xff0c;再用测试集来测试模型的正确率和误差&#xff0c;以验证…...

从0到1入门RabbitMQ

一、同步调用 优势&#xff1a;时效性强&#xff0c;等待到结果后才返回 缺点&#xff1a; 拓展性差性能下降级联失败问题 二、异步调用 优势&#xff1a; 耦合度低&#xff0c;拓展性强异步调用&#xff0c;无需等待&#xff0c;性能好故障隔离&#xff0c;下游服务故障不影响…...

MySQL数据库复杂的增删改查操作

在前面的文章中&#xff0c;我们主要学习了数据库的基础知识以及基本的增删改查的操作。接下去将以一个比较实际的公司数据库为例子&#xff0c;进行讲解一些较为复杂且现时需求的例子。 基础知识&#xff1a; 一文清晰梳理Mysql 数据库基础知识_字段变动如何梳理清楚-CSDN博…...

点云软件VeloView开发环境搭建与编译

官方编译说明 LidarView / LidarView-Superbuild GitLab 我的编译过程&#xff1a; 安装vs2019&#xff0c;windows sdk&#xff0c;qt5.14.2&#xff08;没安装到5.15.7&#xff09;&#xff0c;git&#xff0c;cmake3.31&#xff0c;python3.7.9&#xff0c;ninja下载放到…...

本地YARN集群部署

请先完成HDFS的前置部署&#xff0c;部署方式可查看:本地部署HDFS集群https://blog.csdn.net/m0_73641796/article/details/145998092?spm1001.2014.3001.5502 部署说明 组件配置文件启动进程备注Hadoop HDFS需修改 需启动: NameNode作为主节点 DataNode作为从节点 Secondary…...

STM32常见外设的驱动示例和代码解析

以下是针对STM32常见外设的驱动示例和代码解析,基于HAL库实现,适用于大多数STM32系列(如F1/F4/H7等),可根据具体型号调整引脚和时钟配置。 1. GPIO驱动 应用场景:控制LED、按键检测、继电器开关等。 示例代码: // 初始化LED(推挽输出) void LED_Init(void) {GPIO_In…...

使用数据库和缓存的时候,是如何解决数据不一致的问题的?

1.缓存更新策略 1.1. 缓存旁路模式&#xff08;Cache Aside&#xff09; 在应用里负责管理缓存&#xff0c;读取时先查缓存&#xff0c;如果命中了则返回缓存&#xff0c;如果未命中就查询数据库&#xff0c;然后返回缓存&#xff0c;返回缓存的同时把数据给写入缓存中。更新…...

VS Code C++ 开发环境配置

VS Code 是当前非常流行的开发工具. 本文讲述如何配置 VS Code 作为 C开发环境. 本文将按照如下步骤来介绍如何配置 VS Code 作为 C开发环境. 安装编译器安装插件配置工作区 第一个步骤的具体操作会因为系统不同或者方案不同而有不同的选择. 环境要求 首先需要立即 VS Code…...

使用OpenCV和MediaPipe库——实现人体姿态检测

目录 准备工作如何在Windows系统中安装OpenCV和MediaPipe库&#xff1f; 安装Python 安装OpenCV 安装MediaPipe 验证安装 代码逻辑 整体代码 效果展示 准备工作如何在Windows系统中安装OpenCV和MediaPipe库&#xff1f; 安装Python 可以通过命令行运行python --versio…...

JWT的学习

1、HTTP无状态及解决方案 HTTP一种是无状态的协议&#xff0c;每次请求都是一次独立的请求&#xff0c;一次交互之后就是陌生人。 以CSDN为例&#xff0c;先登录一次&#xff0c;然后浏览器退出&#xff0c;这个时候在进入CSDN&#xff0c;按理说服务器是不知道你已经登陆了&…...

elasticsearch是哪家的

Elasticsearch&#xff1a;数据搜索与分析的领航者 在当今这个信息爆炸的时代&#xff0c;快速且准确地处理海量数据成为了众多企业和组织追求的目标。而Elasticsearch正是在这个背景下脱颖而出的一款强大的开源搜索引擎。它是由位于美国加利福尼亚州的Elastic公司所开发和维护…...

《A++ 敏捷开发》- 18 软件需求

需求并不是关于需求 (Requirements are not really about requirements) 大家去公共图书馆寄存物品&#xff0c;以前都是扫二维码开箱&#xff0c;有些图书馆升级了使用指纹识别。 “是否新方法比以前好&#xff1f;”我问年轻的开发人员。 “当然用指纹识别好。新技术&#x…...

计算机网络:计算机网络的组成和功能

计算机网络的组成&#xff1a; 计算机网络的工作方式&#xff1a; 计算机网络的逻辑功能; 总结&#xff1a; 计算机网络的功能&#xff1a; 1.数据通信 2.资源共享 3.分布式处理:计算机网络的分布式处理是指将计算任务分散到网络中的多个节点&#xff08;计算机或设备&…...

Upload-Labs-Linux 1-20

前端校验绕过&#xff1a;pass 01 两种思路&#xff1a;1.通过抓包&#xff0c;修改后缀 2.前端禁用js绕过前端后缀检验 首先写一个木马&#xff0c;改为图片格式GIF89a<?php eval($_POST[cmd])?>抓包之后改为PHP格式&#xff1a; 使用蚁剑连接木马&#xff0c;第一次尝…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中&#xff0c;明确沟通敏捷转型目的尤为关键&#xff0c;团队成员只有清晰理解转型背后的原因和利益&#xff0c;才能降低对变化的…...

6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙

Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...

CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx

“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网&#xff08;IIoT&#xff09;场景中&#xff0c;结合 DDS&#xff08;Data Distribution Service&#xff09; 和 Rx&#xff08;Reactive Extensions&#xff09; 技术&#xff0c;实现 …...