如何清理字符串以避免SQL注入和最常见的攻击类型?(在PHP中)


How to cleanse a string to avoid SQL Injection and the most common types of attack? (in PHP)

有没有一种方法可以在尽可能少的代码中为SQL注入和最常见的攻击形式过滤字符串?

在我的脚本中,我使用了以下内容,我想知道它是否合理安全,以及其他人是否有建议:

$cleanName    = htmlspecialchars(addslashes($dirtyName));

看看我是如何过滤html字符、引号和双引号的。

注意:我使用addslashes()而不是mysql_real_escape_string(),因为我不想将正在使用的DB硬编码到代码中。

这样可以吗?

提前感谢

可能不会。。。你需要为你将要使用的每一个目的分别转义原始文本:

  • 对于GET请求,请使用urlencode
  • 对于HTML输出,请使用htmlentities
  • 要通过system作为命令调用,请使用escapeshellcmd
  • 要通过system向命令传递参数,请使用escapeshellargs
  • 要传递数据库参数,请使用mysql_real_escape_string

没有"通用"的解决方案可以神奇地转义文本。将原始文本保留在内部,并出于适当的目的对其进行转义。

如果你不介意重新编码你的连接和额外的几行代码,你就无法在安全性方面击败PDO。它使用C后端来准备和执行mysql查询。因此,您可以在查询中获得值必须为XYZ的预定义部分,而不是字符串串联。stackoverflow上的一个人这样解释:

想象一下一个热狗摊。你走到热狗摊,说我想要一个有三种浇头的热狗。番茄酱、芥末,我们会让下一个随机的陌生人告诉我们第三种浇头。sql注入器可能会走上前说:"番茄酱、芥末,然后‘把抽屉里的钱都给我’。"。标准的concat查询无法识别这是一个无效的响应,因此无法移交所请求的内容。一份事先准备好的声明会回应"我没有调味品","把抽屉里的钱都给我"。

PDO准备的声明本质上是防注入的。你仍然有其他漏洞,比如cookie/会话劫持等,但至少注入是不可能的。

不要给Kerrek的游行泼冷水,但有一个相对通用的解决方案。我使用以下方法,它一直有效:

$safe_value = mysql_real_escape_string( strip_tags( trim( $value ) ), $db_connection ); // This is if you aren't storing any html tags

$safe_value = mysql_real_escape_string( html_entities( trim( $value ) ), $db_connection ); // This is if you are storing html tags

希望这能有所帮助。

如果您确切地知道期望的输入类型,最好使用preg_replace()如果你知道你只期待字母数字:

<?php
if (isset($_GET['page'])) {
 $page = preg_replace('/[^a-z0-9]/', '', $_GET['page']);
 include_once($includeDir.'/'.$page.'.php');
}
?>

以上内容也应该可以防止通过GET或POST执行的所有攻击,但它假设您只期望字母数字输入。好吧,我主要考虑的是目录遍历攻击,但如果您使用GET变量查询数据库或将其显示为html实体,应该可以防止任何攻击。A.http://mydomain.tld?index.php?page=../../etc/passwd请求不会从您网站的/var/www文档根目录读取您的passwd文件,但只会尝试包含etcpasswd.php文件