首页 > 编程语言 >Java-SSRF

Java-SSRF

时间:2022-11-07 19:24:45浏览次数:61  
标签:Java SSRF url request URL https new response

漏洞分析

原理:

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

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

作用:

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

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

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

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

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

php ssrf中的伪协议:

file dict sftp ldap tftp gopher

Java ssrf 中的伪协议:

file ftp mailto http https jar netdoc

产生过程

java中ssrf会分比较多的场景

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的产生

尝试一下能不能读取文件

image-20221107185753159

发现根本读取不了,因为这里只支持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

image-20221107185837760

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。

payload

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

image-20221107190033021

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);
            }
    }
}

payload:

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

image-20221107190151740

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

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

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

拓展

imageIO中的SSRF

imageIO类是jdk中自带的一个类,主要用于操作一些图片文件。比如读写、压缩图片。

ssrf 类:

public class ssrf {
    public static BufferedImage read(URL url) throws IOException {
        if (url == null) {
            System.out.println("输入内容为空");
        }


        InputStream  istream = url.openStream();
        ImageInputStream stream =  ImageIO.createImageInputStream(istream);  //获取文件流


        BufferedImage bi = ImageIO.read(stream);  //返回 BufferedImage作为供给的解码结果

        return bi;
    }
}

servlet:

@WebServlet("/httpclientServlet")
public class httpclientServlet extends HttpServlet {


    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String geturl = request.getParameter("url");
        ServletOutputStream outputStream = response.getOutputStream();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        URL url = new URL(geturl);
        BufferedImage image = ssrf.read(url);

        ImageIO.write(image, "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);
        }


    }

}

先来测试一下传入一个图片的url试试

image-20221107190511074

成功输出出来了。证明远程请求图片的功能是没问题的

再来读取一下本地文件试试

image-20221107190536094

发现报错了 貌似读取不了除了图片以外的文件。

再来尝试一下读取本地的图片试试

image-20221107190556401

小结

SSRF漏洞出现的场景有很多,如在线翻译、转码服务、图片收藏/下载、信息采集、邮件系统或者从远程服务器请求资源等。通常可以从一些http请求函数入手

image-20220922121932083

除表6-1中列举的部分敏感函数外,还有很多需要关注的类,如HttpClient类、URL类等。根据实际场景的不同,这些类中的一些方法同样可能存在着SSRF漏洞。此外,还有一些封装后的类同样需要留意,如封装HttpClient后的Request类。审计
此漏洞时,首先应该确定被审计的源程序有哪些功能,通常情况下从其他服务器应用获取数据的功能出现的概率较大,确定好功能后再审计对应功能的源代码能使漏洞挖掘事半功倍。

参考文章

https://xz.aliyun.com/t/2761#toc-1
https://xz.aliyun.com/t/206/
https://xz.aliyun.com/t/7186
https://www.cnblogs.com/nice0e3/p/13683023.html
https://docs.ioin.in/writeup/joychou.org/_index_php_web_javassrf_html/index.html
https://www.fatalerrors.org/a/ssrf-of-java-audit.html
https://xz.aliyun.com/t/7405
https://xz.aliyun.com/t/6993
https://opnsec.com/2018/07/into-the-borg-ssrf-inside-google-production-network/
https://blog.appsecco.com/finding-ssrf-via-html-injection-inside-a-pdf-file-on-aws-ec2-214cc5ec5d90
https://mp.weixin.qq.com/s?__biz=MzIzOTQ5NjUzOQ==&mid=2247483742&idx=1&sn=e7265d5351a6d9ed30d90be1c17be041
https://xz.aliyun.com/t/2761
https://xz.aliyun.com/t/5665

标签:Java,SSRF,url,request,URL,https,new,response
From: https://www.cnblogs.com/gk0d/p/16867112.html

相关文章

  • JavaScript之数组高阶API—reduce()
    一文搞懂JavaScript数组中最难的数组API——reduce()前面我们讲了数组的一些基本方法,今天给大家讲一下数组的reduce(),它是数组里面非常重要也是比较难的函数,那么这篇文章......
  • JAVA MD5加密工具类
     importjava.io.UnsupportedEncodingException;importjava.security.MessageDigest;importjava.security.NoSuchAlgorithmException;/***@Author:JCccc*@CreateTim......
  • JAVA 责任链设计模式
    这次介绍责任链模式,采用最普遍的请假例子来编码实现。先给列出个模拟的需求,一个人请假,调用一个接口,传入的参数是他请假的天数。然后,请假的天数---->如果小于2天,由直属领导......
  • JAVA回调函数简单讲解 CallBack
    回调,其实就是有个回应的那种感觉。那么,接下来,我们就用消息推送的场景,简简单单地讲解下回调函数的使用。直接看代码,先创建一个回调接口,MessageCallBack/***@Author:JCccc......
  • Java-xss
    XSS代码分析在php里面会使用echo对用户输入的参数进行直接输出,导致了xss漏洞的产生。而在Java里面会将接收到的未经过滤的参数共享到request域中,在jsp的页面里面使用EL表......
  • 3183-2020-Java-国赛-4-3
    看题看半天看不懂,原来它这个包装数量是指能装的商品数量啊,这个价格指的不是单个包装的价格,而是包装里包含商品的总价10080200150意思是,第一种200元100个商品、第二......
  • 方法重载,可变参数,作用域,构造器,this---JAVA
    一、方法重载(1)方法名:必须相同;(2)参数列表:必须不同(参数类型或个数或顺序,至少有一样不同,参数名无要求)(3)返回类型:无要求publicclassvar{publicstaticvoidmain(String[......
  • java 手机号里 4位数字变成 * ,脱敏处理
    效果:代码实现: Stringphone="13100001111";StringphoneResult=phone.replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2");System.out.println(phoneResult);结果: ps......
  • java 获取IP地址 无法获取到真实的IP地址springboot 获取访问接口的请求的IP地址
    工具类:springboot获取访问接口的请求的IP地址问题:无法获取到真实IP地址  获取出来全是 192.xxx.xxx.xxx开头或者 172.xxx.xxx.xxx 开头 解决方案:nginx代理需......
  • Java 将两个对象list里面的 某个字段值抽取到一个list里
    场景举例:两个List(rooms1和rooms2)里面放的对象都是Room,现在想把两个List里面的room的id都抽取出来,放在一个List里面。 实现代码:List<Integer>idList=Stream.......