防止SQL注入攻击

5
以下的PHP MySQL语句是否能够防止SQL注入攻击?
$strSQL = "SELECT * FROM Benutzer WHERE Benutzername = '".$Benutzer."' AND Password = '".md5($PW)."'";

变量$Benutzer$PW是用户输入的内容。
我们正在检查用户名和密码是否存在常见的SQL注入技术:

' or 0=0 --, " or 0=0 --, or 0=0 --, ' or 0=0 #, " or 0=0 #, or 0=0 #, ' or 'x'='x, " or "x"="x, ') or ('x'='x, ' or 1=1--, " or 1=1--, or 1=1--, ' or a=a--, " or "a"="a, ') or ('a'='a, ") or ("a"="a, hi" or "a"="a, hi" or 1=1 --, hi' or 1=1 --, hi' or 'a'='a, hi') or ('a'='a and hi") or ("a"="a

我有什么遗漏吗? 我应该使用不同的方法来防止SQL注入吗?

2
这些变量是从哪里来的?你提到跳过登录,这是否意味着这些变量来自于 cookie? - robjmills
变量来自于$_POST并将被发送到函数。成功登录后,我们会写入一个Session-Var。跳过是指在没有有效密码的情况下登录。顺便说一句,感谢您如此迅速的回复。 - wildhaber
1
如果你看到SQL语句是通过字符串拼接而成的,那么应该会听到响亮的警钟声。请尽可能使用绑定参数,例如在PHP中使用PDO和MySQLi库。 - Cheekysoft
7个回答

11

您可以尝试使用参数化查询来查询数据库,这样可以避免 SQL 注入攻击。

我主要使用 postgreSQL,执行此类查询的格式如下:

$query = 'select * from Benutzer where Benutzername = $1 and Passwort = $2';
$params = array($Benutzer, md5($PW));
$results = pg_query_params($query, $params);

大多数数据库都有一个类似于这个功能的函数。

希望这能帮到你,祝好运!

Kyle


1
PDO的工作方式如下。请参见http://fr2.php.net/manual/en/pdostatement.execute.php。 - Aif

5

9
不要使用字符串转义。字符串转义很容易出错,很难正确处理。使用绑定参数。绑定参数通过替代通道发送到数据库中,因此不可能被解析为SQL。 - nobody
5
mysql_real_escape_string() 由 MySQL 服务器执行,我相信 MySQL 的技术人员对此非常熟悉。 - Ryan McCue
或者说,是由MySQL团队制作的PHP中的MySQL库,如果我没记错的话。 - Ryan McCue
谢谢大家 - 我们将在密码中添加一点盐,并使用mysql_real_escape_string()来保护我们在SQL语句中使用的用户输入。 - wildhaber
@Ryan McCue:你可能希望如此,但实际上并不是这样。mysql_real_escape_string()的存在是因为它的前身mysql_escape_string非常糟糕。而且,它仍然是一种有缺陷的方法。 - nobody
MySQL字符串文字转义并不难做对,只是很容易忘记这样做,这就是为什么参数化查询是一件好事的原因。但是Ryan是正确的,转义是正确的概念(无论是显式还是通过参数),而试图嗅探“可能”是注入尝试迹象的“坏”字符串则完全是错误的做法:可笑地不完整,同时也会阻止一些有效的输入。 - bobince


2

如果要保证安全性尽可能高,你应该使用比md5更好的哈希方法,例如sha256。另外,请使用密码盐。


1
他在询问关于SQL注入的问题。 - Pawka
1
是的,那部分已经得到了回答。他还说他想要高安全性 - 所以我免费给了他一些额外的提示。 - gnud

0

尝试使用mysql_real_escape_string()

$strSQL = "SELECT * 
        FROM Benutzer 
        WHERE Benutzername = '".mysql_real_escape_string($Benutzer)."' 
        AND Passwort = '".mysql_real_escape_string(md5($PW))."'";

确保用户注册时使用相同的技术进行注册..例如,

AND Passwort = '".mysql_real_escape_string(md5($PW))."'"

并且

AND Passwort = '".md5(mysql_real_escape_string($PW))."'"

根据输入文本的不同,可能会产生不同的结果。

是的,也要对这个密码加入一些“盐”。以下是一些想法:

sha1(md5($pass)):
sha1($salt.$pass):
sha1($pass.$salt):
sha1($username.$pass):
sha1($username.$pass.$salt):


2
不需要使用 mysql_real_escape_string() 转义密码,因为 MD5 是十六进制数字,不会包含除 0-9 或 A-F 以外的任何字符。 - Ryan McCue
2
不,不要使用字符串转义。请使用绑定参数。 - nobody
2
在特定情况下可能不需要转义,但如果要使用字符串构建,则养成在每个字符串上使用转义的好习惯。关注点分离:你的查询构建器不知道MD5摘要中哪些是有效字符的工作,并且也许将来有人会用可以包含您需要担心的字符的其他内容调用md5。 - bobince

0
安全标准应尽可能高。如果在您的设计中包含了md5,而没有人抬起眉毛或喝咖啡时呛到自己,那么您需要与客户重新审视安全问题。如果安全性至关重要,他们需要为安全专家加入您的团队买单。每个人都说他们想要安全的代码。但愿意为此付费的人很少,所以真正得到安全代码的人也很少。

0

一定要使用strip_tags函数(或者自己编写HTML过滤器)来清除任何公共内容,以防止XSS攻击。


在输出阶段使用htmlspecialchars()是防止XSS攻击的正确方法。 - bobince
除非您想显示一些用户生成的HTML... - Citizen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接