使用数据库级MD5函数是否比应用程序级函数存在更大的安全风险?
我有一段代码可以验证用户的用户名和密码,其内容如下:
$sql = "SELECT *
FROM user
WHERE
username='{$_POST['username']}' AND
password=MD5('{SALT}{$_POST['password']}')";
这比这样做更安全/更不安全吗?
$sql = "SELECT *
FROM user
WHERE
username='{$_POST['username']}' AND
password='".md5(SALT.$_POST['password'])."'";
无论在何处/是否进行转义,第一种方法是否容易受到 SQL 注入攻击?对于除 MySQL 之外的其他数据库引擎,答案是否相同?
I've got a chunk of code that validates a user's username and password, which goes something like this:
$sql = "SELECT *
FROM user
WHERE
username='{$_POST['username']}' AND
password=MD5('{SALT}{$_POST['password']}')";
Is this any more/less secure than doing it like this?
$sql = "SELECT *
FROM user
WHERE
username='{$_POST['username']}' AND
password='".md5(SALT.$_POST['password'])."'";
Regardless of where/if escaping is done, is the first method vulnerable to sql injection attacks? Would the answer be the same for other database engines besides MySQL?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您应该使用准备好的语句和看看这个问题。
You should use prepared statements instead and have a look at this question.
说到注入,如果你正确地转义变量,两种方法都是安全的。
如果您使用完整的查询日志记录,第一种情况将更容易受到攻击,因此密码将显示为纯文本。
此外,如果您的系统受到某种充当脚本和数据库之间代理的病毒的影响,它就能够捕获您的密码。
您可能遇到的最后一个问题(事实上,很少见)是当系统感染病毒时,病毒会从内存中读取敏感数据。
我希望这是有道理的。
Speaking about injection, both ways are secure, if you properly escape variables.
The first case will be more vulnerable, if you use complete query logging, and so the password will appear as plain text.
Besides, if your system is affected by some virus that works as proxy between your script and database, it'll be able to catch your password.
One last problem that you may encounter (quite rarely, in fact), is when the system is inflicted with a virus, that reads sensible data from memory.
I hope this makes sense.
天啊,请告诉我你正在做某种类型的
mysql_escape_string
或mysql_real_escape_string
或至少addslashes
或addcslashes
在将任何$_POST
变量插入原始 MySQL 语句之前?我认为最安全的方法是:
a) 使用
filter_var
或preg_replace
删除 $_POST['username'] 中的无关字符b) < code>SELECT 来自 MySQL 的用户名行(同时获取摘要密码)
c) 将
$_POST
中的密码消息摘要版本与检索到的行的消息摘要版本进行比较(假设你不会在应用程序代码中留下你的密码(明文),而不是在 SQL 语句中如果你这样做,那么只有 1 个可能的注入位置(用户名),并且当你执行
时这是几乎不可能的preg_replace( '/\W/', '', $_POST['username'] )
删除任何非 A-Za-z0-9_- 的内容(或更改为您的用户名白名单字符)。然而,如果你进行了绝对正确的消毒,那么在哪里进行比较并不重要。不过,从理论上讲,我会允许与用户输入和原始 SQL 语句进行尽可能少的交互(即仅通过用户名进行 SELECT 并在数据库外部进行比较)。
Oh god, please tell me you're doing some type of
mysql_escape_string
ormysql_real_escape_string
or AT LEASTaddslashes
oraddcslashes
to any$_POST
variables before you insert them into a raw MySQL statement?I think the most secure way to do this is to:
a) use
filter_var
orpreg_replace
to get rid of extraneous characters from the $_POST['username']b)
SELECT
the row by the username from MySQL (also grabbing the digested password)c) compare the message digested version of the password from the
$_POST
to that of the retrieved row (assuming you don't leave your password cleartext) in your application code, not in the SQL statementIf you do it this way, there's only 1 possible place for injection (username), and it's pretty impossible when you're doing a
preg_replace( '/\W/', '', $_POST['username'] )
which removes anything not A-Za-z0-9_- (or change to your username whitelist of characters).However, if you're doing rock-solid proper sanitization, it really doesn't matter where you do your comparison. Theoretically, though, I'd allow for the least possible interaction with user input and raw SQL statements (i.e. only
SELECT
ing by username and comparing outside of your DB).首先使用 MD5 是为了避免成为不安全的算法,并且永远不应该将其用于密码。您应该使用陈旧的 sha256,并且大多数数据库没有此函数调用。但即使数据库有,我也认为这是一个坏主意。这不是一个坏主意,但最好保留尽可能少的密码副本。通常,数据库可能位于完全不同的计算机上,如果该计算机受到威胁,则攻击者可以通过查看查询来获取明文密码。就 SQL 注入而言,安全性没有区别,从您的查询来看,您应该更担心 SQL 注入。
To start off with MD5 is prevent to be an insecure algorithm and should never be used for passwords. You should use a staled sha256 and most databases do not have this function call. But even if the database did I think its a bad idea. Not a very bad idea, but its best to keep as few copies of your password around. Often the database can be on a completely different machine, and if that machine where compromised then the attacker could obtain clear text passwords by looking at the quires. In terms of SQL Injection, there is no difference in security and judging by your queries you should be more worried about SQL injection.
如果进行适当的转义和清理,则不会发生 SQL 注入
我认为你应该更多地关注执行一项行动而不是另一项行动所花费的费用。在其他条件相同的情况下,第一种方法的执行时间比第二种方法要少。
SQL injection will not occur if proper escaping and sanitizing takes place
I think you should look more at the expense taken to perform one action over another. The first method would take less time to execute than the second method, ceteris paribus.