提问人:kanohn 提问时间:3/2/2021 最后编辑:Dharmankanohn 更新时间:3/2/2021 访问量:59
mysqli 真正的转义字符串在查询内部或外部
Mysqli Real Escape String Inside or Outside Query
问:
我对真正的转义字符串和sql注入的安全性有疑问。
如果我在查询中放置真正的转义字符串,有什么区别吗?喜欢:
$ano = $_POST['ano'];
$SQL->query("DELETE from viewers WHERE ano = '".$SQL->real_escape_string($ano)."'");
或者正确的方法是做这样的?
$ano = $SQL->real_escape_string($_POST['ano']);
$SQL->query("DELETE from viewers WHERE ano = '$ano'");
忽略$SQL,这只是一个例子。
答:
2赞
tadman
3/2/2021
#1
这两种方法都是不正确的。相反,解决方案是使用带有占位符值的预准备语句。
没有其他安全的方法来处理数据参数。
换言之,此查询应如下所示:
$stmt = $SQL->prepare('DELETE from viewers WHERE ano=?'); // Single quotes prevent accidental interpolation/injection
$stmt->bind_param('s', $_POST['ano']); // Just use $_POST directly
$stmt->execute();
这是安全的方法。出现 SQL 注入漏洞的可能性为零。
只有在极少数情况下,占位符值不起作用,但您需要根据具体情况解决这些问题,以查看最佳方法。
手动转义的代码应该是丑陋的,并且应该非常明显地看到所有值都被转义,绝对不会因为愚蠢的拼写错误而使用错误的变量。它还应包括解释和/或道歉形式的评论,说明为什么准备好的声明不起作用。
如果始终如一地使用占位符值,则不会出现任何 SQL 注入错误。这些是一些最糟糕的处理,因为它们通常出现在您通常可能不会测试的异常情况下,并且可能被攻击者利用。即使是一个 SQL 注入错误也足以破坏一个应用程序,因此这里的风险非常高。
评论
1赞
tadman
3/2/2021
@TangentiallyPerpendicular 我不认为你意识到这个问题是多么普遍,也没有意识到它对PHP社区来说是多么独特,在它被公认为一个问题的几十年后,教程仍然推荐危险的方法来解决这个问题。
0赞
kanohn
3/2/2021
@tadman 好的,谢谢。我已经搜索了准备语句,但是对于我的其他查询,我应该使用什么 var?stmt = 用于第一个查询。我可以使用任何其他 var 名称吗?stmt2...等。
0赞
Tangentially Perpendicular
3/2/2021
@tadman我完全意识到这一点,但大声喧哗和杂七杂八是疏远你试图接触的人的好方法。
1赞
tadman
3/2/2021
一般来说,你应该有简单的约定并坚持下去。在大多数情况下,您一次只需要一个语句,因此,就像在文档中使用时一样,您可以摆脱这一点。如果你要处理两个以上的语句,你需要决定你是否要打破这个惯例,要么使用数组,要么使用名称来帮助组织事情。像这样的名字并不能真正传达它是什么,所以你可能会在不知情的情况下错误地使用它。$stmt
$stmt_order_insert
$stmt2
1赞
Your Common Sense
3/2/2021
@TangentiallyPerpendicular我看不到原始评论,但我几乎可以说出它是什么。我有一个非常简单的经验法则,你可以根据它来确定它是否值得发泄:只要这个臭名昭著的函数被用于防止SQL注入的目的,它就必须被丢弃,转而支持准备好的语句。
评论
$stmt = $SQL->prepare('DELETE from viewers WHERE ano=?'); $stmt->bind_param('s', $ano); $stmt->execute(); if($SQL->affected_rows){ /* there was at least one row affected */ } $stmt->close();