URL跳转漏洞, 也叫开放重定向漏洞(open redirect)。 如果处理不当会导致用户被重定向至钓鱼或恶意网站。我们通常用白名单机制来处理,比如qq登录等接口的回调页面就要求做白名单限制。通常我们会判断跳转url中的域名或者路径是否合法,但是问题往往就出现在这些判断中。
漏洞通常发生在以下几个地方:
- 用户登录、统一身份认证处,认证完后的跳转;
- 用户分享、收藏内容过后的跳转;
- 跨站点认证、授权(第三方登录)后的跳转;
- 站内点击其它网址链接时的跳转。
出现漏洞的原因大概有以下5个:
- 写代码时没有考虑过任意URL跳转漏洞,或者根本不知道/不认为这是个漏洞;
- 写代码时考虑不周,用取子串、取后缀等方法简单判断,代码逻辑可被绕过;
- 对传入参数做一些特殊的操作(如域名剪切、拼接、重组)和判断,适得其反,反而被绕过;
- 原始语言自带的解析URL、判断域名的函数库出现逻辑漏洞或者意外特性,可被绕过;
- 原始语言、服务器/容器特性、浏览器等对标准URL协议解析处理等差异性导致被绕过。
在php中, 常用如下方法进行跳转(以参数名url为例):
$redirect_url = $_GET['url'];
header("Location: " . $redirect_url);
后面假设源域名为:www.example.com,我们先设置白名单:
$arr_white_list = ['localhost', 'example.com'];
域名字符串检测
使用
stripos
检测url字符串中是否存在于白名单中的域名 - 不安全
如果使用
stripos
检测字符串是否存在于跳转url中,是不可靠的,比如下面的url:
https://www.example.com/redirect.php?url=http://www.example.com.www.evil.com/untrust.html
代码:
$redirect_url = $_GET['url'];
$is_redirect_url_valid = false; //跳转url是否验证通过
$arr_white_list = ['localhost', 'example.com'];
foreach($arr_white_list AS $white_item){
if(stripos($redirect_url, $white_item) !== false){
$is_redirect_url_valid = true;
break;
}
}
上面这种简单的判断域名是否存在url中是不安全的,不要使用。
提取并检测域名是否在白名单中
使用内置函数
parse_url
来判断url格式是否正确,并提取url的各个部分。
这里我们只考虑给定的url是包含protocol的完整的URL。对严重不合格的 URL,parse_url() 可能会返回 FALSE。
$redirect_url = $_GET['url'];
$arr = parse_url($redirect_url); //解析 URL,返回其组成部分
$host = ''; //要跳转的URL的域名
if($arr !== null && $arr !== false) {
if(array_key_exists('host', $arr)){
$host = $arr['host'];
}
}else{
echo 'Error: url式不正确';
}
$is_redirect_url_valid = false;
$arr_white_list = ['localhost', 'example.com'];
if($host !== ''){
//判断域名是否在白名单中(包含二级域名)
foreach($arr_white_list AS $white_item){
if(
($host === $white_item)
||
(
//子域名: 长度 > 主域名
strlen($host) > strlen($white_item)
&&
substr($host, strlen($host)-strlen($white_item)-1) === '.'.$white_item
)
){
$is_redirect_url_valid = true;
break;
}
}
}
var_dump($is_redirect_url_valid); //打印跳转url检查是否通过
上面的代码简单演示了后端PHP如何判断跳转url能否通过验证。
如果白名单下的页面有重定向漏洞,这里就无法处理。我们至少要确保站内没有重定向漏洞。
防护方法
- 固定跳转地址,不让用户控制变量。 这种不适合登录后返回原来的页面这种场景,但是我们可以把登录功能作为页面公共部分, 所有页面都可以直接调出登录窗口,登录成功后直接reload页面。
- 跳转目标地址采用白名单映射机制, 不在白名单内的跳转到固定地址或不做任何动作。
- 合理充分的校验跳转的目标地址,非己方地址时告知用户跳转风险。
参考:
https://landgrey.me/open-redirect-bypass/
https://www.cnblogs.com/xiaozi/p/10682199.html
版权归原作者 aben_sky 所有, 如有侵权,请联系我们删除。