Java 审计之SSRF篇

0x00 前言

本篇文章来记录一下Java SSRF的审计学习相关内容。

0x01 SSRF漏洞详解

原理:

服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。

大部分的web服务器架构中,web服务器自身都可以访问互联网和服务器所在的内网。

ssrf作用:

对外网服务器所在的内网、本地进行端口扫描,获取一些服务的banner信息 。

攻击运行在内网或者本地的应用程序。

对内网web应用进行指纹识别,通过访问默认文件实现 。

攻击内外网的web应用。sql注入、struct2、redis等。

利用file协议读取本地文件等。

php ssrf中的伪协议:

file dict sftp ldap tftp gopher

Java ssrf 中的伪协议:

file ftp mailto http https jar netdoc

0x02 SSRF产生过程

在java中ssrf会分比较多的场景,不像PHP中那样支持各种伪协议都可以去直接使用。

SSRF中内网探测

@WebServlet("/ssrfServlet")
public class ssrfServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String url = request.getParameter("url"); //接收url的传参
String htmlContent;
PrintWriter writer = response.getWriter(); //获取响应的打印流对象
URL u = new URL(url); //实例化url的对象
try {
URLConnection urlConnection = u.openConnection();//打开一个URL连接,并运行客户端访问资源。
HttpURLConnection httpUrl = (HttpURLConnection) urlConnection; //强转为HttpURLConnection
BufferedReader base = new BufferedReader(new InputStreamReader(httpUrl.getInputStream(), "UTF-8")); //获取url中的资源
StringBuffer html = new StringBuffer();
while ((htmlContent = base.readLine()) != null) {
html.append(htmlContent); //htmlContent添加到html里面
}
base.close(); writer.println(html);//响应中输出读取的资源
writer.flush(); } catch (Exception e) {
e.printStackTrace();
writer.println("请求失败");
writer.flush();
}
}

在代码中HttpURLConnection httpUrl = (HttpURLConnection) urlConnection;,这个地方进行了强制转换,去某度搜索了一下具体用意。得出结论:

URLConnection:可以走邮件、文件传输协议。
HttpURLConnection 只能走浏览器的HTTP协议

也就是说使用了强转为HttpURLConnection后,利用中只能使用http协议去探测该服务器内网的其他应用。

http://localhost:8080/ssrfServlet?url=http://www.baidu.com

这里用来百度来做一个演示,因为懒得自己再在内网中搭建一个环境了。

在代码中,我们未对接收过来的url进行校验,校验其url是否是白名单的url就直接进行了创建url对象进行访问和读取资源,导致了ssrf的产生。

尝试一下能不能读取文件

这里会发现根本读取不了,因为这里只支持http和https的协议。

下面来试试,在不强制转换成HttpURLConnection的情况下试试。

代码如下:

@WebServlet("/ssrfServlet")
public class ssrfServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String url = request.getParameter("url"); //接收url的传参
String htmlContent;
PrintWriter writer = response.getWriter(); //获取响应的打印流对象
URL u = new URL(url); //实例化url的对象
try {
URLConnection urlConnection = u.openConnection();//打开一个URL连接,并运行客户端访问资源。
// HttpURLConnection httpUrl = (HttpURLConnection) urlConnection; //强转为HttpURLConnection
BufferedReader base = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8")); //获取url中的资源
StringBuffer html = new StringBuffer();
while ((htmlContent = base.readLine()) != null) {
html.append(htmlContent); //htmlContent添加到html里面
}
base.close(); writer.println(html);//响应中输出读取的资源
writer.flush(); } catch (Exception e) {
e.printStackTrace();
writer.println("请求失败");
writer.flush();
}
http://localhost:8080/ssrfServlet?url=file:///c:%5c%5cwindows%5c%5cwin.ini

可以成功读取到c:\windows\win.ini的文件。

SSRF中的读取文件

代码如下:

@WebServlet("/readfileServlet")
public class downloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
} protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String url = request.getParameter("url");
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);
}
}
}

和上面的代码对比一下,发现其实都大致相同,唯一不同的地方是一个是用openStream方法获取对象,一个是用openConnection获取对象。两个方法类似。

官方说明文档:

openConnection():返回一个实例,该实例表示与所引用的远程对象的连接。 返回类型: URLConnection
openStream():打开与此连接,并返回一个值以从该连接读取。 返回类型: InputStream

详细说明:

openConnection:返回一个URLConnection对象,它表示到URL所引用的远程对象的连接。每次调用此URL的协议处理程序的openConnection方法都打开一个新的连接。如果URL的协议(例如,HTTP或JAR)存在属于以下包或其子包之一的公共、专用URLConnection子类:java.lang、java.io、java.util、java.net,返回的连接将为该子类的类型。例如,对于HTTP,将返回HttpURLConnection,对于JAR,将返回JarURLConnection。(返回到该URL的URLConnection!)

openStream():打开到此URL的连接并返回一个用于从该连接读入的InputStream。

这里启动一下服务器,测试一下。

http://127.0.0.1:8080//downloadServlet?url=file:///C:%5c%5c1.txt

注意: 这里是三个斜杆,并且反斜杠需要url编码 否则就会报错

未经过url编码直接传入反斜杠

SSRF中的文件下载

漏洞代码:

@WebServlet("/downloadServlet")
public class downloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request,response);
} protected void doGet(HttpServletRequest request, HttpServletResponse 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);
}
}
}

输入:

http://localhost:8080/downloadServlet?url=file:///c:%5c%5c1.txt

这样就把文件给下载下来了,ssrf中的文件下载和文件读取不同点在于响应头。

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

这段代码,设置mime类型为文件类型,访问浏览器的时候就会被下载下来。

