• java代码审计-SSRF


    0x00 前言

    SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定 URL 地址获取网页文本内容,加载指定地址的图片,下载等等。这里主要介绍java中URLConnection()openStream()两个方法产生SSRF的原理和修复方法

    0x01 URLConnection

        @RequestMapping(value = "/urlConnection/vuln", method = {RequestMethod.POST, RequestMethod.GET})
        public String URLConnectionVuln(String url) {
            return HttpUtils.URLConnection(url);
        }
    
    

    这里调用的是HttpUtils.URLConnection(url)

        public static String URLConnection(String url) {
            try {
                URL u = new URL(url);
                URLConnection urlConnection = u.openConnection();
                BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); //send request
                // BufferedReader in = new BufferedReader(new InputStreamReader(u.openConnection().getInputStream()));
                String inputLine;
                StringBuilder html = new StringBuilder();
    
                while ((inputLine = in.readLine()) != null) {
                    html.append(inputLine);
                }
                in.close();
                return html.toString();
            } catch (Exception e) {
                logger.error(e.getMessage());
                return e.getMessage();
            }
        }
    
    

    跟进URLConnection方法,而URLConnection里又调用了URL.openConnection()来发起请求, 这个请求可以直接执行url协议(伪协议)
    漏洞利用:
    使用file协议读文件
    image.png
    使用http协议访问百度
    image.png
    修复方法:
    这里先是对url调用了SecurityUtil.isHttp()来进行检查

        @GetMapping("/urlConnection/sec")
        public String URLConnectionSec(String url) {
    
            // Decline not http/https protocol
            if (!SecurityUtil.isHttp(url)) {
                return "[-] SSRF check failed";
            }
    
            try {
                SecurityUtil.startSSRFHook();
                return HttpUtils.URLConnection(url);
            } catch (SSRFException | IOException e) {
                return e.getMessage();
            } finally {
                SecurityUtil.stopSSRFHook();
            }
    
        }
    

    SecurityUtil.isHttp()比较简单,就是判断url是否是以http://或https://开头

        public static boolean isHttp(String url) {
            return url.startsWith("http://") || url.startsWith("https://");
        }
    

    单纯的ban掉其他协议显然是不够的,还不能够防止对内网进行探测,于是在获取url内容之前,开启了一个hook来对用户行为进行监听,SecurityUtil.startSSRFHook(),就有效防止了ssrf攻击

    0x02 openStream

    openStream()方法的实现也是调用了 openConnection生成一个 URLConnection 对象,然后再通过这个对象调用的getInputStream()方法的

        @GetMapping("/openStream")
        public void openStream(@RequestParam String url, HttpServletResponse response) throws IOException {
            InputStream inputStream = null;
            OutputStream outputStream = null;
            try {
                String downLoadImgFileName = WebUtils.getNameWithoutExtension(url) + "." + WebUtils.getFileExtension(url);
                // download
                response.setHeader("content-disposition", "attachment;fileName=" + downLoadImgFileName);
    
                URL u = new URL(url);
                int length;
                byte[] bytes = new byte[1024];
                inputStream = u.openStream(); // send request
                outputStream = response.getOutputStream();
                while ((length = inputStream.read(bytes)) > 0) {
                    outputStream.write(bytes, 0, length);
                }
    
            } catch (Exception e) {
                logger.error(e.toString());
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        }
    

    通过WebUtils.getNameWithoutExtension(url) + "." + WebUtils.getFileExtension(url)来获取下载文件名,然后执行inputStream = u.openStream(); 来看一下openStream(),也是调用了openConnection(),也会根据传入的协议的不同来进行处理

        public final InputStream openStream() throws java.io.IOException {
            return openConnection().getInputStream();
        }
    

    由此可以得知,openStream()方法同样也可以进行ssrf来探测内网以及文件下载,修复方案同上

    0x03 总结

    关键词:
    URLConnection、openConnection、openStream
    漏洞利用:
    关于SSRF漏洞利用相关可以看这篇文章,总结的很详细!
    从一文中了解SSRF的各种绕过姿势及攻击思路

  • 相关阅读:
    第11章 Java集合(一)
    防暑降温
    如何签署exe或Windows应用程序?
    使用多阶段和多尺度联合通道协调注意融合网络进行单图去雨[2022论文]
    如何利用Airtest做一些简单的装包小任务
    Ubuntu20.04 PostgreSQL 14 安装配置记录
    uniapp 跳转页面保存和刷新 拦截器的使用
    音容笑貌,两臻佳妙,人工智能AI换脸(deepfake)技术复刻《卡萨布兰卡》名场面(Python3.10)
    BLE Mesh中的Sequence number和IV Index
    [RK3568 Android11] Binder通信整体框架
  • 原文地址:https://www.cnblogs.com/Ne2o1/p/17192112.html