Java 审计之SSRF篇

Java审计之SSRF篇0x00前言本篇文章来记录一下JavaSSRF的审计学习相关内容。0x01SSRF漏洞详解原理:服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

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

Java 审计之SSRF篇

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

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

尝试一下能不能读取文件

Java 审计之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

Java 审计之SSRF篇

可以成功读取到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编码 否则就会报错

Java 审计之SSRF篇

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

Java 审计之SSRF篇

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

Java 审计之SSRF篇

这样就把文件给下载下来了,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。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119921.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ScheduledExecutorService定时周期执行指定的任务

    ScheduledExecutorService定时周期执行指定的任务一:简单说明ScheduleExecutorService接口中有四个重要的方法,其中scheduleAtFixedRate和scheduleWithFixedDelay在实现定时程序时比较方便。下面是该接口的原型定义java.util.concurrent.ScheduleExecutorServiceextends ExecutorServiceextends Execut

    2022年6月2日
  • DeviceIOControl实战「建议收藏」

    DeviceIOControl实战「建议收藏」实战DeviceIoControl之一:通过API访问设备驱动程序Q 在NT/2000/XP中,我想用VC编写应用程序访问硬件设备,如获取磁盘参数、读写绝对扇区数据、测试光驱实际速度等,该从哪里入手呢?A 在NT/2000/XP中,应用程序可以通过API函数DeviceIoControl来实现对设备的访问—获取信息,发送命令,交换数据等。利用该接口函数向指定的设备驱动发送正确

    2022年9月7日
  • npm使用淘宝镜像(npm切换淘宝镜像)

    1.通过cnpm使用淘宝镜像:npminstall-gcnpm–registry=https://registry.npm.taobao.org2.将npm设置为淘宝镜像:npmconfigsetregistryhttps://registry.npm.taobao.org3.查看cnpm镜像设置:cnpmconfiggetregistry

    2022年4月10日
  • Android屏幕适配AndroidAutoSize的使用「建议收藏」

    Android屏幕适配AndroidAutoSize的使用「建议收藏」Android屏幕适配AndroidAutoSize的使用AndroidAutoSize的使用加入依赖配置AndroidManifest.xml主单位或者副单位主单位的配置副单位的配置主单位的使用副单位的使用插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML图表FLowchart流程图导出与导入导出导入AndroidAutoSize的使

    2022年5月26日
  • 【C#】后台线程IsBackground「建议收藏」

    【C#】后台线程IsBackground「建议收藏」简单点来说:C#中的线程分前台线程和后台线程。对于前台线程来说,如果这些线程不退出,则主线程无法退出,则整个进程也无法退出。会造成即使界面窗口关掉了,但是进程管理器里还有该程序。因此,在关闭窗口时,需要编程显示的把这些前台线程关掉才行。但是,这样就会带来个问题,需要记录这些前台线程的实例才行,很不方便。为此,可以把线程定义为后台线程。后台线程与前台线程的唯一区别就是:后台线程不需要主动关闭。当所有前台线程都退出以后,主线程会自动的关掉后台线程,然后让进程退出。定义线程为后台线程的方法为:Thr

    2022年10月16日
  • 自动化测试+性能面试题整理–个人最新【持续更新】「建议收藏」

    自动化测试+性能面试题整理–个人最新【持续更新】「建议收藏」写在前面公司要求招一名自动化测试,能力要求不高,1年左右自动化经验+部分性能经验即可,让我出一份题,我就百度+公司项目遇到的问题,出了一份,出题整体思路是:接口自动化问题+性能问题+规划的ui、app自动化+整体质量体系建设等多方面考虑。下面是正题自动化测试面试题1:基础篇目的:验证求职者是否在自动化测试岗位有实际应用于生产的工作经验1、使用什么测试框架做的上一个项目的自动化测试?说下怎么…

    2022年9月29日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号