网站地图    收藏   

主页 > 后端 > 网站安全 >

PHP的安全问题 - 网站安全 - 自学php

来源:自学PHP网    时间:2015-04-17 12:00 作者: 阅读:

[导读] PHP的语法结构与C、Prel 非常相似,开发者可以直接在任何文本编辑器中编辑 PHP 命令代码,不需要任何特殊的开发环境。在 Web 页面中,所有 PHP 代码都被放置在 ?php 和 ?之间。PHP 存在着...

PHP的语法结构与C、Prel 非常相似,开发者可以直接在任何文本编辑器中编辑 PHP 命令代码,不需要任何特殊的开发环境。在 Web 页面中,所有 PHP 代码都被放置在 “<?php” 和 “?>”之间。PHP 存在着它自身独有的一些安全问题。
1)全局变量未初始化漏洞
PHP中的全局变量是不需要预先声明的,他们会在第一次使用时自动创建,由 PHP 根据上下文环境自动确定变量的类型。这对于程序员而言是相当方便的,只要一个变量被创建,就可以在程序中的任何地方使用。,但也导致在 PHP 程序的编写过程中,程序员很少初始化变量,通常都直接使用创建默认的空值。这使得攻击者可以通过给全局变量赋值来欺骗代码,执行恶意的目的。
PHP程序员通过接受用户的输入(如表单、Cookie或变量值),然后对用户数据进行处理,将结果返回到客户端浏览器

 
<form method="get" action="test.php">
<input type="text" name="test">
<input type="submit">
</form>
在这个例子中,PHP程序员将会在客户端浏览器中显示一个提交按钮。当用户单击“提交”按钮时,test.php 将处理用户的输入。在他运行时,“$test”变量中包含用户的输入数据,然而用户可能会在浏览器地址栏的 URL 中直接输入变量值,如输入
http://test/test.php?test=justtest
此时 test 变量的值将被直接置为 justtest 。攻击者可以利用这种方法来跳过验证机制。
在来看这一段 PHP 代码:

<!--?php 
if($pwd = "password"){
  $pass = 1;
}
if($pass ==1 )
echo "you are a vaild user";
?-->
这段程序的设计意图是通过检验用户输入的口令来验证用户是否具有使用服务的权限。但攻击者可以通过
http://test/test.php:pass=1
将$pass(pass变量)置为1,跳过设置的验证机制,直接使用服务。
理论上讲,为了保护PHP程序的安全,对所有的变量都应该在使用前对其验证。但当PHP程序中变量较多时,这要求巨大的工作量,实际常用的一种保护方式是检查用户的提交数据。
PHP 使用四个不同的数组变量来处理用户输入,一个安全的PHP程序应该对这四个数组分别进行检查,包括:
1.HTTP_GET_VARS,处理GET方式提交的数据。
2.HTTP_POST_VARS,处理POST方式提交的数据。
3.HTTP_COOKIE_VARS,处理COOKIE方式提交的数据。
4.HTTP_POST_FILES(PHP 4.10之后的版本),处理文件上传变量。
2)文件上传功能
PHP 自动支持文件上载。看下面例子:

