Java 中支持的协议
Java网络请求支持的协议包括:http,https,file,ftp,mailto,jar,netdoc。
1、HttpClient
HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、昀新的、功能丰富的支持HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议昀新的版本和建议。
HttpClient 实现了 HTTP1.0 和 HTTP1.1。也实现了 HTTP 全部的方法,如: GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE 。
2、HttpAsyncClient
HttpAsyncClient 是一个异步的 HTTP 客户端开发包,基于 HttpCore NIO 和 HttpClient 组件。
HttpAsyncClient 的出现并不是为了替换 HttpClient,而是作为一个补充用于需要大量并发连接,对性能要求非常高的基于 HTTP 的原生数据通信,而且提供了事件驱动的 API。
3、java.net.URLConnection
java.net.URLConnection,是 Java 原生的 HTTP 请求方法。URLConnection 类包含了许多方法可以让你的 URL 在网络上通信。此类的实例既可用于读取URL所引用的资源,也可用于写入URL所引用资源。
4、java.net.HttpURLConnection
HttpURLConnection 继承自 URLConnection。可以向指定网站发起GET或POST请求。
5、java.net.URL
在 java.net 包中定义了 URL 类,该类用来处理有关 URL 的内容。通过使用 URL 对象的 openStream() 方法创建打开指定 URL 链接,以获取输入流资源内容。
6、java.net.Socket
java.net.Socket 是 Java 套接字编程使用的类。提供了两台计算机之间的通信机制。在Java代码审计中,我们可能会遇见使用Socket判断IP与端口连通性的代码。如果IP和端口接受外部输入,那么极有可能存在SSRF漏洞。
7、OkHttp
OKHttp 是一个网络请求框架,OKHttp会为每个客户端创建自己的连接池和线程池。重用连接和线程可以减少延迟并节省内存。OkHttp中请求方式分为同步请求( client.newCall(request).execute())和异步请求( client.newCall(request).enqueue() )两种
8、ImageIO
ImageIO 是Java读写图片操作的一个类。在代码审计中,如果目标使用了 ImageIO.read 读取图片,且读取的图片地址可控的话,可能会存在SSRF漏洞。
9、Hutool
Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅。
在Hutool中,也实现了HTTP客户端,Hutool-http针对JDK的HttpUrlConnection做一层封装,简化了HTTPS请求、文件上传、Cookie记忆等操作,使Http请求变得无比简单。
Hutool-http的核心集中在两个类:
- HttpRequest
- HttpResponse
10、 Jsoup
Jsoup 是基于 Java 的 HTML 解析器,可以从指定的 URL 中解析 HTML 内容
11、RestTemplate
RestTemplate 是从Spring3.0 开始支持的一个HTTP 请求工具,它提供了常见的REST请求方案的模版,例如GET 请求、POST 请求、PUT 请求等等。从名称上来看,是更针对RESTFUL风格API设计的。但通过他调用普通的HTTP接口也是可以的。
SSRF审计关键字:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| HttpRequest.get HttpRequest.post Jsoup.connect getForObject RestTemplate postForObject httpclient execute HttpClients.createDefault httpasyncclient HttpAsyncClients.createDefault java.net.URLConnection openConnection java.net.HttpURLConnection openStream openConnection Socket java.net.Socket okhttp OkHttpClient newCall ImageIO.read javax.imageio.ImageIO HttpRequest.get jsoup Jsoup.connect RestTemplate org.springframework.web.client.RestTemplate
|
防御:
重写底层代码(Socket connect)增加IP是否在内网的判断代码,如果是进行报错,可以有效防范
XXE代审
1.XML介绍
XML (Extensible Markup Language) 是一种可扩展的标记语言,用于标记电子文件中的各种元素。它是用来传输和存储数据的一种常用方式(html用来展示的),并且可以被很多不同的应用程序所使用。
XML 的基本概念是标记,它使用标签来描述文档中的元素。每个标签都有一个名称,并且可以包含属性和值。
XML 的一个主要优点是它允许不同的应用程序之间进行数据交换,因为它是一种通用的数据格式。它还可以用于存储数据,并且可以使用 XML 文档来描述数据的结构。
XML 在许多不同的领域都有广泛的应用,包括电子商务、计算机技术、生物学和其他领域。它是一种流行的数据格式,并且被广泛使用。
Java中的XXE支持 sun.net.www.protocol 里面的所有协议:http,https,file,ftp,mailto,jar,netdoc 。
通常可以使用以下协议来发起XXE攻击:
- file:允许通过文件系统访问本地文件。
- http:允许通过HTTP协议访问远程服务器上的文件。
- https:允许通过HTTPS协议访问远程服务器上的文件。
- ftp:允许通过FTP协议访问远程服务器上的文件。
1 2 3 4 5
| <?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY file SYSTEM "file:///etc/passwd"> ]> <root>&file;</root>
|
2、DTD
DTD(Document Type Definition)是文档类型定义的缩写。它是一种用来定义XML文档结构的文本文件,用于描述XML文档中元素的名称、属性和约束关系。DTD可以帮助浏览器或其他应用程序更好地解析和处理XML文档。
漏洞解析:
1、DOM 解析
DOM的全称是Document Object Model,也即文档对象模型。DOM 解析是将一个 XML 文档转换成一个 DOM 树,并将 DOM 树放在内存中。
使用大致步骤:
- 创建一个 DocumentBuilderFactory 对象
- 创建一个 DocumentBuilder 对象
- 通过 DocumentBuilder 的 parse() 方法加载 XML
- 遍历 name 和 value 节点
1 2 3
| DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance() DocumentBuilder db = dbf.newDocumentBuilder() Document document = db.parse(is)
|
2、SAX 解析
SAX 的全称是 Simple APIs for XML,也即 XML 简单应用程序接口。与 DOM 不同,SAX 提供的访问模式是一种顺序模式,这是一种快速读写 XML 数据的方式。
使用大致步骤:
- 获取 SAXParserFactory 的实例
- 获取 SAXParser 实例
- 创建一个 handler() 对象
- 通过 parser 的 parse() 方法来解析 XML
1 2 3 4 5 6 7
| 一. SAXParserHandler handler = new SAXParserHandler(); //解析xml parser.parse(new InputSource(new StringReader(body)), handler);
二. SAXReader reader = new SAXReader(); reader.read(new InputSource(new StringReader(body)));
|
3、JDOM 解析
JDOM 是一个开源项目,它基于树型结构,利用纯 JAVA 的技术对 XML 文档实现解析、生成、序列化以及多种操作。
使用大致步骤:
- 创建一个 SAXBuilder 的对象
- 通过 saxBuilder 的 build() 方法,将输入流加载到 saxBuilder 中
1 2 3 4 5 6
| JDOM 需要在 pom.xml 文件中引入该依赖 <dependency> <groupId>org.jdom</groupId> <artifactId>jdom</artifactId> <version>1.1.3</version> </dependency>
|
1 2
| SAXBuilder builder = new SAXBuilder(); builder.build(new InputSource(new StringReader(body)));
|
4、DOM4J 解析
Dom4j 是一个易用的、开源的库,用于XML,XPath 和 XSLT。它应用于Java平台,采用了Java集合框架并完全支持 DOM,SAX 和 JAXP。是 Jdom 的升级品
使用大致步骤:
- 创建 SAXReader 的对象 reader
- 通过 reader 对象的 read() 方法加载 xml 文件
1 2 3 4 5 6
| 依赖 <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6</version> </dependency>
|
1 2
| SAXReader reader = new SAXReader(); reader.read(new InputSource(new StringReader(body)));
|
5、Digester 解析
Digester 是 Apache 下一款开源项目。 目前最新版本为 Digester 3.x 。
Digester 是对 SAX 的包装,底层是采用的是 SAX 解析方式
使用大致步骤:
- 创建 Digester 对象
- 调用 Digester 对象的 parse() 解析 XML
1 2 3 4 5
| <dependency> <groupId>commons-digester</groupId> <artifactId>commons-digester</artifactId> <version>2.1</version> </dependency>
|
1 2
| Digester digester = new Digester(); digester.parse(new StringReader(body));
|
靶场复现:
xxedemo靶场:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package com.example.xxedemo;
import org.dom4j.io.SAXReader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.xml.sax.InputSource;
import javax.servlet.http.HttpServletRequest; import java.io.InputStream; import java.io.StringReader;
@RestController public class DOM4JTest {
@RequestMapping("/dom4jdemo/vul") public String dom4jDemo(HttpServletRequest request) { try { InputStream in = request.getInputStream(); String body = convertStreamToString(in);
SAXReader reader = new SAXReader(); reader.read(new InputSource(new StringReader(body))); return "DOM4J XXE......"; } catch (Exception e) { return "EXCEPT ERROR!!!"; } } public static String convertStreamToString(java.io.InputStream is) { java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } }
|
访问路径:http://127.0.0.1:8886/dom4jdemo/vul
关键字:SAXReader符合DOM4J 解析 并没有会XXE进行防护
抓包:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| GET /dom4jdemo/vul HTTP/1.1 Host: 127.0.0.1:8886 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Upgrade-Insecure-Requests: 1 Sec-Fetch-Mode: navigate User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:139.0) Gecko/20100101 Firefox/139.0 Cookie: JSESSIONID=C6223D7ACFF84109FA5B62818C028CEA; remember-me=YWRtaW46MTc1MDczMTMxNjU2Njo2M2MzM2U1NTc0NDc0NjE2Mjc3NGIwYjVmMzEwNjgwOQ; XSRF-TOKEN=40496df0-4bfb-4b2a-b7d4-50cf6715dc75 Sec-Fetch-Site: none Priority: u=0, i Accept-Encoding: gzip, deflate, br, zstd Sec-Fetch-Dest: document Sec-Fetch-User: ?1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
|
改为POST,修改Content-Type值为:text/xml,并在请求体中加上paylod,可以读取本地文件
1 2 3 4 5 6 7
| <?xml version="1.0"?> <!DOCTYPE root [ <!ENTITY file SYSTEM "file:///D:/abc/demo.txt"> ]> <root> &file; </root>
|

