前言
- java.net.URL是Java的JDK提供的一个有20多年历史的通用类库,但是也正由于它的历史久远存在历史包袱,在很多场景下会导致应用存在莫名其妙的Bug和漏洞。本文主要描述的是几种常见的问题。在日常做URL处理时,更建议使用java.net.URI库替代掉java.net.URL库。
java.net.URL库解析时存在Bug与浏览器(Chrome,safari)解析不一致
- Java类java.net.URL中存在一个Bug,与Chrome和Safari中实现不一样。如果用户输入为http://a.com\\@b.com时,此时java.net.URL的getHost函数得到的结果时b.com,但是当把http://a.com\\@b.com这个放到Chrom或者Safari中时,会发现返回的是a.com域,因此就出现了不一致,绕过了检测。
public class TestURI {
public static void main(String argv[]) throws MalformedURLException, URISyntaxException {
URL u = new URL("http://a.com\\@b.com/index.html");
// System.out.println(u.toExternalForm());
System.out.println(u.getHost());
URI us = new URI("http://alibaba.com@baidu.com/index.html");
System.out.println(us.getHost());
}
}
// 运行结果为b.com,但Chrome、Safari访问时会跳转到a.com ...
- 解决方案是替换为java.net.URI,用户输入http://a.com\@b.com/index.html会抛出异常报错。
java.net.URL库解析的解析错误
java.net.URL在一些特殊payload下的解析结果与chrome、safari下不符。譬如payload为http://a.com#@b.com/,chrome中会跳转到a.com,而java.net.URL则认为是b.com这样讲为URL跳转bypass提供可能性。
public class URITest {
public static void main(String argv[]) throws MalformedURLException, URISyntaxException {
URL u = new URL("http://a.com#@b.com/");
System.out.println(u.getHost());//运行结果:b.com
URI us = new URI("http://a.com#@b.com/");
System.out.println(us.getHost());//运行结果:a.com
}
}
java.net.URL库未支持//这种模式报错
public class TestURI {
public static void main(String argv[]) throws MalformedURLException, URISyntaxException {
URL u = new URL("//alibaba.com/index.html");
System.out.println(u.getHost());
}
}
// 运行报错 ...
- 解决方案:替换成java.net.URI库
java.net.URL库碰到Host中带_不报错,而java.net.URI库返回null
URL u = new URL("http://ali_baba.com/index.html");
// System.out.println(u.toExternalForm());
System.out.println(u.getHost());
URI us = new URI("http://alibaba.com.com/index.html");
System.out.println(us.getHost());
// 运行结果为ali_baba.com , null(URI会滤掉)
传入URI之后特殊处理。从规范协议上看,其实Host本身不应该带_的,全是URL这个库坑人。据说有20年历史了,坑货,辣鸡。
判断
uri.getHost() == uri.toURL().getHost()
,如果不成立时,表明Host有_等异常。
其他特殊URL解析问题
- http://a.com@n.com:80@c.com/ , java.net.URL会报错,而java.net.URI会返回null。此时chrome返回的是c.com