PHP漏洞原理
PHP是一种服务器端的,嵌入HTML的脚本语言。PHP区别其他语言的地方是它的代码在服务器端执行,例如收集表格数据,生成动态页面内容,或者收发cookies等,今天我们来了解一下它的漏洞问题。
汽车雨刷器 一 全局变量
全局变量,就是能够在整个程序执行的过程中都存在的变量。基于PHP的应用程序的主函数一般都是接受用户的输入,然后对输入数据进行处理,然后把结果返回到客户端浏览器。为了使PHP代码访问用户的输入尽可能容易,实际上PHP是把这些输入数据看作全局变量来处理的。
<form method="get" action="get.php">
<input type="text" name="test">
<input type="submit">
</form>
这段代码会显示一个文本框和提交按钮。当用户点击提交按钮时,页面就会将用户输入的数据传递到“get.php”,当“get.php”运行时,“$test”就会自动创建,包含了用户在文本框输入的数据。我们可以看出,攻击者可以按照自己的意愿创建任意的全局变量。下面的认证代码暴露了PHP的全局变量所导致的安全问题:
<?php
if ($password == "monster")
$pass = 1;
……………
if ($pass == 1)
echo "认证通过";
?>
上面的代码首先检查用户的密码是否为“monster”,如果匹配的话,则设置“$pass”为“1”,之后如果“$pass”的值为“1”的话,就会认证通过。
从表面看起来,这是正确的,但是这段代码犯了想当然的错误,它假定“$pass”在没有设置值的时候是空的,却没有想到,攻击者可以创建任何全局变量并赋值,通过提交“server/get.php?pass=1”的方法,我们完全可以欺骗这段代码,使它相信我们是已经认证过的。
二 过滤输入/输出转义
过滤是Web应用安全的基础。它是你验证数据合法性的过程。通过在输入时确认对所有的数据进行过滤,你可以避免未过滤数据在你的程序中被误信及误用。大多数流行的PHP应用的漏洞最终都是因为没有对输入进行恰当过滤造成的。最好的方法是把过滤看成是一个检查的过程。
另外一个Web应用安全的基础是对输出进行转义或对特殊字符进行编码,以保证原意不变。例如,O'Reilly在传送给MySQL数据库前需要转义成O\'Reilly。单引号前的反斜杠代表单引号是数据本身的一部分,而不是并不是它的本义。
为了区分数据是否已转义,还是建议定义一个命名机制。对于输出到客户机的转义数据,使$html数组进行存储,该数据首先初始化成一个空数组,对所有已过滤和已转义数据进行保存。
<?php
$html = array( );
$html['username'] = htmlentities($clean['username'], ENT_QUOTES, 'UTF-8');
echo "<p>Welcome, {$html['username']}.</p>";中国著名的桥
?>
htmlspecialchars( )函数与htmlentities( )函数基本相同,它们的参数定义完全相同,只不过是htmlentities( )的转义更为彻底。
通过$html['username']把username输出到客户端,你就可以确保其中的特殊字符不会被浏览器所错误解释。如果username只包含字母和数字的话,实际上转义是没有必要的,但
是这体现了深度防范的原则。
SQL 注入是PHP应用中最常见的漏洞之一,事实上,开发者需要同时犯以上两个错误才会引发一个SQL注入漏洞。
三 远程文件
辐射3详细攻略 PHP是一种具有丰富特性的语言,提供了大量的函数,使编程者实现某个功能很容易。但是从安全的角度来看,功能越多,要保证它的安全性就越难,远程文件就是说明这个问题的一个很好的例子:
<?php
if (!($fo = fopen("$file", "s"))
echo("文件$file打开错误 ");
梦见大雨 ?>
上面的脚本试图打开文件“$filename”,如果失败就显示错误信息。那么如果我们能够指定“$file”的话,就能利用这个脚本浏览任何文件。但是,这个脚本还存在一个不太明显的特性,那就是它可以从任何其它WEB或FTP站点读取文件。实际上,PHP的大多数文件处理函数对远程文件的处理是透明的。
例如:
如果指定“$file”为“target/scripts/..%c1%1c../winnt/?/c+dir”,则上面的代码实际上是利用主机target上的unicode漏洞,执行了dir命令。
这使得支持远程文件的include(),require(),include_once()和require_once()在上下文环境中变得更有趣。这些函数主要功能是包含指定文件的内容,并且把它们按照PHP代码解释。
例如:
<?php
include($dir."/ attack.php");
?>
上例中“$dir”一般是一个在执行代码前已经设置好的路径,如果攻击者能够使得“$dir”没有被设置的话,那么他就可以改变这个路径。但是攻击者并不能做任何事情,因为他们只能在他们指定的路径中访问文件“attack.php”。但是由于有了对远程文件的支持,攻击者就可以做任何事情。例如,攻击者可以在某台服务器上放一个文件“attack.php”,里面包含了恶意代码
然后把“$dir”设置为“evilhost/”,这样我们就可以在目标主机上执行上面的恶意代码,将结果返回到客户的浏览器中。
需要注意的是,攻击服务器(也就是evilhost)应该不能执行PHP代码,否则攻击代码会在攻击服务器,而不是目标服务器执行。
四 文件上载
PHP自动支持基于RFC 1867的文件上载,我们看下面的例子:
<form method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="hidden" name="maxfilesize" value="1024">
<input type="submit">
党员转正思想汇报 </form>
上面的代码让用户从本地机器选择一个文件,当点击提交后,文件就会被上载到服务器。这显然是很有用的功能,但是PHP的响应方式会使这项功能变的不安全。当 PHP在它开始解析被调用的PHP代码之前,它会先接受远程用户的文件,检查文件的长度是否超过 “$ maxfilesize variable”定义的值,如果通过这些测试的话,文件就会被存在服务器的一个临时目录中。
因此,攻击者可以发送任意文件给运行PHP的主机,在PHP程序还没有决定是否接受文件上载时,文件就已经被保存在服务器上面了。
现在我们看一下处理文件上载的PHP程序,正如上面所说,文件被接收并且存在服务器
上(位置一般是/tmp),文件名一般是随机的。PHP程序需要上载文件的信息以便处理它,这可以通过两种方式,一种方式是在PHP 3中已经使用的,另一种是在我们对以前的方法提出安全公告后引入的。
但是,我们可以肯定的说,问题还是存在的,大多数PHP程序还是使用老的方式来处理上载文件。PHP设置了四个全局变量来描述上载文件,比如说上面的例子:
$file = Filename on local machine (e.g "/tmp/phpxXuoXG")
$file_size = Size in bytes of file (e.g 1024)
$file_name =远程系统上的文件名(e.g "c:/")
$file_type = Mime type of uploaded file (e.g "text/plain")
然后PHP程序开始处理根据“$file”指定的文件,问题在于“$file”不一定是一个PHP设置的变量,任何远程用户都可以指定它。如果我们使用下面的方式:
vulnhost/file.php?file=/ ... file_
就导致了下面的PHP全局变量(当然POST方式也可以(甚至是Cookie)):
$file = "/etc/passwd"
$file_size = 10240
$file_type = "text/plain"
$file_name = ""
上面的表单数据正好满足了PHP程序所期望的变量,但是这时PHP程序不再处理上载的文件,而是处理“/etc/passwd”(通常会导致内容暴露)。这种攻击可以用于暴露任何敏感文件的内容。
我 在前面已经说了,新版本的PHP使用HTTP_POST_FILES[]来决定上载文件,同时也提供了很多函数来解决这个问题,例如有一个函数用来判断某个文件是不是实际上载的文件。这些函数很好的解决了这个问题,但是实际上肯定有很多PHP程序仍然使用旧的方法,很容易受到这种攻击。
作为文件上载的攻击方法的一个变种,我们看一下下面的一段代码:
<?php
if (file_exists($file))
include("$file");环保家具品牌
?>
如 果攻击者可以控制“$file”的话,很显然它可以利用“$file”来读取远程系统上的任何文件。攻击者的最终目标是在远程服务器上执行任意指令, 但是他无法使用远程文件,因此,他必须得在远程服务器上创建一个PHP文件。这乍看起来好象是不可能的,但是文件上载帮了我们这个忙,如果攻击者先在本地 机器上创建一个包含PHP代码的文件,然后创建一个包含名为“file”的文件域的表单,最后用这个表单通过文件上载把创建的包含PHP代码的文件提交 给上面的代码,PHP就会把攻击者提交的文件保存起来,并把“$file”的值设置为攻击者提交的文件,这样file_exists()函数会检查通过,攻击者的代码也将执行。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论