java之SSRF代码审计

1、SSRF漏洞审计点

服务端请求伪造(Server-Side Request Forge)简称 SSRF,它是由攻击者构造的 payload传给服务端,服务端对传回的 payload 未作处理直接执行后造成的漏洞,一般用于在内网探测或攻击内网服务。

利用: 扫描内网 、 向内部任意主机的任意端口发送精心构造的攻击载荷请求 、 攻击内网的 Web 应用 、 读取文件 、 拒绝服务攻击

Java网络请求支持的协议很多,包括:http,https,file,ftp,mailto,jar, netdoc。 Java 支持

的协议可以在rt. sun.net.www.protocol 包下看到 (jdk1.7)

Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。 gopher协议支持发出GET、POST请求:可以先截获get请求包和post请求包,在构成符 合gopher协议的请求。 在高版本的 JDK7 里,虽然sun.net.www.protocol 中还有 gopher 包,但是实际也已 经不能使用,会抛java.net.MalformedURLException: unknown protocol: gopher 的 异常,所以只能在JDK7以下才能使用。

jdk1.8 可以看到gopher 在 JDK8 中已经被移除。

Java中的SSRF相对于在PHP中来说,协议支持少一些,而且部分协议是受限的比如 gopher协议,所以总体上来说Java的SSRF危害肯没PHP中那么大。

容易出现漏洞的地方 :

基本上都是发起url请求的地方:

  1. 分享:通过URL地址分享网页内容

  2. 转码服务

  3. 在线翻译

  4. 图片加载与下载:通过URL地址加载或下载图片

  5. 图片、文章收藏功能

  6. 未公开的API实现以及其他调用URL的功能

  7. 从URL关键字中寻找:share、wap、url、link、src、source、target、u、3g、 display、sourceURI、imageURL、domain

  8. 云服务器商。(各种网站数据库操作)

常用函数 url关键词: share、wap、url、link、src、source、target、u、display、sourceURI、imageURL、domain...

代码审计时需要关注的发起HTTP请求的类及函数,部分如下:

HttpURLConnection.getInputStream
URLConnection.getInputStream
Request.Get.execute
Request.Post.execute
URL.openStream
ImageIO.read
OkHttpClient.newCall.execute
HttpClients.execute
HttpClient.execute
BasicHttpEntityEnclosingRequest()
DefaultBHttpClientConnection()
BasicHttpRequest()

1.1 URLConnection.getInputStream

URLConnection 是一个抽象类,表示指向 URL 指定的资源链接,其本身依赖于 Socket 类实现网络连接。 支持的协议有:file ftp mailto http https jar netdoc gopher

依据url读取文件内容:

例如:

/**
 * 通过URLConnectionU读取本地文件内容到程序中
 */
public class Demo01 {
    public static void main(String[] args) throws IOException {
        String url = "file:///1.txt";
       //构造一个 URL 对象
        URL u = new URL(url);
       //调用 URL.openConnection() 方法来获取一个 URLConnection 实例
        URLConnection urlConnection = u.openConnection();
        //调用 getInputStream() 拿到请求的响应流,此时已经建立连接。
        BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //发起请求
        String inputLine;
        StringBuffer html = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            html.append(inputLine);
        }
        System.out.println("html:" + html.toString());
        in.close();
    }
}
​

URLStreamHandler 是一个抽象类,每个协议都有继承它的子类 —— Handler。 Handler 定义了该如何去打开一个连接,即 openConnection() 。 如果直接传入一个 URL 字符串,会在构造对象时,根据 protocol 自动创建对应 的 Handler 对象

在调用 URL.openConnection() 获取 URLConnection 实例的时候,真实的网络连接实 际上并没有建立,只有在调用 URLConnection.connect() 方法后才会建立连接。

控制台输入文件内容:

例如:

/**
 *
 * 通过URLConnection以http协议请求网络资源
 */
public class Demo02 {
    public static void main(String[] args) throws IOException {
        String htmlContent;
//        String url = "http://www.baidu.com";
        String url = "https://www.baidu.com";
        //String url = "file:///etc/passwd";
        URL u = new URL(url);
        URLConnection urlConnection = u.openConnection();//打开一个URL连接,建立连接
        BufferedReader base = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
        StringBuffer html = new StringBuffer();
        while ((htmlContent = base.readLine()) != null) {
            System.out.println(htmlContent);
​
            html.append(htmlContent); //htmlContent添加到html里面
​
        }
        base.close();
//        System.out.println("探测:"+url);
        System.out.println("----------Response------------");
​
    }
}
​

