JAVA代码审计之SSRF

0x01 SSRF简介

SSRF 是 Server-Side Request Forge 的英文首字母缩写,中文意思是服务器端请求伪造。Web 应用程序往往会提供一些能够从远程获取图片或是文件的接口,在这些接口上用户使用指定的 URL 便能完成远程获取图片、下载文件等操作。攻击者可以通过使用 file 协议来读取服务器本地/etc/passwd 和/proc/self/cmdline 等敏感文件,同时攻击者也可以利用被攻击的服务器绕过防火墙直接对处于内网的机器发起进一步的攻击。

Java中的SSRF支持以下协议:http,https,file,ftp,mailto,jar,netdoc

0x02 审计常见的函数

URL.openConnection()URL.openStream()HttpClient.execute()HttpClient.executeMethod()HttpURLConnection.connect()HttpURLConnection.getInputStream()HttpServletRequest()BasicHttpEntityEnclosingRequest()DefaultBHttpClientConnection()BasicHttpRequest()HttpURLConnection

0x03 常见的解析接口

  1. HttpClient

HttpClient 是 Apache Jakarta Common 下的一个子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。但是在默认情况下,其也会产生 SSRF 漏洞。

@RestController@RequestMapping("/ssrf")public class HttpClientController {    @GetMapping("/httpclient/ssrf")    public String HttpClientDemo(@RequestParam String url) throws IOException {        StringBuilder result = new StringBuilder();        //创建Httpclient对象        CloseableHttpClient client = HttpClients.createDefault();         //创建GET请求        HttpGet httpGet = new HttpGet(url);        //发送请求        HttpResponse httpResponse = client.execute(httpGet);        //获取响应内容        BufferedReader rd = new BufferedReader(new                InputStreamReader(httpResponse.getEntity().getContent()));        String line;        while ((line = rd.readLine()) != null) {            result.append(line);        }        return result.toString();    }}

2.URLConnection

URLConnection,是Java原生的HTTP请求方法。URLConnection 类包含了许多方法可以让你的 URL 在网络上通信。此类的实例既可用于读取URL所引用的资源,也可用于写入URL所引用资源.

@RestController@RequestMapping("/ssrf")public class UrlConnectionController {    @GetMapping("/urlconnection/ssrf")    public String UrlConnectionDemo(@RequestParam String url) throws IOException    {        StringBuilder result = new StringBuilder();        URL url1 = new URL(url);        URLConnection urlConn = url1.openConnection();        urlConn.connect();        BufferedReader in = new BufferedReader(new InputStreamReader(                urlConn.getInputStream()));        String inputLine;        while ((inputLine = in.readLine()) != null) {            result.append(inputLine);        }        in.close();        return result.toString();    }}

3.HttpURLConnection

HttpURLConnection 是 Java 的标准类,它继承自 URLConnection,可用于向指定网站发送 GET 请求与 POST 请求。同样的,在没有过滤的默认情况下其会产生 SSRF 漏洞。

@RestController@RequestMapping("/ssrf")public class HttpUrlConnectionController {    url=https://www.baidu.com    @GetMapping("/httpurlconnection/ssrf")    public String HttpUrlConnectionDemo(@RequestParam String url) throws            IOException {        StringBuilder result = new StringBuilder();        URL url1 = new URL(url);        HttpURLConnection connection = (HttpURLConnection)                 url1.openConnection();                //设置请求方式        connection.setRequestMethod("GET");        int responseCode = connection.getResponseCode();        if (responseCode == HttpURLConnection.HTTP_OK){            BufferedReader in = new BufferedReader(new InputStreamReader(                    connection.getInputStream()));            String inputLine;            while ((inputLine = in.readLine()) != null) {                result.append(inputLine);            }        }        return result.toString();    }}

4.ImageIO

ImageIO 是Java读写图片操作的一个类。在代码审计中,如果目标使用了 ImageIO.read 读取图片,且读取的图片地址可控的话,可能会存在SSRF漏洞。

@RestController@RequestMapping("/ssrf")public class ImageIOController {    @GetMapping("/imageio/ssrf")    public String ImageioDemo(@RequestParam String url) throws IOException {        StringBuilder result = new StringBuilder();        URL url1 = new URL(url);        Image image = ImageIO.read(url1);        return image.toString();    }}

5.RestTemplate

RestTemplate 是从Spring3.0 开始支持的一个HTTP 请求工具,它提供了常见的REST请求方案的模版,例如GET 请求、POST 请求、PUT 请求等等。从名称上来看,是更针对RESTFUL风格API设计的。但通过他调用普通的HTTP接口也是可以造成ssrf的。

@RestController@RequestMapping("/ssrf")public class RestTemplateController {    @GetMapping("/resttemplate/ssrf")    public String RestTemplateDemo(@RequestParam String url){        RestTemplate restTemplate = new RestTemplate();        String result = restTemplate.getForObject(url ,String.class);        return result;    }}

0x04 SSRF漏洞修复

对于 SSRF 漏洞的修复比较简单,总结下来主要包括以下几点:正确处理 302 跳转(在业务角度看,不能直接禁止 302,而是对跳转的地址重新104 网络安全 Java 代码审计实战进行检查)。限制协议只能为 HTTP/HTTPS,防止跨协议。设置内网 IP 黑名单(正确判定内网 IP、正确获取 host)。在内网防火墙上设置常见的 Web 端口白名单(防止端口扫描,则可能业务受限比较大)

    // 判断是否是http类型    public static boolean isHttp(String url) {        return url.startsWith("http://") || url.startsWith("https://");    }        // 判断是否为内网    public static boolean isIntranet(String url) {        Pattern reg = Pattern.compile("^(127\.0\.0\.1)|(localhost)|        (10\.\d{1,3}\.\d{1,3}\.\d{1,3})|(172\.((1[6-9])|(2\d)|        (3[01]))\.\d{1,3}\.\d{1,3})|(192\.168\.\d{1,3}\.\d{1,3})$");        Matcher match = reg.matcher(url);        Boolean a = match.find();        return a;    }        // 不允许跳转或判断跳转    HttpURLConnection conn = (HttpURLConnection) u.openConnection();conn.setInstanceFollowRedirects(false); // 不允许重定向或者对重定向后的地址做二次判断       conn.connect();

自我审计的话可以去下载任务调度系统或者开源代码中存在ssrf漏洞的系统(github开源项目或者站长下载一些免费的开源项目都可以下载源码)。或者是看github上的写好的代码https://github.com/JoyChou93/java-sec-code/blob/master/src/main/java/org/joychou/controller/SSRF.java


原文始发于微信公众号(Kokoxca安全):JAVA代码审计之SSRF

版权声明:admin 发表于 2024年2月25日 下午9:01。
转载请注明:JAVA代码审计之SSRF | CTF导航

相关文章