REQUEST_URI 返回的是包括后面数据串的地址,如 index.php?str=1234 PHP_SELF 是 index.php
--------------------------------------------------------------------------------
$_SERVER[’PHP_SELF’]在开发的时候常会用到,通常用来引用当前网页地址,而且它是系统自动生成的全局变量,也会有什么问题么?让咱们先看看下面的代码吧:
<form action=”<?php echo $_SERVER[’PHP_SELF’]; ?>”> <input type=”submit” name=”submit” value=”submit” /> </form>
这段代码很是简单,咱们想用$_SERVER[’PHP_SELF’]来让网页提交时提交到它本身,假设代码文件名为test.php,在执行的时候就必定会获得咱们指望的地址么?首先试试地址http://…/test.php,结果固然是没有问题的啦,别着急,你再访问一下http://…/test.php/a=1,将会获得以下客户端代码:
<form action=”/fwolf/temp/test.php/a=1″> <input type=”submit” name=”submit” value=”submit” /> </form>
显然,这已经超出了咱们的指望,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,或者更改当前页面的任何内容,好比更改表单提交的目的地,更改显示的内容(好比给一个连接地址增长一个onclick=…的属性,这样用户点击的时候就会执行攻击者指定的代码,甚至链接到并不是此连接地址自己的网站),甚至做出一个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种方式:
一、htmlentities
用htmlentities($_SERVER[’PHP_SELF’])来替代简单的$_SERVER[’PHP_SELF’],这样即便网址中包含恶意代码,也会被“转换”为用于显示的html代码,而不是被直接嵌入html代码中执行,简单一点说,就是“<”会变成“<”,变成无害的了。
二、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操做的时候都是这样。
另外还有两点须要指出,第一是这种写法虽然没有直接用到$_SERVER[’PHP_SELF’],但实际效果倒是同样的,只是发生的时间错后到了用户提交以后的下一个页面,因此,form的action仍是不要留空的好。第二点,除了PHP_SELF以外,其余的$_SERVER变量也许也会有相似的漏洞,好比SCRIPT_URI, SCRIPT_URL, QUERY_STRING, PATH_INFO, PATH_TRANSLATED等等,在使用他们以前必定要先做htmlentities之类的php