草庐IT

PHP编码安全之四: URL跳转安全(漏洞)

aben_sky 2023-08-01 原文

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

有关PHP编码安全之四: URL跳转安全(漏洞)的更多相关文章

  1. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  2. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  3. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  4. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  5. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  6. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  7. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

  8. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  9. ruby - Rack:如何将 URL 存储为变量? - 2

    我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.

  10. Tomcat AJP 文件包含漏洞(CVE-2020-1938) - 2

    目录1.漏洞简介2、AJP13协议介绍Tomcat主要有两大功能:3.Tomcat远程文件包含漏洞分析4.漏洞复现 5、漏洞分析6.RCE实现的原理1.漏洞简介2020年2月20日,公开CNVD的漏洞公告中发现ApacheTomcat文件包含漏洞(CVE-2020-1938)。ApacheTomcat是Apache开源组织开发的用于处理HTTP服务的项目。ApacheTomcat服务器中被发现存在文件包含漏洞,攻击者可利用该漏洞读取或包含Tomcat上所有webapp目录下的任意文件。该漏洞是一个单独的文件包含漏洞,依赖于Tomcat的AJP(定向包协议)。AJP自身存在一定缺陷,导致存在可控

随机推荐