Java 审计之SSRF篇

0x00 前言

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

0x01 SSRF漏洞详解

原理:

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

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

ssrf作用:

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

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

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

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

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

php ssrf中的伪协议:

  1. file dict sftp ldap tftp gopher

Java ssrf 中的伪协议:

  1. file ftp mailto http https jar netdoc

0x02 SSRF产生过程

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

SSRF中内网探测

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

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

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

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

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

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

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

尝试一下能不能读取文件

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

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

代码如下:

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

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

SSRF中的读取文件

代码如下:

  1. @WebServlet("/readfileServlet")
  2. public class downloadServlet extends HttpServlet {
  3. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  4. this.doGet(request,response);
  5. }
  6. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  7. String url = request.getParameter("url");
  8. int len;
  9. OutputStream outputStream = response.getOutputStream();
  10. URL file = new URL(url);
  11. byte[] bytes = new byte[1024];
  12. InputStream inputStream = file.openStream();
  13. while ((len = inputStream.read(bytes)) > 0) {
  14. outputStream.write(bytes, 0, len);
  15. }
  16. }
  17. }

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

官方说明文档:

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

详细说明:

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

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

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

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

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

SSRF中的文件下载

漏洞代码:

  1. @WebServlet("/downloadServlet")
  2. public class downloadServlet extends HttpServlet {
  3. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  4. this.doGet(request,response);
  5. }
  6. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  7. String filename = "1.txt";
  8. String url = request.getParameter("url");
  9. response.setHeader("content-disposition", "attachment;fileName=" + filename);
  10. int len;
  11. OutputStream outputStream = response.getOutputStream();
  12. URL file = new URL(url);
  13. byte[] bytes = new byte[1024];
  14. InputStream inputStream = file.openStream();
  15. while ((len = inputStream.read(bytes)) > 0) {
  16. outputStream.write(bytes, 0, len);
  17. }
  18. }
  19. }

输入:

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

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

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

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

参考文章

  1. https://xz.aliyun.com/t/2761#toc-1
  2. https://xz.aliyun.com/t/206/
  3. 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. Mybatis 循环删除/插入

    <foreach collection="array" open="(" separator="," close=")&qu ...

  2. Spring注解驱动开发03(按照条件注册bean)

    按照条件注册bean 使用@Conditional注解来控制bean的注册 使用步骤 先实现Condition接口,条件写在matches方法里 注意事项:Condition接口是org.spring ...

  3. SwitchyOmega 配置

    1.google 扩展程序里面的chrome 网上应用店里面安装Proxy SwitchyOmega 2.新建情景模式 3.配置代理 4.自动切换添加新建的情景模式,最后保存

  4. 个人项目WordCount(C++/QT)

    个人项目WordCount(C++/QT) GitHub项目地址:https://github.com/Nova-cjp/Word-Count 百度云链接:https://pan.baidu.com/ ...

  5. .sync 修饰符

    vue 修饰符sync的功能是:当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定 //写一个(子)组件Child.vue <template> <div c ...

  6. computed&watch

    computed 定义:根据其他属性被计算出来的值 computed :{ [key: string]: Function | { get: Function, set: Function } } 是 ...

  7. ZK的watch机制

    1.watcher原理框架 由图看出,zk的watcher由客户端,客户端WatchManager,zk服务器组成.整个过程涉及了消息通信及数据存储. zk客户端向zk服务器注册watcher的同时, ...

  8. 必看!2020最新黑马JAVA 学习路线

    https://www.fang1688.cn/2020/08/24/%e5%bf%85%e7%9c%8b%ef%bc%81java-%e5%ad%a6%e4%b9%a0%e8%b7%af%e7%ba ...

  9. PAT甲级真题 A1025 PAT Ranking

    题目概述:Programming Ability Test (PAT) is organized by the College of Computer Science and Technology o ...

  10. React-Native知识点相关

    React-Native相关 一,为什么要使用React-native? Hybrird的首屏时间太慢,白屏太久,影响用户体验: 原生native开发成本较高: 这里补充一点Webview的性能优化: ...