参考文章

https://xz.aliyun.com/t/2761#toc-1
https://xz.aliyun.com/t/206/
https://xz.aliyun.com/t/7186

0x03 结尾

SSRF的一些产生也不止文章里面写到的这么一点,包括一些第三方的组件,如果在未经过验证的情况下发起一个远程请求,那么都有可能存在SSRF漏洞。

后面打算找套源码专门审计一下SSRF。

Java 审计之SSRF篇的更多相关文章

  1. Java审计之XSS篇

    Java审计之XSS篇 0x00 前言 继续 学习一波Java审计的XSS漏洞的产生过程和代码. 0x01 Java 中XSS漏洞代码分析 xss原理 xss产生过程: 后台未对用户输入进行检查或过滤 ...

  2. Java 审计之XXE篇

    Java 审计之XXE篇 0x00 前言 在以前XXE漏洞了解得并不多,只是有一个初步的认识和靶机里面遇到过.下面来 深入了解一下该漏洞的产生和利用. 0x01 XXE漏洞 当程序在解析XML输入时, ...

  3. Java审计之SQL注入篇

    Java审计之SQL注入篇 0x00 前言 本篇文章作为Java Web 审计的一个入门文,也是我的第一篇审计文,后面打算更新一个小系列,来记录一下我的审计学习的成长. 0x01 JDBC 注入分析 ...

  4. Java审计之命令执行篇

    Java审计之命令执行篇 0x00 前言 在Java中能执行命令的类其实并不多,不像php那样各种的命令执行函数.在Java中目前所知的能执行命令的类也就两种,分别是Runtime和 ProcessB ...

  5. Java审计之文件操作漏洞

    Java审计之文件操作漏洞篇 0x00 前言 本篇内容打算把Java审计中会遇到的一些文件操作的漏洞,都给叙述一遍.比如一些任意文件上传,文件下载,文件读取,文件删除,这些操作文件的漏洞. 0x01 ...

  6. 漏洞经验分享丨Java审计之XXE(下)

    上篇内容我们介绍了XXE的基础概念和审计函数的相关内容,今天我们将继续分享Blind XXE与OOB-XXE的知识点以及XXE防御方法,希望对大家的学习有所帮助! 上期回顾  ◀漏洞经验分享丨Java ...

  7. 漏洞经验分享丨Java审计之XXE(上)

    最近在审计公司的某个项目时(Java方面),发现了几个有意思的Blind XXE漏洞,我觉得有必要分享给大家,尤其是Java审计新手,了解这些内容可以让你少走一些弯路. Java总体常出现的审计漏洞如 ...

  8. Java多线程系列--“基础篇”11之 生产消费者问题

    概要 本章,会对“生产/消费者问题”进行讨论.涉及到的内容包括:1. 生产/消费者模型2. 生产/消费者实现 转载请注明出处:http://www.cnblogs.com/skywang12345/p ...

  9. Java多线程系列--“基础篇”04之 synchronized关键字

    概要 本章,会对synchronized关键字进行介绍.涉及到的内容包括:1. synchronized原理2. synchronized基本规则3. synchronized方法 和 synchro ...

随机推荐

  1. Eclipse中构建maven项目的两种方式

    Eclipse中构建maven项目的两种方式 方式一: 1.构建maven项目 1.1 新建meven项目,可在Other中找到maven文件夹 1.2 进入maven项目后,点击next 1.3 在 ...

  2. Go:grpc

    一.grpc安装 将 https://github.com/google/go-genproto 修改文件名放到 $GOPATH/src/google.golang.org/genproto 将 ht ...

  3. Open vSwitch with DPDK

    http://docs.openvswitch.org/en/latest/intro/install/dpdk/

  4. linux tmpfs及消耗内存脚本

    一.tmpfs介绍 tmpfs是一种虚拟内存文件系统,正如这个定义它最大的特点就是它的存储空间在VM里面VM是由linux内核里面的vm子系统管理的东西,现在大多数操作系统都采用了虚拟内存管理机制VM ...

  5. web渗透测试之sqlmap拿到数据库信息

    通过扫描我们发现目标网站存在sql注入漏洞,我们访问该里面后发现该网站里面有个表格提交参数.确实存在没有过滤 使用sqlmap扫描发现漏洞的确存在,这里是布尔盲注 查看当前数据库名 查看表名得到以下信 ...

  6. 【转】Linux环境搭建FTP服务器与Python实现FTP客户端的交互介绍

    Linux环境搭建FTP服务器与Python实现FTP客户端的交互介绍 FTP 是File Transfer Protocol(文件传输协议)的英文简称,它基于传输层协议TCP建立,用于Interne ...

  7. 小程序 RecorderManager计时不准确问题

    官方文档:RecorderManager 录音管理器,内部实现计时不准确.有以下俩个问题: 点击暂停继续,当录音结束时,stop返回的时间包含了暂停的那一段时间. 正常录音,录音文件的时长有概率少个1 ...

  8. 什么是URL标准化

    http://www.wocaoseo.com/thread-194-1-1.html RL标准化是来自于国外matt cutts的博客文章,期望能给蜘蛛一个规范化的URL作为收录的标准.举个简单的例 ...

  9. python+requests+unittest执行自动化接口测试

    1.安装requests.xlrd.json.unittest库 <1>pip 命令安装: pip install requestspip install xlrdpip install ...

  10. go语言之字符串、指针、数组、切片、结构struct、面向对象

    一: 字符串 概述: Go 语言将字符串作为 种原生的基本数据类型,字 符串的初始化可以使用字符串字面量. (1)字符串是常量,可以通过类 数组 索引访问其字节单元,但是不能修改某个字节的值 (2)宇 ...