我有一大堆代码可以验证用户的用户名和密码,如下所示:
$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之外,其他数据库引擎的答案是否相同?
答案 0 :(得分:3)
您应该使用预备语句而不是和查看this question。
答案 1 :(得分:2)
谈到注射,如果你正确地逃避变量,两种方式都是安全的。
如果您使用完整的查询记录,第一种情况将更容易受到攻击,因此密码将显示为纯文本。
此外,如果您的系统受到某些在您的脚本和数据库之间作为代理的病毒的影响,它将能够捕获您的密码。
您可能遇到的最后一个问题(实际上很少发生)是系统受到病毒感染,从内存中读取合理数据。
我希望这是有道理的。
答案 2 :(得分:1)
天啊,请告诉我你正在对任何mysql_escape_string
变量进行某种mysql_real_escape_string
或addslashes
或至少addcslashes
或$_POST
< strong>在之前将它们插入到原始的MySQL语句中?
我认为最安全的方法是:
a)使用filter_var
或preg_replace
摆脱$ _POST ['username']中的无关字符
b)SELECT
来自MySQL的用户名行(也抓取消化的密码)
c)将来自$_POST
的密码的消息消化版本与检索到的行的密码消息(假设您没有将密码保留为明文)在应用程序代码中进行比较,而不是在SQL语句中
如果你这样做的话,只有一个可能的注射位置(用户名),当你做preg_replace( '/\W/', '', $_POST['username'] )
去除任何不是A-Za-z0-9_-的东西时,这是非常不可能的(或者更改为您的用户名白名单。)
然而,如果你正在进行坚如磐石的正确消毒,那么你在哪里进行比较并不重要。但从理论上讲,我允许尽可能少地与用户输入和原始SQL语句进行交互(即只有SELECT
用户名并比较数据库外部。)
答案 3 :(得分:1)
从MD5开始是防止成为不安全的算法,不应该用于密码。您应该使用staled sha256,并且大多数数据库都没有此函数调用。但即使数据库确实存在,我认为这是一个坏主意。这不是一个非常糟糕的主意,但最好保留密码副本。通常,数据库可以位于完全不同的计算机上,如果该计算机受到攻击,则攻击者可以通过查看quires来获取明文密码。在SQL注入方面,安全性和判断没有区别,你应该更担心SQL注入。
答案 4 :(得分:0)
无论在何处/如果进行转义,第一种方法是否容易受到sql注入攻击?
如果正确进行转义和清理,则不会发生SQL注入
除了MySQL之外,其他数据库引擎的答案是否相同?
我认为你应该更多地考虑执行一项行动而不是另一项行动的费用。第一种方法比第二种方法(ceteris paribus)花费的时间更少。