PHP代码安全点滴

我们来看看有那几点是需要注意的。

初始化你的变量
我们看下面的代码:
if ($admin)
{
echo ‘登陆成功!’;
include(‘admin.’);
}
else
{
echo ‘你不是管理员,无法进行管理!’;
}
我们看上面的代码好像是能正常运行,没有问题,那么假如我提交一个非法的参数过去,那么效果会如何呢?比如我们的这个页是 http://www.traget.com/login.php,那么我们提交:http://www.target.com/login.php?admin=1,呵呵,你想一想,我们是不是直接就是管理员,可以直接进行管理了?
当然,可能你会觉得不会犯这么简单错的错误,可最近暴出来的phpwind 1.3.6论坛漏洞,导致能够直接拿到管理员权限,就是因为有个$skin变量没有初始化,导致了后面一系列问题。
那么我们如何避免上面的问题呢?首先,从php.ini入手,把php.ini里面的register_global = off,就是不是所有的注册变量为全局,那么就能避免了。但是,我们不是服务器管理员,只能从代码上改进了,那么我们如何改进上面的代码呢?我们改写如下:
$admin = 0; // 初始化变量
if ($_POST['admin_user'] && $_POST['admin_pass'])
{
// 判断提交的管理员用户名和密码是不是对的相应的处理代码
// …
$admin = 1;
}
else
{
$admin = 0;
}

if ($admin)
{
echo ‘登录成功!’;
include(‘admin.php’);
}
else
{
echo ‘你不是管理员,无法进行管理!’;
}
那么这时候你再提交http://www.target.com/login.php?admin=1就不好使了,因为我们在一开始就把变量初始化为 $admin = 0 了,那么你就无法通过这个漏洞获取管理员权限。

防止SQL Injection
SQL注射应该是目前危害最大的攻击方法了,包括最早的ASP到PHP,都是国内这两年流行的技术,基本原理就是通过对提交变量的不过滤形成注入点然后使恶意用户能够提交一些SQL查询语句,导致重要数据被窃取、数据丢失损坏,或者直接被入侵者拿到后台管理权限。
我们既然了解了基本的注射入侵的方式,那么我们如何去防范呢?这个就应该我们从代码去入手了。
我们知道Web上提交数据有两种方式,一种是GET、一种是POSTT,那么很多常见的SQL注射就是从GET方式入手的,而且注射的语句里面一定包含一些SQL语句,SQL语句有四大关键词:select、update、delete、insert。如果我们在提交的数据中进行过滤是不是能够避免这些问题呢?
于是我们使用正则就构建如下函数:
/*
函数名称:inject_check()
函数作用:检测提交的值是不是含有SQL注射的字符,防止注射,保护服务器安全
参 数:$sql_str: 提交的变量
返 回 值:返回检测结果,ture or false
函数作者:heiyeluren
*/
function inject_check($sql_str)
{
return eregi(‘select|insert|update|delete|\’|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile’, $sql_str); // 进行过滤
}
函数里把“select,insert,update,delete, union, into, load_file, outfile /*, ./ , ../ , ‘”等等危险的参数字符串全部过滤掉,那么就能够控制提交的参数了,程序可以这么构建:
if (inject_check($_GET['id']))
{
exit('你提交的数据非法,请检查后重新提交!');
}
else
{
$id = $_GET['id'];
echo '提交的数据合法,请继续!';
}
?>
假设我们提交URL为:http://www.target.com/a.php?id=1,那么就会提示:“提交的数据合法,请继续!”。如果我们提交http://www.target.com/a.php?id=1′ select * from tb_name,就会出现提示:“你提交的数据非法,请检查后重新提交!”那么就达到了我们的要求。
但是,问题还没有解决,假如我们提交的是 http://www.target.com/a.php?id=1asdfasdfasdf 呢?这个URL是符合上面的规则的,但是实际上它是不正常的,于是为了避免可能出现的其它情况,我们可以再构建一个函数来进行检查:
/*
函数名称:verify_id()
函数作用:校验提交的ID类值是否合法
参 数:$id: 提交的ID值
返 回 值:返回处理后的ID
函数作者:heiyeluren
*/
function verify_id($id=null)
{
if (!$id) { exit(‘没有提交参数!’); } // 是否为空判断
elseif (inject_check($id)) { exit(‘提交的参数非法!’); } // 注射判断
elseif (!is_numeric($id)) { exit(‘提交的参数非法!’); } // 数字判断
$id = intval($id); // 整型化
return $id;
}
呵呵,那么我们就能够进行校验了,于是我们上面的程序代码就变成了下面的:
if (inject_check($_GET['id']))
{
exit('你提交的数据非法,请检查后重新提交!');
}
else
{
$id = verify_id($_GET['id']); // 这里引用了我们的过滤函数,对$id进行过滤
echo '提交的数据合法,请继续!';
}
?>
好,问题到这里似乎都解决了,但是我们有没有考虑过Post提交的大批量的数据呢?比如一些字符可能会对数据库造成危害,比如“_”,“%”,这些字符都有特殊意义,那么我们如果进行控制呢?还有一点,就是当我们的php.ini里面的“magic_quotes_gpc = off”的时候,那么提交的不符合数据库规则的数据都是不会自动在前面加“\”的,那么我们要控制这些问题,于是构建如下函数:
/*
函数名称:str_check()
函数作用:对提交的字符串进行过滤
参 数:$var: 要处理的字符串
返 回 值:返回过滤后的字符串
函数作者:heiyeluren
*/
function str_check( $str )
{
if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否打开
{
$str = addslashes($str); // 进行过滤
}
$str = str_replace(“_”, “\_”, $str); // 把 ‘_’过滤掉
$str = str_replace(“%”, “\%”, $str); // 把’ % ‘过滤掉
return $str;
}
OK,我们又一次的避免了服务器被沦陷的危险。
最后,再考虑提交一些大批量数据的情况,比如发贴,或者写文章、新闻,我们需要一些函数来帮我们过滤和进行转换,再上面函数的基础上,我们构建如下函数:
/*
函数名称:post_check()
函数作用:对提交的编辑内容进行处理
参 数:$post: 要提交的内容
返 回 值:$post: 返回过滤后的内容
函数作者:heiyeluren
*/
function post_check($post)
{
if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否为打开
{
$post = addslashes($post); // 进行magic_quotes_gpc没有打开的情况对提交数据的过滤
}
$post = str_replace(“_”, “\_”, $post); // 把 ‘_’过滤掉
$post = str_replace(“%”, “\%”, $post); // 把’ % ‘过滤掉
$post = nl2br($post); // 回车转换
$post= htmlspecialchars($post); // html标记转换
return $post;
}
在脚本编程的时候,一定要养成良好的编程习惯,例如本文所说的对变量进行初始化,同时注意变量的过滤,变量对整个系统的安全性起了很重要的作用。希望这些点滴能让你养成更好的习惯。

相关日志

标签Tags:, , ,
Leave a comment

0 Comments.

Leave a Reply


[ Ctrl + Enter ]