PHP:mysql_real_escape_string是否足以清理用户input?
mysql_real_escape_string
是否足以在大多数情况下清除用户input?
::编辑::
我主要想防止SQL注入,但我最终想知道,如果我应用mysql_real_escape_string后我可以信任用户数据,或者如果我应该采取额外的措施来清理数据之前,我将它传递给应用程序和数据库。
我看到清理HTML字符的地方很重要,但我不认为需要信任用户input。
Ť
在所有的情况下, mysql_real_escape_string
是不够的,但它绝对是非常好的朋友。 更好的解决scheme是使用Prepared Statements
//example from http://php.net/manual/en/pdo.prepared-statements.php $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)"); $stmt->bindParam(1, $name); $stmt->bindParam(2, $value); // insert one row $name = 'one'; $value = 1; $stmt->execute();
另外,不要忘记HTMLPurifier可以用来丢弃任何无效/可疑的字符。
………..
编辑:根据下面的评论,我需要张贴这个链接(我应该做之前抱歉造成混乱)
mysql_real_escape_string()与Prepared Statements
引用:
mysql_real_escape_string()倾向于影响addslashes()的相同types的问题。
Chris Shiflett (安全专家)
您的问题的答案是不。mysql_real_escape_string()不适合所有用户input和mysql_real_escape_string()不会停止所有的SQL注入。 addslashes()是另一个在php中使用的常用函数,它也有同样的问题。
弱点代码:
mysql_query("select * from user where id=".mysql_real_escape_string($_GET[id]));
poc漏洞利用:
http://localhost/sql_test.php?id=1 or sleep(500)
这个补丁是在id周围使用引号:
mysql_query("select * from user where id='".mysql_real_escape_string($_GET[id])."'");
真的最好的办法是使用参数化的查询,这是很多人指出的。 Pdo运作良好,adodb是另一个stream行的php库。
如果你使用mysql_real_escape_string,应该只能用于sql注入,而没有别的。 漏洞高度依赖于数据的使用方式。 应该在function的基础上对function进行安全措施。 是的,XSS是一个非常严重的问题 。 不过滤HTML是严重的错误,一个黑客将用于pw3n你。 请阅读xss常见问题 。
对数据库来说,是的。 你会想要充分考虑为输出转义/编码数据。
您还应该考虑根据您期望的内容来validationinput。
你有没有考虑使用准备好的陈述 PHP提供了多种与数据库交互的方式。 其中大部分都比mysql_ *函数更好。
PDO , MDB2和MySQL的改进应该让你开始。
什么情况?
对于SQL查询,这是很好的。 (Prepared语句更好 – 我为此投了PDO – 但函数转义就好)。对于HTML等,它不是工作的工具 – 尝试一个通用的htmlspecialchars
专用或更精确的工具,如HTML净化器 。
要解决编辑问题 :您可以添加的唯一的其他层是数据的自动生成,例如,确认如果要将整数放入数据库中,并且您期望得到一个正整数,则在尝试放入一个负整数。 就数据完整性而言, mysql_real_escape_string
是最好的转义语句(尽pipe准备好的语句是一个更清晰的系统,可以避免完全转义)。
mysql_real_escape_string()
仅用于防止SQL注入攻击。 它不会帮助您防止跨站点脚本攻击。 为此,您应该在输出最初从用户input中收集的数据之前使用htmlspecialchars()
。
有两种方法,一种是使用准备好的语句(正如其他答案中提到的那样),但这会减慢你的应用程序,因为你现在必须向数据库发送两个请求,而不是一个。 如果你能忍受降低的performance,那就去做吧。 准备好的语句使您的代码更漂亮,更容易处理。
如果您select使用mysql_real_escape_string,那么请确保您转义所有不受信任的string。 (mysql_real_escape_string)转义string是SQL注入安全 。 如果你不逃避所有的string,那么你是不安全的。 你应该真的结合mysql_real_escape_string和inputvalidation; 检查你希望保持一个数字的variables真的是一个数字,并在预期的范围内。 请记住,永远不要相信用户。
有不同types的“清洁”。
mysql_real_escape_string对于数据库数据来说已经足够了,但是如果它是HTML的话,它仍然可以在浏览器上进行评估。
要从用户input中删除HTML,可以使用strip_tags 。
我build议你看看使用PDO,而不是一般的MySQL的东西,因为它支持开箱即用的准备语句,以及那些处理无效数据的转义。
你可以尝试两个,如在
function clean_input($instr) { // Note that PHP performs addslashes() on GET/POST data. // Avoid double escaping by checking the setting before doing this. if(get_magic_quotes_gpc()) { $str = stripslashes($instr); } return mysql_real_escape_string(strip_tags(trim($instr))); }
最好的办法是使用Prepared Statements
我想我会补充说,PHP 5.2 +具有inputfilterfunction,可以以各种方式消毒用户input。
这里是手动input以及Matt Butcher的博客文章 ,他们为什么说他们很棒。