有没有一种方法可以在尽可能少的代码中为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文件