文件读取:

http://127.0.0.1:8080/ssrf/urlConnection/vuln?url=file:///1.txt


文件下載:

SSRF 中的文件下载和文件读取不同点在于响应头

response.setHeader("content-disposition", "attachment;fileName=" + filename);

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition

例如:

RequestMapping(value = "/urlConnection/download", method = {RequestMethod.POST,
RequestMethod.GET})
public void downloadServlet(HttpServletRequest request, HttpServletRespons
e response) throws ServletException, IOException {
String filename = "1.txt";
String url = request.getParameter("url");
response.setHeader("content-disposition", "attachment;fileName=" + filename);
int len;
OutputStream outputStream = response.getOutputStream();
URL file = new URL(url);
byte[] bytes = new byte[1024];
InputStream inputStream = file.openStream();
while ((len = inputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, len);
}
}
/**
* Download the url file.
* http://localhost:8080/ssrf/openStream?url=file:///etc/passwd
* <p>
* new URL(String url).openConnection()
* new URL(String url).openStream()
* new URL(String url).getContent()
*/
@GetMapping("/openStream")
public void openStream(@RequestParam String url, HttpServletResponse response)
throws IOException {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
String downLoadImgFileName = WebUtils.getNameWithoutExtension(url) + "." +
WebUtils.getFileExtension(url);
// download
response.setHeader("content-disposition", "attachment;fileName=" +
downLoadImgFileName);
​
URL u = new URL(url);
int length;
byte[] bytes = new byte[1024];
inputStream = u.openStream(); // send request
outputStream = response.getOutputStream();
while ((length = inputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, length);
}
​
} catch (Exception e) {
logger.error(e.toString());
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
}
​
http://127.0.0.1:8080/ssrf/openStream?url=file:///1.txt

1.2 HttpURLConnection.getInputStream

HttpURLConnection 是 URLConnection 的子类, 用来实现基于 HTTP URL 的请求、响应功能,每个 HttpURLConnection 实例都可用于生成单个网络请求,支持GET、POST、PUT、DELETE等方式。

例如:

/**
 *
 * 通过HttpURLConnection以http协议请求网络资源
 */
public class Demo03 {
    public static void main(String[] args) throws IOException {
        String htmlContent;
//        String url = "http://www.baidu.com";
        String url = "https://www.baidu.com";
        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();
        System.out.println("探测:"+url);
        System.out.println("----------Response------------");
        System.out.println(html);
    }
}

HttpURLConnection 不支持file协议, 例如:file协议读取文件 file:///etc/passwd ,

FileURLConnection类型不能转换为 HttpURLConnection类型

1.3 Request.Get/Post.execute

Request类对HttpClient进行了封装。类似Python的requests库。 例如:

Request.Get(url).execute().returnContent().toString();

添加依赖:

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.13</version>
</dependency>

访问百度 :

/**
 *
 * 通过 Request.Get/Post.execute请求网络资源
 */
public class Demo04 {
    public static void main(String[] args) throws IOException {
//        String html = Request.Get("http://www.baidu.com").execute().returnContent().toString();
        String html = Request.Get("https://www.baidu.com/").execute().returnContent().toString();
        System.out.println(html);
    }
}

1.4 URL.openStream

String url = request.getParameter("url");
URL u = new URL(url);
InputStream inputStream = u.openStream();

例如:

/**
 * URL.openStream
 */
public class Demo05 {
    public static void main(String[] args) throws IOException {
        String htmlContent;
//        String url = "http://www.baidu.com";
                String url = "https://www.baidu.com";
​
// String url = "file:///etc/passwd";
        URL u = new URL(url);
        System.out.println("探测:"+url);
        System.out.println("----------Response------------");
        BufferedReader base = new BufferedReader(new InputStreamReader(u.openStream(), "UTF-8")); //获取url中的资源
        StringBuffer html = new StringBuffer();
        while ((htmlContent = base.readLine()) != null) {
            html.append(htmlContent); //htmlContent添加到html里面
        }
        System.out.println(html);
​
    }
}
​

1.5 HttpClients.execute

