PHP编码安全之四: URL跳转安全(漏洞)-程序员宅基地

技术标签: python  java  php  http  javascript  

URL跳转漏洞, 也叫开放重定向漏洞(open redirect)。 如果处理不当会导致用户被重定向至钓鱼或恶意网站。我们通常用白名单机制来处理,比如qq登录等接口的回调页面就要求做白名单限制。通常我们会判断跳转url中的域名或者路径是否合法,但是问题往往就出现在这些判断中。

漏洞通常发生在以下几个地方:

  1. 用户登录、统一身份认证处,认证完后的跳转;
  2. 用户分享、收藏内容过后的跳转;
  3. 跨站点认证、授权(第三方登录)后的跳转;
  4. 站内点击其它网址链接时的跳转。

出现漏洞的原因大概有以下5个:

  1. 写代码时没有考虑过任意URL跳转漏洞,或者根本不知道/不认为这是个漏洞;
  2. 写代码时考虑不周,用取子串、取后缀等方法简单判断,代码逻辑可被绕过;
  3. 对传入参数做一些特殊的操作(如域名剪切、拼接、重组)和判断,适得其反,反而被绕过;
  4. 原始语言自带的解析URL、判断域名的函数库出现逻辑漏洞或者意外特性,可被绕过;
  5. 原始语言、服务器/容器特性、浏览器等对标准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能否通过验证。

如果白名单下的页面有重定向漏洞,这里就无法处理。我们至少要确保站内没有重定向漏洞。

防护方法

  1. 固定跳转地址,不让用户控制变量。 这种不适合登录后返回原来的页面这种场景,但是我们可以把登录功能作为页面公共部分, 所有页面都可以直接调出登录窗口,登录成功后直接reload页面。

  2. 跳转目标地址采用白名单映射机制, 不在白名单内的跳转到固定地址或不做任何动作。

  3. 合理充分的校验跳转的目标地址,非己方地址时告知用户跳转风险。

参考:

https://landgrey.me/open-redirect-bypass/

https://www.cnblogs.com/xiaozi/p/10682199.html

http://www.apgy.club/temp/url.html

https://www.anquanke.com/post/id/94377

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/aben_sky/article/details/121513950

智能推荐

关于selenium实现滑块验证-程序员宅基地

文章浏览阅读202次。python2.7+selenium2实现淘宝滑块自动认证参考链接:https://blog.csdn.net/ldg513783697/article/details/51583641selenium、python模拟登陆淘宝参考链接:https://blog.csdn.net/mighty13/article/details/78035088..._selesnuim滑块验证

第六篇:CamX添加自定义vendortag_camx 添加vendortag-程序员宅基地

文章浏览阅读29次。注:本文章所有权归:小驰成长圈,禁止转载宣传!_camx 添加vendortag

基于Spark的机器学习实践 (二) - 初识MLlib_mlib基于spark core-程序员宅基地

文章浏览阅读2k次。1 MLlib概述1.1 MLlib 介绍◆ 是基于Spark core的机器学习库,具有Spark的优点◆ 底层计算经过优化,比常规编码效率往往要高◆ 实现了多种机器学习算法,可以进行模型训练及预测1.2 Spark MLlib实现的算法◆ 逻辑回归 朴素贝叶斯 线性回归 SVM 决策树 LDA 矩阵分解1.3 Spark MLlib官方介绍1.3.1 搜索官方文档1.3..._mlib基于spark core

《剑指offer》——二叉树的下一个结点-程序员宅基地

文章浏览阅读401次。题目: 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。思路: 分析二叉树的下一个节点,一共有以下情况: 1.二叉树为空,则返回空; 2.节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点; 3.节点不是根节点。如果该节点是其父节点的左孩子,则返

数字反转的列表实现方法(python)_python在函数内,将数字num转换为其相反顺序的数字列表。-程序员宅基地

文章浏览阅读1.3k次。做题心得_python在函数内,将数字num转换为其相反顺序的数字列表。

Java 之 FileReader FileInputStream InputStreamReader BufferedReader 作用与区-程序员宅基地

文章浏览阅读57次。ava.io下面有两个抽象类:InputStream和ReaderInputStream是表示字节输入流的所有类的超类Reader是用于读取字符流的抽象类InputStream提供的是字节流的读取,而非文本读取,这是和Reader类的根本区别。即用Reader读取出来的是char数组或者String,使用InputStream读取出来的是byte数组。弄清了两个超类的根本区别,再来看他们底下..._java bufferreader inputstream

随便推点

pycharm远程调试方式-程序员宅基地

文章浏览阅读178次。首先下载安装xming注意事项host里可以写多个允许的ip本地ip不要用百度查是错的,右键网络属性看ipv4简单测试方式 xclock远程调试先下载pycharm启动方式/bin ./pycharm.sh设置环境设定为anaconda3/envs/xx/bin/py3.5...

linux命令行交叉编译qt,Linux下实现Qt 4.6.3移植 Ubuntu10.10篇-程序员宅基地

文章浏览阅读245次。Linux下实现Qt 4.6.3移植 (10.10篇) 是本篇介绍的内容,不多说先来看内容。1、移植准备1.1编译所需环境和资源1、Qt源码包:Qt4.6源码包 :qt-everywhere-opensource-src-4.6.3.tar.gz2、交叉编译工具:arm-linux-gcc-4.4.3-20100728.tar3、触摸屏校验工具 :tslib-1.4.tar.gz4、PC运行的OS..._qt4.6.3 交叉编译

python不同曲线设置标签_python 绘制拟合曲线并加指定点标识的实现 Python怎么实现非线性的拟合...-程序员宅基地

文章浏览阅读642次。Python 怎么用曲线拟合数据我有两组数据: y = [41.417, 49.077, 26.683, 42.137, 37.31, 10.022, Python中利用guiqwt进行曲线数据拟合。怎么用Python将图像边界用最小二乘法拟合成曲线怎么用matplotlib在同一个图上画离散点及其拟合直线也许是怕再伤对方一次,所以分手时,一个没有挽留,另一个也没回头。python如何分享一条拟合..._不同曲线标签 python

转义JavaScript特殊字符-程序员宅基地

文章浏览阅读80次。JavaScriptUtils.javaScriptEscape("%admin' or '1=1") //转义JavaScript特殊字符 转载于:https://www.cnblogs.com/xianhenyuan/..._"javascriptutils.javascriptescape(\"%admin' or '1=1\")"

java 更新list内的元素_list更新元素-程序员宅基地

文章浏览阅读1.5w次。/*** 更新list内的元素。* @param objlist* @param oldObj 旧对象* @param newObj 要更新的对象* @return*/public List updateElement(List objlist,Object oldObj,Object newObj){int position=objlist.indexOf(old_list更新元素

wamp2.1配置虚拟主机-程序员宅基地

文章浏览阅读71次。修改配置文件httpd.conf,并去掉#Include conf/extra/httpd-vhosts.conf前面的#修改apache/conf/extra/httpd-vhosts.conf<VirtualHost*:80>DocumentRoot"D:/wamp/www"ServerNamelocalhost<D..._wamp 2.2 虚拟映射