$_server['php_self'] 漏洞,PHP的$_SERVER['PHP_SELF']造成的XSS漏洞攻击及其解决方案

本文介绍了PHP全局变量$_SERVER['PHP_SELF']的用途及其可能带来的安全风险。通过示例展示了如何利用$_SERVER['PHP_SELF']进行跨站脚本(XSS)攻击,并提出了两种安全防护措施:使用htmlentities转义和替换为$_SERVER['REQUEST_URI']。强调了在处理用户输入数据时的安全原则,提醒开发者注意网址等数据的安全验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

$_SERVER[‘PHP_SELF‘]简介

$_SERVER[‘PHP_SELF‘] 表示当前 PHP文件相对于网站根目录的位置地址,与 document root 相关。

假设我们有如下网址,$_SERVER[‘PHP_SELF‘]得到的结果分别为:

http://www.php-note.com/php/    :   /php/test.php

http://www.php-note.com/php/test.php    :    /php/test.php

http://www.php-note.com/php/test.php?test=foo    :    /php/test.php

http://www.php-note.com/php/test.php/test/foo    :    /php/test.php/test/foo

因此,可以使用 $_SERVER[‘PHP_SELF‘] 很方便的获取当前页面的地址:

$url = "http://". $_SERVER[‘HTTP_HOST‘] . $_SERVER[‘PHP_SELF‘];

上面是简单获取 http 协议的当前页面 URL ,只是要注意该地址是不包含 URL 中请求的参数(?及后面的字串)的。如果希望得到包含请求参数的完整 URL 地址,请使用 $_SERVER[‘REQUEST_URI‘] 。

PHP $_SERVER[‘PHP_SELF‘] 安全性

由于利用 $_SERVER[‘PHP_SELF‘] 可以很方便的获取当前页面地址,因此一些程序员在提交表单数据到当前页面进行处理时,往往喜欢使用如下这种方式:

假设该页面地址为:

http://www.php-note.com/php/test.php

访问该页面,得到的表单 html 代码如下:

这段代码是正确的,但是当访问地址变成:

http://www.php-note.com/php/test.php/test/foo /a=1

页面正常执行了,表单 html 代码变成:

显然,这已经超出了我们的期望,Web服务器居然没有产生诸如404之类的错误,页面正常执行了,并且在生成的html代码中居然有用户可以输入的部分,恐怖的地方就在这里。别小看那个“a=1”,如果把它换成一段js代码,就显得更危险了,比如这么调用:

http://…/test.php/%22%3E%3Cscript%3Ealert(’xss’)%3C/script%3E%3Cfoo

是不是看到了js的alert函数执行的效果?检查一下生成的html源代码找找原因吧。

通过这种嵌入js代码的方式,攻击者能夠获得512~4k的代码空间,甚至还可以连接外部网站的js代码或者通过image调用来伪装js代码的方式,那样js代码的长度就不受限制了,然后通过js,他们可以轻松的获取用户的cookie,或者更改当前页面的任何内容,比如更改表单提交的目的地,更改显示的内容(比如给一个链接地址增加一个οnclick=…的属性,这样用户点击的时候就会执行攻击者指定的代码,甚至连接到并非此链接地址本身的网站),甚至作出一个ajax效果来也不一定,总之,不要忽视js的威力。

那么,再来看看这个漏洞产生的原理,首先test.php/….这种调用是web服务器允许的,很多cms系统,比如我以前用过的plog,好像也是采用这种方式,在服务器不支持rewrite的情况下实现诸如http://… /index.php/archive/999这样的固定网址的(我以前还以为是对404错误页下的手),所以带“/”的地址无法从web服务器上禁止。然后再看看php中对$_SERVER[‘PHP_SELF‘]的识别,他就是一个包含当前网址值的全局变量,天知道用户会输入什么样的网址,在上面的例子中是恶意的,可是在wikipedia这样的网站上,却又是可以正常使用这种方式的地址的。所以,最终的结论要落在开发人员身上了,没有很好的处理与用户交互的数据。

从安全角度来讲,在开发应用尤其是web应用的时候,所有用户提交的数据都是不安全的,这是基本原则,所以我们才不厌其烦的又是客户端验证又是服务端验证。从上面说的这个安全漏洞来讲,不安全的内容中又要增加“网址”一条了。要解决$_SERVER[‘PHP_SELF‘]的安全隐患,主要有以下2种方式:

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将会变成字符“

另外还有两点需要指出,第一是这种写法虽然没有直接用到$_SERVER[‘PHP_SELF‘],但实际效果却是一样的,只是发生的时间错后到了用户提交之后的下一个页面,所以,form的action还是不要留空的好。第二点,除了PHP_SELF之外,其他的$_SERVER变量也许也会有类似的漏洞,比如SCRIPT_URI、 SCRIPT_URL、 QUERY_STRING、PATH_INFO、PATH_TRANSLATED等等,在使用他们之前一定要先作htmlentities之类的。

延伸阅读:

原文:http://www.cnblogs.com/52php/p/5670068.html

### PHP `$_SERVER` 超全局变量使用说明 #### 定义与功能 `$_SERVER` 是 PHP 中的一个超全局变量,它包含了服务器环境的信息以及执行脚本时的运行状态。这些信息可能包括路径、头信息(header)、脚本的位置以及其他有用的数据[^1]。 #### 示例代码 以下是一个简单的示例,展示如何使用 `$_SERVER` 获取当前页面所在的主机名: ```php <?php echo $_SERVER['SERVER_NAME']; ?> ``` 此代码片段会输出服务器名称,例如 `"example.com"` 或本地开发环境下的 `"localhost"`[^2]。 #### 查询字符串解析 除了基本的服务器信息,`$_SERVER` 还可以用来解析 URL 的查询字符串部分。下面的例子展示了如何提取并显示查询参数中的 ID 和 Name: ```php <?php // 假设查询字符串是 "id=123&name=John" $id = isset($_GET['id']) ? $_GET['id'] : null; $name = isset($_GET['name']) ? $_GET['name'] : null; echo "ID: " . htmlspecialchars($id) . "<br>"; echo "Name: " . htmlspecialchars($name) . "<br>"; ?> ``` 需要注意的是,在实际应用中应始终验证和清理输入数据以防止安全漏洞,如 SQL 注入或 XSS 攻击[^4]。 #### 可用键值列表 以下是常见的 `$_SERVER` 键及其含义的一些例子: - `'HTTP_HOST'`: 当前请求的 Host 头部字段。 - `'SCRIPT_FILENAME'`: 当前所执行脚本的绝对路径。 - `'REMOTE_ADDR'`: 访问者的 IP 地址。 - `'REQUEST_METHOD'`: 请求方法 (通常是 GET, HEAD, POST, PUT)。 - `'PHP_SELF'`: 正在执行脚本的文件名相对于 Web 根目录的路径。 #### 应用场景 `$_SERVER` 主要用于获取客户端请求和服务器配置方面的细节。比如检测用户的浏览器类型 (`'HTTP_USER_AGENT'`) 或者记录日志以便后续分析访问模式等操作[^5]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值