前言

  • java.net.URL是Java的JDK提供的一个有20多年历史的通用类库,但是也正由于它的历史久远存在历史包袱,在很多场景下会导致应用存在莫名其妙的Bug和漏洞。本文主要描述的是几种常见的问题。在日常做URL处理时,更建议使用java.net.URI库替代掉java.net.URL库。

java.net.URL库解析时存在Bug与浏览器(Chrome,safari)解析不一致

  1. public class TestURI {
  2. public static void main(String argv[]) throws MalformedURLException, URISyntaxException {
  3. URL u = new URL("http://a.com\\@b.com/index.html");
  4. // System.out.println(u.toExternalForm());
  5. System.out.println(u.getHost());
  6. URI us = new URI("http://alibaba.com@baidu.com/index.html");
  7. System.out.println(us.getHost());
  8. }
  9. }
  10. // 运行结果为b.com,但Chrome、Safari访问时会跳转到a.com ...

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提供可能性。

  1. public class URITest {
  2. public static void main(String argv[]) throws MalformedURLException, URISyntaxException {
  3. URL u = new URL("http://a.com#@b.com/");
  4. System.out.println(u.getHost());//运行结果:b.com
  5. URI us = new URI("http://a.com#@b.com/");
  6. System.out.println(us.getHost());//运行结果:a.com
  7. }
  8. }

java.net.URL库未支持//这种模式报错

  1. public class TestURI {
  2. public static void main(String argv[]) throws MalformedURLException, URISyntaxException {
  3. URL u = new URL("//alibaba.com/index.html");
  4. System.out.println(u.getHost());
  5. }
  6. }
  7. // 运行报错 ...
  • 解决方案:替换成java.net.URI库

java.net.URL库碰到Host中带_不报错,而java.net.URI库返回null

  1. URL u = new URL("http://ali_baba.com/index.html");
  2. // System.out.println(u.toExternalForm());
  3. System.out.println(u.getHost());
  4. URI us = new URI("http://alibaba.com.com/index.html");
  5. System.out.println(us.getHost());
  6. // 运行结果为ali_baba.com , null(URI会滤掉)
  • 传入URI之后特殊处理。从规范协议上看,其实Host本身不应该带_的,全是URL这个库坑人。据说有20年历史了,坑货,辣鸡。

  • 判断uri.getHost() == uri.toURL().getHost() ,如果不成立时,表明Host有_等异常。

其他特殊URL解析问题

参考资料