什么是SSRF以及如何预防-----代码实例

https://blog.csdn.net/jimmyleeee/article/details/124733955说明了SSRF是怎么一会事,以及需要验证哪几个部分?

为了验证每一个部分,首先需要做的就是根据一个URL取出每一个部分的值,然后再根据取出来的值来进行判断。可能有的人会立刻想到将URL的字符串值转换成java.net.URL类,然后通过URL类的实例在获取每一个部分的内容,下面是根据URL缩写的代码示例以及测试代码:

package com.test.utils;

import java.net.MalformedURLException;
import java.net.URL;

public class URLUtil {
    public static String getProtocol(String strUrl) {
        try {
            URL url =new URL(strUrl);
            return url.getProtocol();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return "";

    }

    public static String getHost(String strUrl) {
        try {
            URL url =new URL(strUrl);
            return url.getHost();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return "";

    }

    public static int getPort(String strUrl) {
        try {
            URL url =new URL(strUrl);
            if (url.getPort() == -1) {
                return url.getDefaultPort();
            } else {
                return url.getPort();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return -1;

    }

    public static String getPath(String strUrl) {
        try {
            URL url =new URL(strUrl);
            return url.getPath();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        return "";

    }

    public static void testURL() {
        String url1="http://www.example.com/test/test1?query=test";
        System.out.println("url1:protocol="+getProtocol(url1)+" host="+getHost(url1)
                + " port="+getPort(url1) + " Path=" +getPath(url1));

        String url2="https://www.example.com/test/test1?query=test";
        System.out.println("url2:protocol="+getProtocol(url2)+" host="+getHost(url2)
                + " port="+getPort(url2) + " Path=" +getPath(url2));

        String url7="https://www.example.com:8443/test/test1?query=test";
        System.out.println("url7:protocol="+getProtocol(url7)+" host="+getHost(url7)
                + " port="+getPort(url7) + " Path=" +getPath(url7));

        String url3="http://www.example.com:80/test/test1?query=test";
        System.out.println("url3:protocol="+getProtocol(url3)+" host="+getHost(url3)
                + " port="+getPort(url3) + " Path=" +getPath(url3));

        String url4="http://127.0.0.1/test/test1?query=test";
        System.out.println("url4:protocol="+getProtocol(url4)+" host="+getHost(url4)
                + " port="+getPort(url4) + " Path=" +getPath(url4));

        String url5="http://127.0.0.1:80/test/test1?query=test";
        System.out.println("url5:protocol="+getProtocol(url5)+" host="+getHost(url5)
                + " port="+getPort(url5) + " Path=" +getPath(url5));

        String url6="https://127.0.0.1:8443/test/test1?query=test";
        System.out.println("url6:protocol="+getProtocol(url6)+" host="+getHost(url6)
                + " port="+getPort(url6) + " Path=" +getPath(url6));

        String url9="https://127.0.0.1:8443/test/test1?query=test";
        System.out.println("url9:protocol="+getProtocol(url9)+" host="+getHost(url9)
                + " port="+getPort(url9) + " Path=" +getPath(url9));

        String url8="ftps://127.0.0.1/test";
        System.out.println("url8:protocol="+getProtocol(url8)+" host="+getHost(url8)
                + " port="+getPort(url8) + " Path=" +getPath(url8));


    }
}

测试结果如下:

url1:protocol=http host=www.example.com port=80 Path=/test/test1
url2:protocol=https host=www.example.com port=443 Path=/test/test1
url7:protocol=https host=www.example.com port=8443 Path=/test/test1
url3:protocol=http host=www.example.com port=80 Path=/test/test1
url4:protocol=http host=127.0.0.1 port=80 Path=/test/test1
url5:protocol=http host=127.0.0.1 port=80 Path=/test/test1
url6:protocol=https host=127.0.0.1 port=8443 Path=/test/test1
url9:protocol=https host=127.0.0.1 port=8443 Path=/test/test1
java.net.MalformedURLException: unknown protocol: ftps
	at java.net.URL.<init>(URL.java:617)
	at java.net.URL.<init>(URL.java:507)
	at java.net.URL.<init>(URL.java:456)
	at com.test.utils.URLUtil.getProtocol(URLUtil.java:9)
	at com.test.utils.URLUtil.testURL(URLUtil.java:89)
	at com.test.LargestApplication.main(LargestApplication.java:79)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
java.net.MalformedURLException: unknown protocol: ftps
	at java.net.URL.<init>(URL.java:617)
	at java.net.URL.<init>(URL.java:507)
	at java.net.URL.<init>(URL.java:456)
	at com.test.utils.URLUtil.getHost(URLUtil.java:20)
	at com.test.utils.URLUtil.testURL(URLUtil.java:89)
	at com.test.LargestApplication.main(LargestApplication.java:79)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
java.net.MalformedURLException: unknown protocol: ftps
	at java.net.URL.<init>(URL.java:617)
	at java.net.URL.<init>(URL.java:507)
	at java.net.URL.<init>(URL.java:456)
	at com.test.utils.URLUtil.getPort(URLUtil.java:31)
	at com.test.utils.URLUtil.testURL(URLUtil.java:90)
	at com.test.LargestApplication.main(LargestApplication.java:79)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
java.net.MalformedURLException: unknown protocol: ftps
	at java.net.URL.<init>(URL.java:617)
	at java.net.URL.<init>(URL.java:507)
	at java.net.URL.<init>(URL.java:456)
	at com.test.utils.URLUtil.getPath(URLUtil.java:46)
	at com.test.utils.URLUtil.testURL(URLUtil.java:90)
	at com.test.LargestApplication.main(LargestApplication.java:79)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)

发现试用ftps协议时,出现了异常。根据代码调试发现URL只支持HTTP、HTTPS、file三种协议,所以其他协议都会报java.net.MalformedURLException的异常。

于是,又转换了一下想法,使用java.net.URI类又实现了一个,代码示例如下:

package com.test.utils;

import java.net.URI;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

public class URIUtil {
    private String strUrl = null;
    private URI uri = null;
    private Map<String, String>  defaultPorts = null;

    public  URIUtil(String url) {
        strUrl = url;
        uri = URI.create(strUrl);

        defaultPorts =Protocols.getMap();
    }

    public String getProtocol() {
        return uri.getScheme();
    }

    public String getHost() {
        return uri.getHost();
    }

    public int getPort() {
        return uri.getPort() == -1? getDefaultPort() : uri.getPort();
    }

    public String getPath() {
        return uri.getPath();
    }

    private int getDefaultPort() {
        String protocol = getProtocol();
        if (protocol != null) {
            String defaultPort = defaultPorts.get(protocol.toUpperCase());
            if (defaultPort != null ){
                return Integer.valueOf(defaultPort);
            }
        }
        return -1;
    }

    public enum Protocols{
        HTTP("HTTP", "80"),
        HTTPS("HTTPS", "443");

        private String name;
        private String port;

        private Protocols(String name, String port) {
            this.name = name;
            this.port = port;
        }
        public String getName() {
            return name;
        }
        public String getPort() {
            return port;
        }

        public  static Map<String, String> getMap() {
            Map<String, String> map = Arrays.asList(Protocols.values()).stream().collect(Collectors.toMap
                    (obj->obj.getName(),Protocols::getPort));
            return map;
        }
    }

    public static void testURI() {
        String uri1="http://www.example.com/test/test1?query=test";
        URIUtil uriUtil1 = new URIUtil(uri1);
        System.out.println("uri1:protocol="+uriUtil1.getProtocol()+" host="+uriUtil1.getHost()
                + " port="+uriUtil1.getPort() + " Path=" +uriUtil1.getPath());

        String uri2="https://www.example.com/test/test1?query=test";
        URIUtil uriUtil2 = new URIUtil(uri2);
        System.out.println("uri2:protocol="+uriUtil2.getProtocol()+" host="+uriUtil2.getHost()
                + " port="+uriUtil2.getPort() + " Path=" +uriUtil2.getPath());

        String uri7="https://www.example.com:8443/test/test1?query=test";
        URIUtil uriUtil7 = new URIUtil(uri7);
        System.out.println("uri7:protocol="+uriUtil7.getProtocol()+" host="+uriUtil7.getHost()
                + " port="+uriUtil7.getPort() + " Path=" +uriUtil7.getPath());

        String uri3="http://www.example.com:80/test/test1?query=test";
        URIUtil uriUtil3 = new URIUtil(uri3);
        System.out.println("uri3:protocol="+uriUtil3.getProtocol()+" host="+uriUtil3.getHost()
                + " port="+uriUtil3.getPort() + " Path=" +uriUtil3.getPath());

        String uri4="http://127.0.0.1/test/test1?query=test";
        URIUtil uriUtil4 = new URIUtil(uri4);
        System.out.println("uri4:protocol="+uriUtil4.getProtocol()+" host="+uriUtil4.getHost()
                + " port="+uriUtil4.getPort() + " Path=" +uriUtil4.getPath());

        String uri5="http://127.0.0.1:80/test/test1?query=test";
        URIUtil uriUtil5 = new URIUtil(uri5);
        System.out.println("uri5:protocol="+uriUtil5.getProtocol()+" host="+uriUtil5.getHost()
                + " port="+uriUtil5.getPort() + " Path=" +uriUtil5.getPath());

        String uri6="https://127.0.0.1:8443/test/test1?query=test";
        URIUtil uriUtil6 = new URIUtil(uri6);
        System.out.println("uri6:protocol="+uriUtil6.getProtocol()+" host="+uriUtil6.getHost()
                + " port="+uriUtil6.getPort() + " Path=" +uriUtil6.getPath());

        String uri9="https://127.0.0.1:8443/test/test1?query=test";
        URIUtil uriUtil9 = new URIUtil(uri9);
        System.out.println("uri9:protocol="+uriUtil9.getProtocol()+" host="+uriUtil9.getHost()
                + " port="+uriUtil9.getPort() + " Path=" +uriUtil9.getPath());

        String uri8="ftps://127.0.0.1/test";
        URIUtil uriUtil8 = new URIUtil(uri8);
        System.out.println("uri8:protocol="+uriUtil8.getProtocol()+" host="+uriUtil8.getHost()
                + " port="+uriUtil8.getPort() + " Path=" +uriUtil8.getPath());

        String uri10="ftps://127.0.0.1:29/test";
        URIUtil uriUtil10 = new URIUtil(uri10);
        System.out.println("uri10:protocol="+uriUtil10.getProtocol()+" host="+uriUtil10.getHost()
                + " port="+uriUtil10.getPort() + " Path=" +uriUtil10.getPath());

        String uri11="gropher://127.0.0.1:29/test";
        URIUtil uriUtil11 = new URIUtil(uri11);
        System.out.println("uri11:protocol="+uriUtil11.getProtocol()+" host="+uriUtil11.getHost()
                + " port="+uriUtil11.getPort() + " Path=" +uriUtil11.getPath());

        String uri12="test://127.0.0.1:29/test";
        URIUtil uriUtil12 = new URIUtil(uri12);
        System.out.println("uri12:protocol="+uriUtil12.getProtocol()+" host="+uriUtil12.getHost()
                + " port="+uriUtil12.getPort() + " Path=" +uriUtil12.getPath());

        String uri13="/test/relativepath";
        URIUtil uriUtil13 = new URIUtil(uri13);
        System.out.println("uri13:protocol="+uriUtil13.getProtocol()+" host="+uriUtil13.getHost()
                + " port="+uriUtil13.getPort() + " Path=" +uriUtil13.getPath());

        String uri14="https://api.example.com/test/test1?query=test";
        URIUtil uriUtil14 = new URIUtil(uri14);
        System.out.println("uri14:protocol="+uriUtil14.getProtocol()+" host="+uriUtil14.getHost()
                + " port="+uriUtil14.getPort() + " Path=" +uriUtil14.getPath());

    }
}

测试结果如下:

uri1:protocol=http host=www.example.com port=80 Path=/test/test1
uri2:protocol=https host=www.example.com port=443 Path=/test/test1
uri7:protocol=https host=www.example.com port=8443 Path=/test/test1
uri3:protocol=http host=www.example.com port=80 Path=/test/test1
uri4:protocol=http host=127.0.0.1 port=80 Path=/test/test1
uri5:protocol=http host=127.0.0.1 port=80 Path=/test/test1
uri6:protocol=https host=127.0.0.1 port=8443 Path=/test/test1
uri9:protocol=https host=127.0.0.1 port=8443 Path=/test/test1
uri8:protocol=ftps host=127.0.0.1 port=-1 Path=/test
uri10:protocol=ftps host=127.0.0.1 port=29 Path=/test
uri11:protocol=gropher host=127.0.0.1 port=29 Path=/test
uri12:protocol=test host=127.0.0.1 port=29 Path=/test
uri13:protocol=null host=null port=-1 Path=/test/relativepath
uri14:protocol=https host=api.example.com port=443 Path=/test/test1

效果和预期的一样。 

不过,在代码里对于没有提供端口的情况进行了一些特殊处理,因为使用的URL中如果没有端口的话,默认的都会返回-1,代码中通过定义了某些协议的默认端口,如果没有端口的话,就使用默认的端口代替。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值