String url = request.getParameter("url");
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = client.execute(httpGet); //发起请求

例如:

/**
 * HttpGet
 */
public class Demo06 {
    public static void main(String[] args) throws IOException {
        String htmlContent;
//        String url = "http://www.baidu.com";
        String url = "https://www.baidu.com";
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        System.out.println("探测:"+url);
        System.out.println("----------Response------------");
        HttpResponse httpResponse = client.execute(httpGet); //发起请求
        BufferedReader base = new BufferedReader(new InputStreamReader(
                httpResponse.getEntity().getContent()));
        StringBuffer html = new StringBuffer();
        while ((htmlContent = base.readLine()) != null) {
            html.append(htmlContent); //htmlContent添加到html里面
        }
        System.out.println(html);
​
​
    }
}
​

1.6 ImageIO.read

javax.imageio.ImageIO 类是JDK自带的类,使用read() 方法来加载图片。 它可以传入一个 URL 对象,且没有协议限制。

String url = request.getParameter("url");
URL u = new URL(url);
BufferedImage img = ImageIO.read(u);

例如:

    @GetMapping("/ImageIO/vul")
    public void ImageIO(@RequestParam String url, HttpServletResponse response) {
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            URL u = new URL(url);
            InputStream istream = u.openStream();
            ImageInputStream stream = ImageIO.createImageInputStream(istream); //获取文件流
            BufferedImage bi = ImageIO.read(stream); //BufferedImage作为供给的
            ImageIO.write(bi, "png", os);
            InputStream input = new ByteArrayInputStream(os.toByteArray());
            int len;
            byte[] bytes = new byte[1024];
            while ((len = input.read(bytes)) > 0) {
                outputStream.write(bytes, 0, len);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
案例:
默认密码:admin/admin123

1.7 HttpUtils.URLConnection(url)

用到了 URLConnection.getInputStream:

2 SSRF漏洞修复方案

1 /**
2 * check SSRF (判断逻辑为判断URL的IP是否是内网IP)
3 * 如果是内网IP,返回false,表示checkSSRF不通过。否则返回true。即合法返回true
4 * URL只支持HTTP协议
5 * 设置了访问超时时间为3s
6 */
7 public static Boolean checkSSRF(String url) {
8 HttpURLConnection connection;
9 String finalUrl = url;
10 try {
11 do {
12 // 判断当前请求的URL是否是内网ip
13 Boolean bRet = isInnerIpFromUrl(finalUrl);
14 if (bRet) {
15 return false;
16 }
17 connection = (HttpURLConnection) new URL(finalUrl).openConnection();
18 connection.setInstanceFollowRedirects(false);
19 connection.setUseCaches(false); // 设置为false,手动处理跳转,可以拿到每个
跳转的URL
20 connection.setConnectTimeout(3*1000); // 设置连接超时时间为3s
21 connection.setRequestMethod("GET");
22 connection.connect(); // send dns request
23 int responseCode = connection.getResponseCode(); // 发起网络请求
24 if (responseCode >= 300 && responseCode <=307 && responseCode!= 304 &&
responseCode != 306) {
25 String redirectedUrl = connection.getHeaderField("Location");
26 if (null == redirectedUrl)
27 break;
28 finalUrl = redirectedUrl;
29 System.out.println("redirected url: " + finalUrl);
30 }else
31 break;
32 } while (connection.getResponseCode() != HttpURLConnection.HTTP_OK);
33 connection.disconnect();
34 } catch (Exception e) {
35 return true;
36 }
37 return true;
38 }

2. 1、白名单校验url及ip

/**
2 * 判断一个URL的IP是否是内网IP
3 * 如果是内网IP,返回true
4 * 非内网IP,返回false
5 */
public static boolean isInnerIpFromUrl(String url) throws Exception {
String domain = getUrlDomain(url);
if (domain.equals("")) {
return true; // 异常URL当成内网IP等非法URL处理
}
​
ip = DomainToIP(domain);
if(ip.equals("")){
return true; // 如果域名转换为IP异常,则认为是非法URL
 }
return isInnerIp(ip);
}
/**
*
* 内网IP:
* 10.0.0.1 - 10.255.255.254 (10.0.0.0/8)
* 192.168.0.1 - 192.168.255.254 (192.168.0.0/16)
* 127.0.0.1 - 127.255.255.254 (127.0.0.0/8)
 * 172.16.0.1 - 172.31.255.254 (172.16.0.0/12)
*/
public static boolean isInnerIp(String strIP) throws IOException {
try {
String[] ipArr = strIP.split("\\.");
if (ipArr.length != 4) {
return false;
}
​
int ip_split1 = Integer.parseInt(ipArr[1]);
​
return (ipArr[0].equals("10") || ipArr[0].equals("127") ||
(ipArr[0].equals("172") && ip_split1 >= 16 && ip_split1 <= 31) ||
(ipArr[0].equals("192") && ipArr[1].equals("168")));
} catch (Exception e) {
return false;
}
}

2.2、限制协议与端口

/**
* 从URL中获取域名
* 限制为http/https协议
*/
public static String getUrlDomain(String url) throws IOException{
try {
URL u = new URL(url);
if (!u.getProtocol().startsWith("http") && !u.getProtocol().start
sWith("https")) {
throw new IOException("Protocol error: " + u.getProtocol());
}
return u.getHost();
} catch (Exception e) {
return "";
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/738824.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

捕捉过往的时光,5个步骤,安卓手机找回删除的照片

手机不仅仅是一个通讯工具&#xff0c;更是一个记录生活点滴的神器。手机照相机的出现&#xff0c;让我们随时随地都能捕捉到美好的瞬间&#xff0c;留下珍贵的回忆。然而&#xff0c;随着时间的推移&#xff0c;我们可能会不小心删除了这些照片&#xff0c;或者因为各种原因导…

分布式锁实现方案-基于Redis实现的分布式锁

目录 一、基于Lua看门狗实现 1.1 缓存实体 1.2 延迟队列存储实体 1.3 分布式锁RedisDistributedLockWithDog 1.4 看门狗线程续期 1.5 测试类 1.6 测试结果 1.7 总结 二、RedLock分布式锁 2.1 Redlock分布式锁简介 2.2 RedLock测试例子 2.3 RedLock 加锁核心源码分析…

DVWA-CSRF-samesite分析

拿DVWA的CSRF为例子 接DVWA的分析&#xff0c;发现其实Impossible的PHPSESSID是设置的samesite1. 参数的意思参考Set-Cookie SameSite:控制 cookie 是否随跨站请求一起发送&#xff0c;这样可以在一定程度上防范跨站请求伪造攻击&#xff08;CSRF&#xff09;。 下面用DVWA CS…

springboot加载bean的方式

在SpringBoot的大环境下&#xff0c;基本上很少使用之前的xml配置Bean&#xff0c;主要是因为这种方式不好维护而且也不够方便。 springboto注入bean主要采用下图几种方式&#xff0c; 1、注解装配Bean 1、使用Component等派生注解 只要在类上加类上加 Component 注解即可,该…

[图解]企业应用架构模式2024新译本讲解17-活动记录1

1 00:00:01,070 --> 00:00:04,180 下一个我们要说的就是 2 00:00:04,190 --> 00:00:06,740 活动记录模式了 3 00:00:07,640 --> 00:00:11,210 同样是数据源架构模式 4 00:00:12,300 --> 00:00:18,480 里面的一个&#xff0c;活动记录 5 00:00:18,490 --> 00…

万界星空科技低代码云mes核心功能详解!建议收藏!

在当今数字化时代&#xff0c;制造企业面临着日益复杂的生产管理挑战。为了提高生产效率、降低成本、优化资源利用&#xff0c;许多企业开始转向云端制造执行系统&#xff08;MES&#xff09;。云MES系统作为数字化转型的关键组成部分&#xff0c;具有一系列核心功能和优势&…

Maven深度解析:Java项目构建

Maven是一个由Apache软件基金会维护的软件项目管理和理解工具&#xff0c;它主要服务于基于Java的软件项目。。 Maven深度解析&#xff1a;Java项目构建 引言 在Java开发领域&#xff0c;项目构建和管理是一个复杂而关键的任务。Maven作为这一领域的佼佼者&#xff0c;以其声…

MySQL的综合运用

MySQL版的葵花宝典&#xff0c;欲练此功&#xff0c;挥刀自。。。呃&#xff0c;&#xff0c;&#xff0c;说错了&#xff0c;是先创建两个表&#xff0c;分别是location表和store_info表 示例表为location表和store_info表&#xff0c;如下图所示&#xff1a; 操作一&#xf…

OpenAI Sora:我们来自混乱,我们也将回归混乱

最近&#xff0c;我开始深入了解并整理一些关于Sora这个人工智能模型的系列文章。我的目标是从两个角度深入探讨&#xff1a;一是Sora的技术细节&#xff0c;包括它的原理和功能&#xff1a;OpenAI Sora&#xff1a;距离黑客帝国仅一步之遥&#xff0c;二是Sora的应用前景&…

告别繁琐!一键互换新旧文件夹名,高效批量改名神器助您轻松管理文件库

在日常工作中&#xff0c;我们经常需要对文件夹进行命名和重命名操作。然而&#xff0c;当面对大量需要互换新旧名称的文件夹时&#xff0c;传统的手动操作不仅效率低下&#xff0c;还容易出错。为了解决这一难题&#xff0c;我们特别推出了一款高效、便捷的文件夹批量改名工具…

【GD32F303红枫派使用手册】第二十四节 DHT11温湿度传感器检测实验

24.1 实验内容 通过本实验主要学习以下内容&#xff1a; DHT11操作原理 单总线GPIO模拟操作原理 24.2 实验原理 HT11是一款已校准数字信号输出的温湿度一体化数字传感器。该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点信号&#xff0c;传输距离可达20米以…

nginx负载均衡案例,缓存知识----补充

负载均衡案例 ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near great all on wordpress.* to wp172.16.1.% indentified by 1 at line 1 MariaDB [(none)]>…

算法与数据结构面试宝典——回溯算法详解(C#,C++)

文章目录 1. 回溯算法的定义及应用场景2. 回溯算法的基本思想3. 递推关系式与回溯算法的建立4. 状态转移方法5. 边界条件与结束条件6. 算法的具体实现过程7. 回溯算法在C#&#xff0c;C中的实际应用案例C#示例C示例 8. 总结回溯算法的主要特点与应用价值 回溯算法是一种通过尝试…

算法常见手写代码

1.NMS def py_cpu_nms(dets, thresh):"""Pure Python NMS baseline."""#x1、y1、x2、y2、以及score赋值x1 dets[:, 0]y1 dets[:, 1]x2 dets[:, 2]y2 dets[:, 3]scores dets[:, 4]#每一个检测框的面积areas (x2 - x1 1) * (y2 - y1 1)#按…

C语言 while循环1

在C语言里有3种循环&#xff1a;while循环 do while 循环 for循环 while语句 //while语法结构 while&#xff08;表达式&#xff09;循环语句; 比如在屏幕上打印1-10 在while循环中 break用于永久的终止循环 在while循环中&#xff0c;continue的作用是跳过本次循环 …

【数据分析实战】—预测宠物收养状况数据分析

文章目录 数据集数据集描述特征用途注意 宠物收养预测环境准备探索数据帧数据预处理机器学习数据预处理&#xff1a;模型培训和评估&#xff1a;合奏学习&#xff1a; 添加底部名片获取数据集吧&#xff01; 数据集 数据集描述 宠物收养数据集提供了对各种因素的全面调查&…

安规管理:PLM安规管理、PLM安规管理新策略

安规管理&#xff1a;PLM安规管理、PLM安规管理新策略 随着科技的飞速发展&#xff0c;电子产品已经成为我们生活中不可或缺的一部分。然而&#xff0c;这些产品在给人们带来便利的同时&#xff0c;也可能带来触电、火灾、有害辐射等安全隐患。为了保护消费者的生命财产安全&am…

JavaWeb系列二十: jQuery的DOM操作 下

jQuery的DOM操作 CSS-DOM操作多选框案例页面加载完毕触发方法作业布置jQuery获取选中复选框的值jQuery控制checkbox被选中jQuery控制(全选/全不选/反选)jQuery动态添加删除用户 CSS-DOM操作 获取和设置元素的样式属性: css()获取和设置元素透明度: opacity属性获取和设置元素高…

Spring中事务的传播机制

一、前言 首先事务传播机制解决了什么问题 Spring 事务传播机制是包含多个事务的方法在相互调用时&#xff0c;事务是如何在这些方法间传播的。 事务的传播级别有 7 个&#xff0c;支持当前事务的&#xff1a;REQUIRED、SUPPORTS、MANDATORY&#xff1b; 不支持当前事务的&…