php的服务器变量$SERVER以及防止$_SERVER['PHP_SELF']造成的XSS漏洞攻击及其解决方案

一、背景

      突然想起来之前面试的一些面试题,让我写出几个服务器变量$SERVER代表的意思。。实话实说,这些东西已经忘记很久了,都是用的时候直接上网查,今天再复习复习吧。

二、$SERVER

      $_SERVER 是一个包含诸如头信息(header)、路径(path)和脚本位置(script locations)的数组。它是 PHP 中一个超级全局变量,我们可以在 PHP 程序的任何地方直接访问它。

1、$SERVER包含的参数

#测试网址:     http://localhost/blog/testurl.php?id=5

//获取域名或主机地址 
echo $_SERVER['HTTP_HOST']."<br>"; #localhost

//获取网页地址 
echo $_SERVER['PHP_SELF']."<br>"; #/blog/testurl.php

//获取网址参数 
echo $_SERVER["QUERY_STRING"]."<br>"; #id=5

//获取用户代理 
echo $_SERVER['HTTP_REFERER']."<br>"; 

//获取完整的url
echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
echo 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'];
#http://localhost/blog/testurl.php?id=5

//包含端口号的完整url
echo 'http://'.$_SERVER['SERVER_NAME'].':'.$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"]; 
#http://localhost:80/blog/testurl.php?id=5

//只取路径
$url='http://'.$_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"]; 
echo dirname($url);
#http://localhost/blog
//其他的
$_SERVER['REQUEST_URI']:访问此页面所需的 URI 。 
$_SERVER['SCRIPT_FILENAME']:当前运行 PHP 程序的绝对路径及文件名。 
$_SERVER['argv']:传递给当前 PHP 程序的参数。

以上是一些常用的$SERVER数组。

2、关于 $SERVER[HTTP_HOST]$SERVER[SERVER_NAME ]的区别

这部分具体参考链接:
php $_SERVER中的SERVER_NAME 和HTTP_HOST的区别

当满足以下三个条件时,两者会输出相同信息。
1. 服务器为80端口
2. apache的conf中ServerName设置正确
3. HTTP/1.1协议规范

建议使用$SERVER[‘HTTP_POST’]比较稳定一些

3、关于$_SERVER["REQUEST_URI"]

      之前在网上经常会遇到使用$_SERVER[“REQUEST_URI”] 取不到值的情况,后面才知道,这个变量只有 apache 才支持,如果你使用的是nginx或者其他服务器,需要用其他方式获得

<?php

// 说明:获取 _SERVER['REQUEST_URI'] 值的通用解决方案
// 来源:drupal-5.1 bootstrap.inc
// 整理:CodeBit.cn ( http://www.CodeBit.cn )

function request_uri()
{
    if (isset($_SERVER['REQUEST_URI']))
    {
        $uri = $_SERVER['REQUEST_URI'];
    }
    else
    {
        if (isset($_SERVER['argv']))
        {
            $uri = $_SERVER['PHP_SELF'] .'?'.$_SERVER['argv'][0];
        }
        else
        {
            $uri = $_SERVER['PHP_SELF'] .'?'.$_SERVER['QUERY_STRING'];
        }
    }
    return $uri;
}

?>

三、关于PHP的$_SERVER[‘PHP_SELF’]造成的XSS漏洞攻击及其解决方案

参考链接:
PHP的$_SERVER[‘PHP_SELF’]造成的XSS漏洞攻击及其解决方案

这部分,笔者建议:

1、htmlentities

      用htmlentities($_SERVER['PHP_SELF'])来替代简单的$_SERVER[‘PHP_SELF’],这样即使网址中包含恶意代码,也会被“转换”为用于显示的html代码,而不是被直接嵌入html代码中执行,简单一点说,就是“<”会变成“<”,变成无害的了。

2、REQUEST_URI

      用$_SERVER["REQUEST_URI"]来替代$_SERVER[‘PHP_SELF’],在phpinfo()中可以看到这两个变量的区别:

$_SERVER[”REQUEST_URI”]    :   /fwolf/temp/test.php/%22%3E%3Cscript%3Ealert(’xss’)%3C/script%3E%3Cfoo
$_SERVER[”PHP_SELF”]     :    /fwolf/temp/test.php/”> 

$_SERVER["REQUEST_URI"]会原封不动的反映网址本身,网址中如果有%3C,那么你得到的也将会是%3C,而$ _SERVER['PHP_SELF']会对网址进行一次urldecode操作,网址中的%3C将会变成字符“<”,所以就产生了漏洞。

      需要注意的是,在很多情况下,浏览器会对用户输入要提交给web服务器的内容进行encode,然后服务器端程序会自动进行decode,得到相应的原指,在我们进行post或者get操作的时候都是这样。

end

===============================================================
20180626补充:

php的$server['HTTP_ORIGIN']  
这个参数在出现跨域请求的情况下,会返回请求的域名

我们可以在限制跨域请求的时候,使用该方法,获取访问的域名,如果该域名在我们的允许名单里,则生成一个新的header头

代码如下:

$allow_origin = array(  
            'http://pzhiliao.local',
            'http://miaozhiliao.com',
            'http://lux.xzhiliao.com/',
            'http://svzhiliao.com/',
            'http://www.xl.com/',
            'http://appb.xzl.com:8080',

            'http://appeb.xl.com',
            'http://xu.apweb.xl.com',

        );
        //判断是否存在跨域,获取请求的域名
        $origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';
        //如果得到的域名在我们的array之内的话,则加个header头,解决跨域问题
        if(in_array($origin, $allow_origin)){  
            header("Access-Control-Allow-Origin:".$origin);
        }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁柱同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值