XXE 漏洞审计函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| XMLReaderFactory createXMLReader SAXBuilder SAXReader SAXParserFactory newSAXParser Digester DocumentBuilderFactory DocumentBuilder XMLReader DocumentHelper XMLStreamReader SAXParser SAXSource TransformerFactory SAXTransformerFactory SchemaFactory Unmarshaller XPathExpression javax.xml.parsers.DocumentBuilder javax.xml.parsers.DocumentBuilderFactory javax.xml.stream.XMLStreamReader javax.xml.stream.XMLInputFactory org.jdom.input.SAXBuilder org.jdom2.input.SAXBuilder org.jdom.output.XMLOutputter oracle.xml.parser.v2.XMLParser javax.xml.parsers.SAXParser org.dom4j.io.SAXReader org.dom4j.DocumentHelper org.xml.sax.XMLReader javax.xml.transform.sax.SAXSource javax.xml.transform.TransformerFactory javax.xml.transform.sax.SAXTransformerFactory javax.xml.validation.SchemaFactory javax.xml.validation.Validator javax.xml.bind.Unmarshaller javax.xml.xpath.XPathExpression java.beans.XMLDecoder
|
**XXE **漏洞防御
目前常用的修复方案为 setFeature。设置 setFeature 打开或关闭一些配置,进而防御 XXE 攻击。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @RequestMapping(value = "/Digester/sec", method = RequestMethod.POST) public String DigesterSec(HttpServletRequest request) { try { String body = WebUtils.getRequestBody(request); logger.info(body); Digester digester = new Digester(); digester.setFeature("http://apache.org/xml/features/disallow-doctypedecl", true); digester.setFeature("http://xml.org/sax/features/external-general entities", false); digester.setFeature("http://xml.org/sax/features/external-parameterentities", false); digester.parse(new StringReader(body)); return "Digester xxe security code"; } catch (Exception e) { logger.error(e.toString()); return EXCEPT; } }
|
URL跳 转漏洞:
URL重定向漏洞是指当应用程序使用 Java 的内置函数或类来处理 URL 重定向时,如果没有正确地验证输入,则可能允许攻击者构造恶意的 URL 来重定向到恶意网站。这样,攻击者就可以让用户访问恶意网站。
302 重定向之 sendRedirect
1 2 3 4 5 6 7 8 9 10 11
|
@RequestMapping("/sendRedirect") @ResponseBody public static void sendRedirect(HttpServletRequest request, HttpServletResponse response) throws IOException { String url = request.getParameter("url"); response.sendRedirect(url); }
|
1 2 3 4 5 6 7 8 9 10 11 12
|
@RequestMapping("/setHeader") @ResponseBody public static void setHeader(HttpServletRequest request, HttpServletResponse response) { String url = request.getParameter("url"); response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); response.setHeader("Location", url); }
|
URL 跳转和 SSRF 漏洞区别
在调试代码时不难发现,URL 跳转动作主要发生在客户端处,也就是以你的浏览器进行访问和你直接使用浏览器访问意思相同。
而 SSRF 漏洞请求 URL 主要发生在服务端处,也就是服务器端请求了 URL,然后将他获取到的资源返回给了你。