首页 > 代码库 > 谈谈关于PHP的代码安全相关的一些致命知识

谈谈关于PHP的代码安全相关的一些致命知识

使用 mysql_real_escape_string() 防止 SQL 注入问题。
使用正则表达式和 strlen() 来确保 GET 数据未被篡改。
使用正则表达式和 strlen() 来确保用户提交的数据不会使内存缓冲区溢出。
使用 strip_tags() 和 htmlspecialchars() 防止用户提交可能有害的 HTML 标记。
避免系统被 Tamper Data 这样的工具突破。
使用惟一的令牌防止用户向服务器远程提交表单。
 

规则1:绝不相信外部数据或者输入数据

 
比如:GET变量,表单POST,数据库,配置文件,会话变量或者是cookid
 
解决方法:对用户输入进行清理的简单方法,使用正则表达式来处理,只希望接收字母,字符串限制为特定数量的字符,或者所有的字母都是小写的
$myUsername = cleanInput($_POST[‘username‘]); //clean!
$arrayUsers = array($myUsername, ‘tom’, ‘tommy’); //clean!
define(”GREETING”, ‘hello there’ . $myUsername); //clean!
function cleanInput($input){
$clean = strtolower($input);
$clean = preg_replace(”/[^a-z]/”, “”, $clean);
$clean = substr($clean,0,12);
return $clean;
}
规则2:禁用那些使安全性难以实施的PHP设置
例如:要确保禁用register_globals.在项目上线是要确保已经关闭了错误报告级别
 
规则3:SQL注入
  • 使用mysql_real_escape_string()作为用户输入的包装器。  
  •    $sql = "select count(*) as ctr from user where username = ‘".mysql_real_escape_string($username)." ‘ and password = ‘".mysql_real_escape_string($pw)." ‘ limit 1 ";
    使用了此函数能对字符串中字符进行转义,使得字符串不能传递‘ 等特殊符号
  • 防止用户操纵变量
在URL地址栏中,通常会有将链接指向template.php?pid = 33或者 template.php?pid = 456 这样的位置,URL中问号后面的部分称之为查询字符串,也称之为GET查询字符串
$pid = $_GET[‘pid‘];
$obj = new Page();
$content = $obj ->fetchPaget($pid);
代码看起来没什么问题,但是用户可以在地址栏上随意输入值了。我们应该确保pid 应该是数字,可以使用 is_numeric(),但还不够,如果是10.2,+0234.34e5,0xff339988f又该如何呢,我们可以使用正则来显示GET变量 preg_match(‘/^[0-9+$]/‘,$pid).还要检查变量的长度是否为0,显示变量的长度,防止缓冲区溢出
$pid = $_GET[‘pid‘];
if (strlen($pid)){
if (!ereg(”^[0-9]+$”,$pid) && strlen($pid) > 5){
}
}else{
}
$obj = new Page;
$content = $obj->fetchPage($pid);

?> [/php]
  • 缓冲区溢出攻击
缓冲区溢出攻击向缓冲区发送大量数据,使部分数据溢出到相邻的内存缓冲区,从而破坏缓冲区或者重写逻辑。这样就能够造成拒绝服务、破坏数据或者在远程服务器上执行恶意代码。
防止缓冲区溢出攻击的惟一方法是检查所有用户输入的长度
 if ($_POST[‘submit‘] == “go”){
$name = substr($_POST[‘name‘],0,40);
}
?>
$_SERVER[‘PHP_SELF‘];?>” method=”post”>
 
Name
“name” id=”name” size=”20″ maxlength=”40″/>
  • 防止十六进制字符
if ($_POST[‘submit‘] == “go”){
$name = substr($_POST[‘name‘],0,40);
$name = cleanHex($name);
}
function cleanHex($input){
$clean = preg_replace(”![\][xX]([A-Fa-f0-9]{1,3})!”, “”,$input);
return $clean;
}
  • 跨站点脚本攻击
PHP 提供了 strip_tags() 函数,这个函数可以清除任何包围在 HTML 标记中的内容。strip_tags() 函数还允许提供允许标记的列表,比如
if ($_POST[‘submit‘] == “go”){
$name = strip_tags($_POST[‘name‘]);
$name = substr($name,0,40);
$name = cleanHex($name);
}
function cleanHex($input){
$clean = preg_replace\
(”![\][xX]([A-Fa-f0-9]{1,3})!”, “”,$input);
return $clean;
}
从安全的角度来看,对公共用户输入使用 strip_tags() 是必要的。如果表单在受保护区域(比如内容管理系统)中,而且您相信用户会正确地执行他们的任务(比如为 Web 站点创建 HTML 内容),那么使用 strip_tags() 可能是不必要的,会影响工作效率。
 
 
  • 远程表单提交

Web 的好处是可以分享信息和服务。坏处也是可以分享信息和服务,因为有些人做事毫无顾忌。
以表单为例。任何人都能够访问一个 Web 站点,并使用浏览器上的 File > Save As 建立表单的本地副本。然后,他可以修改 action 参数来指向一个完全限定的 URL(不指向 formHandler.php,而是指向http://www.yoursite.com/formHandler.php,因为表单在这个站点上),做他希望的任何修改,点击 Submit,服务器会把这个表单数据作为合法通信流接收。
首先可能考虑检查 $_SERVER[‘HTTP_REFERER‘],从而判断请求是否来自自己的服务器,这种方法可以挡住大多数恶意用户,但是挡不住最高明的黑客。这些人足够聪明,能够篡改头部中的引用者信息,使表单的远程副本看起来像是从您的服务器提交的。
处理远程表单提交更好的方式是,根据一个惟一的字符串或时间戳生成一个令牌,并将这个令牌放在会话变量和表单中。提交表单之后,检查两个令牌是否匹配。如果不匹配,就知道有人试图从表单的远程副本发送数据。
要创建随机的令牌,可以使用 PHP 内置的 md5()、uniqid() 和 rand() 函数,如下所示:
清单 18. 防御远程表单提交
                   
[php] session_start();
if ($_POST[‘submit‘] == “go”){
//check token
if ($_POST[‘token‘] == $_SESSION[‘token‘]){
  $name = strip_tags($_POST[‘name‘]);
  $name = substr($name,0,40);
  $name = cleanHex($name);
}else{
}
}
$token = md5(uniqid(rand(), true));
$_SESSION[‘token‘]= $token;
function cleanHex($input){
$clean = preg_replace(”![\][xX]([A-Fa-f0-9]{1,3})!”, “”,$input);
return $clean;
}
?>

谈谈关于PHP的代码安全相关的一些致命知识