内容简介:服务端未对传入的跳转url变量进行检查和控制,导致可恶意构造任意一个恶意地址,诱导用户跳转到恶意网站。由于是从可信的站点跳转出去的,用户会比较信任,所以跳转漏洞一般用于钓鱼攻击,通过转到恶意网站欺骗用户输入用户名和密码盗取用户信息,或欺骗用户进行金钱交易。修复该漏洞最有效的方法之一就是校验传入的跳转url参数值,判断是否为预期域名。在java中可使用下列方法:
*本文作者:ChangeS,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。
任意URL跳转漏洞
服务端未对传入的跳转url变量进行检查和控制,导致可恶意构造任意一个恶意地址,诱导用户跳转到恶意网站。由于是从可信的站点跳转出去的,用户会比较信任,所以跳转漏洞一般用于钓鱼攻击,通过转到恶意网站欺骗用户输入用户名和密码盗取用户信息,或欺骗用户进行金钱交易。
修复该漏洞最有效的方法之一就是校验传入的跳转url参数值,判断是否为预期域名。在 java 中可使用下列方法:
String url = request.getParameter("returnUrl"); String host = ""; try { host = new URL(url).getHost(); } catch (MalformedURLException e) { e.printStackTrace(); } if host.endsWith(".bbb.com"){ //跳转 }else{ //不跳转,报错 }
上述代码中主要校验了客户端传来的returnUrl参数值,使用java.net.URL包中的getHost()方法获取了将要跳转url的host,判断host是否为目标域,上述代码中限制了必须跳转到xxx.bbb.com的域名,从而排除了跳转到不可信域名的可能。
但是,getHost()方法真的靠谱吗??
getHost()方法的坑之一
可以被反斜线绕过,即 returnUrl=[http://www.aaa.com](http://www.aaa.com)\[www.bbb.com](http://www.bbb.com)
会被代码认为是将要跳转到 bbb.com
,而实际在浏览器中反斜线被纠正为正斜线,跳转到 [www.aaa.com/www.bbb.com](http://www.aaa.com/www.bbb.com)
,最终还是跳到 [www.aaa.com](http://www.aaa.com)
的服务器。
使用下列代码进行测试:
public class Main { public static void main(String[] args) { String url = "https://www.aaa.com\\www.bbb.com?x=123"; String host = ""; try { host = new URL(url).getHost(); } catch (MalformedURLException e) { e.printStackTrace(); } System.out.println("host---"+host); System.out.println("url---"+url); } }
url参数的域名getHost()之后是 [www.aaa.com](http://www.aaa.com)
还是 [www.bbb.com](http://www.bbb.com)
呢?打印结果如下:
该结果会被endsWith(“.bbb.com”)方法判断为真,从而成功执行跳转,但实际在浏览器中跳转到了 [www.aaa.com](http://www.aaa.com)
网站。
getHost()方法的坑之二
getHost()方法的结果在不同JDK版本中对井号#的处理结果不同,通常井号被用作页面锚点,对于 [https://www.aaa.com#www.bbb.com?x=123](https://www.aaa.com#www.bbb.com?x=123)
这个url,较高版本的JDK中,取出结果为 [www.aaa.com](http://www.aaa.com)
,低版本中为 [www.aaa.com#www.bbb.com](http://www.aaa.com#www.bbb.com)
,从而低版本又可绕过endsWith(“.bbb.com”)方法,成功跳转。
这里所说的高版本指的是 java version 1.8.0_181
或者 java version 1.7.0_161
中的181和161,与JDK7还是8无关。可能java在某个时间集中修复了JDK6/7/8中的URL库。
测试过程中发现 1.6.0_45
, 1.7.0_71
, 1.8.0_25
均可被#绕过,即不同的JDK中低版本均存在问题。
通过对比 rt.jar---java---net--URLStreamHandler.java
代码(低版本为左边,高版本为右边)找到问题所在如下图所示,代码中的start为url中冒号位置,limit为url中井号位置:
从代码中可以发现,低版本中未考虑到一个完整url中斜线/或者问号?之前会出现井号#的情况,如果url中有斜线/或者问号?,取host就以斜线或者问号为终止,即使中间包含井号也不处理;而高版本中进行了井号位置的判断,排除了使用井号绕过的可能。但是线上生成环境的JDK版本又不是敢随便乱升级的,只能从代码里提前预防。
下图为使用不同版本JDK测试的结果:
同一段代码在不同JDK版本中打印出的host值不同,在低版本中包含了井号及其后边的部分。
综合上述两个坑,若想使用getHost()来修复任意URL跳转漏洞,需要考虑到反斜线和井号绕过,可使用如下代码:
String url = request.getParameter("returnUrl"); String host = ""; try { url = url.replaceAll("[\\\\#],"/"); //替换掉反斜线和井号 host = new URL(url).getHost(); } catch (MalformedURLException e) { e.printStackTrace(); } if host.endsWith(".bbb.com"){ //跳转 }else{ //不跳转,报错 }
附送一个真实例子
该站可使用井号配合斜线或者问号来绕过域名检测,即将target设置为URL编码后的 [https://www.baidu.com#www.bbb.com?x=123](https://www.baidu.com#www.bbb.com?x=123)
,该站即可302跳转到百度。
*本文作者:ChangeS,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。
以上所述就是小编给大家介绍的《任意URL跳转漏洞修复与JDK中getHost()方法之间的坑》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- struts2架构网站漏洞修复详情与利用漏洞修复方案
- 如何做好漏洞管理的漏洞修复工作
- phpcms网站漏洞修复之远程代码写入缓存漏洞利用
- 系统漏洞及修复汇总
- 中间件漏洞及修复汇总
- WEB应用漏洞及修复汇总
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Pragmatic Thinking and Learning
Andy Hunt / The Pragmatic Bookshelf / 2008 / USD 34.95
In this title: together we'll journey together through bits of cognitive and neuroscience, learning and behavioral theory; you'll discover some surprising aspects of how our brains work; and, see how ......一起来看看 《Pragmatic Thinking and Learning》 这本书的介绍吧!