<form method="post" enctype="multipart/form-data">
<input type="file" name="hello">
<input type="hidden" name="max_file_size" value="10240">
<input type="submit">
</form>
这段代码让用户从本地机器上选择一个文件,当单击“提交”按钮后,文件就会被上载到服务器。这显然是很有用的功能,但是PHP程序的响应方式使这项功能变得不安全。
当PHP程序第一次接到这种请求时,设置在他开始解析被调用的PHP代码之前,他会先接受远程用户的文件,检查文件的长度是否超过$MAX_FILE_SIZE 变量定义的值。如果通过测试,文件就会被存在本地的一个临时目录中。
因此,攻击者可以发送任意文件给主机,在PHP程序还没有决定是否接收文件上传时,文件就已经被存储到服务器上了。文件被临时存储在服务器上时(存储的位置是在配置文件中指定的,一般是/tmp),扩展名一般是随机的,类似phpxXuoXG的形式。PHP 程序使用四个全局变量来描述这个上载文件,以上面的例子为例,PHP程序可以使用全局变量$hello、$hello_size、$hello_name、$hello_type来描述上载的文件。
$hello = 本地计算机上的文件名(例如“/tmp/phpxXuoXG”)
$hello_size = 以字节为单位的文件大小(例如1024)
$hello_name= 上传的文件在远程计算机上的原始文件名(例如:c:\\temp\\hello.txt)
$hello_type = 上传文件的Mine类型(例如“text/plain”)
然后PHP程序开始处理$hello 指定的文件。
问题在于$hello 不一定是一个 PHP设置的变量,任何远程用户都可以指定它。如果使用下面的方式:
http://www.2cto.com /vuln.php?hello=/etc/passwd&hello_size=1024&hello_type=text/plain&hello_name=hello.txt
就导致了下面的PHP全局变量的赋值:
$hello = "etc/passwd"
$hello_size = 1024
$hello_type= "text/plain"
$hello_name = "hello.txt"
这四个数据正好满足了 PHP 程序所期望的变量,但是,这时候 PHP 不再是处理上载的文件,而是处理/etc/passwd 。这种攻击可以用于暴漏任何敏感文件的内容。
为解决这以问题,新版本的PHP使用 HTTP_POST_FILES[]来处理上载文件,同时提供了许多新的函数来弥补这个过程的缺陷,例如使用一个专门的函数来判断某个文件是不是实际上载的文件,他们很好地解决了这一个问题,但是实际上仍然有很多 PHP 程序使用的是旧的全局变量描述文件的方法,因而仍然和内容收到这种攻击。
3)库文件引用问题
最初,人们开发和发布PHP程序的时候,为了区别代码库和主程序代码,为代码库文件设置了一个扩展名.inc。但是他们很快发现这是一个错误。因为当把PHP作为Apache的模块使用时,PHP解释器是根据文件的扩展名来决定是否解析为PHP代码,而扩展名由站点管理员指定,一般是.php 、.php3 和 .php4,其他扩展名的文件将无法被PHP解释器正确解析为PHP代码,如果直接请求服务器上的这类文件,就会得到该文件的源代码,这会引起严重的源代码泄漏问题。
一个最简单的解决办法就是给每个文件都指定一个PHP文件的扩展名,但是,由于每个文件都被指定成PHP扩展名,因而通过直接请求这个文件,可能使本该在某个上下文环境中运行的代码独立运行。
下面是一个明显的例子。
main.php中的代码:

<!--?php
$libDir = "/libdir";
$langDir = "$libdir/languages"
...
include("$libdir/loadlanguage.php");
?-->
libdir/loadlanguage.php 中的代码:

...
include("$langDir/$userLang");
当libdir/loadlanguage.php 被main.php调用时是相当安全的。但是由于libdir/loadlanguage 扩展名为 PHP解释器能正确解析的.php,因此远程攻击者就可以直接请求这个文件运行,并且可以任意指定$langDir和$userLang的值。这就将带来安全隐患。
PHP的配置非常灵活,完全可以通过合理地配置选项来抵抗其中的一些攻击。
(1)禁止为用户创建全局变量。将register_globals选项设置为OFF,进制PHP程序自动为用户输入创建全局变量。也就是说,如果用户提交表单变量hello,PHP不会创建$hello,而只会创建HTTP_GET/POST_VARS['hello]。这是PHP中一个极其重要的选项。
(2)设置安全模式。设置safe_model选项为ON。这将限制可执行命令和可使用的函数,以及文件访问权限。设置allow_url_fopen选项为OFF,禁止PHP程序通过URL方式打开远程文件。
(3)禁止显示错误信息。将display_error选项设置为OFF,log_errors 选项设置为ON,禁止把错误信息显示在网页中,而是记录到服务器的日志文件里。这可以有效地抵制攻击者对目标脚本中所使用的函数和其他敏感信息的探测

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论