您如何保护您的网站免受本地文件包含和 SQL 注入 (PHP) 的影响?
7 回答
有许多措施要采取。确保在存储到数据库之前清理所有输入。我建议对将要存储的所有数据使用mysql_real_escape_string() 。将字符输入限制为合理的长度,并确保您获得了该字段所期望的数据类型。锁定多次提交特定数据区域的尝试。抓取上传文件的内容以寻找恶意模式。
Wikibooks 有一章是关于 SQL 注入的;
名单还在继续。幸运的是,即使在这方面稍加努力,也可以修补大量漏洞。
为 SQL 准备的语句(请参阅PDO::prepare()
)或正确的转义 ( PDO::quote()
)。
对于本地路径,您需要仔细清理输入(残酷但安全preg_replace('/[^a-z]/','',$str)
:)或完全避免在路径中使用不受信任的数据(使用 ID、预定义字符串等)
为了防止 SQL 注入,我建议使用 PDO(http://us3.php.net/pdo)。您需要的扩展程序等可能会阻止采用,但这是好东西。
就我个人而言,我使用了一个自制的数据库访问层,我的所有查询都通过它实现了一堆不错的功能,包括mysql_real_escape_string()
“本地文件包含”是指您include()
在从用户输入构建的路径上调用或类似的情况,例如在非常简单的基于文件的 CMS 或类似内容中?如果是这样,答案与 SQL 注入基本相同——您必须清理输入。
清理文件路径需要您设置一些关于可以从何处包含文件的基本规则,并无情地拒绝任何不符合要求的输入。例如,如果您只是在子目录中按名称包含文件,那么您可以应用以下基本算法:
- 拒绝包含
.
,..
或/
(或\
在 Windows 下)的文件名 - 将文件名限制为基本的字母数字字符
- 附加包含目录名称并附加适当的扩展名
PHP 文档有更多关于文件系统安全的信息。您还可以设置open_basedir
将文件访问限制在特定目录树内,但这是 PHP 的“安全模式”的一部分,该模式已被弃用(将在 PHP 6.0 中删除),因为它并不是非常安全。
就像其他人所说的那样,mysql\_real\_escape\_string()
是防止 SQL 注入的最安全方法。我为我的所有 SQL 使用了一个自定义 DB 接口类,它通过一个sanitize()
函数传递所有需要的变量。这是从类中删除的 sanitize 函数,以防你想看看它。
/**
* Sanitize variable for querying
*
* @param mixed $var The variable to sanitize
* @param bool $deep Will inspect the string deeper, converting 'null' to NULL and adding '' around strings
* @param mixed $numstrings Whether or not to treat numbers as strings (ie add quotes)
* @return $var
*/
function sanitize($var, $deep = true, $numstrings = false) {
if (is_array($var)) { //run each array item through this function (by reference)
foreach ($var as $key=>$val) {
$var[$key] = sanitize($val, $deep, $numstrings);
}
}
else if (is_null($var) || ( $deep && preg_match('/^null$/i', $var) > 0 ) ) { //convert null variables to SQL NULL
$var = "NULL";
}
else if (is_bool($var)) { //convert boolean variables to binary boolean
$var = ($var) ? 1 : 0;
}
else if ($numstrings && is_string($var)) {
$var = mysql_real_escape_string($var);
if ($quotes) {
$var = "'". $var ."'";
}
}
else if (!is_numeric($var)) { //clean strings
$var = mysql_real_escape_string($var);
if ($deep) {
$var = "'". $var ."'";
}
}
return $var;
}
至于“本地文件包含”,我使用了两种不同的方法。请记住,最安全的技术是将敏感文件保存在网络无法访问的地方。
如果它只是一个文件,或者我不想让全世界看到,我只需将“.ht”附加到文件名。默认情况下,Apache 拒绝访问以“.ht”开头的文件。只需确保不要将您的文件命名为与 Apache 配置文件(.htaccess、.htpasswd 等)相同的名称。
如果您有多个不想访问的文件,请将它们全部保存在您网站的子目录中(同样,敏感文件应该在其他地方)。然后在子目录中,添加一个拒绝访问该目录的 .htaccess 文件(它们仍然可以通过 PHP 访问)。
#this is all you need in the file
Order Allow , Deny
Deny from all
为避免 SQL 注入在您提交之前加密您的密码