我用非常简单的 php 代码构建了几个网站,到目前为止一切顺利,但我碰巧现在担心主题“安全”我想知道在 PHP 中创建登录/身份验证过程的最佳方法是什么,
这就是我的方法目前所做的:
在注册过程中,用户提交电子邮件和密码
密码将作为 md5 字符串存储在 mysql 中,因此除了用户之外的任何人都知道它。
当用户登录时,
SELECT * FROM usertable WHERE email = $emailsubmitted AND pass = md5($passsubmitted)
如果结果数组的大小大于零,则意味着用户存在,
因此我设置
session_start();
$_SESSION['logged'] = 'true';
$_SESSION[userid] = userid;
为用户浏览的每个页面,我将执行检查以查看会话变量是否存在。
底线:我想知道这是否足够安全以及如何改进。
i built several sites with very simple code of php and so far so good, but i happens that I'm now worried about topic "security" i wonder what is the best way to create a login/authentication process in PHP
this is what I currently do:
during registration the user submit an email and a password
the password will be stored, in mysql, as an md5 string, so anybody but the user knows it.
when the user login, i do
SELECT * FROM usertable WHERE email = $emailsubmitted AND pass = md5($passsubmitted)
then if the sizeof the resulting array is more then zero, it means the user exists
so I set
session_start();
$_SESSION['logged'] = 'true';
$_SESSION[userid] = userid;
so for everypage the user browse i'll perform a check to see if the session variable exists.
BOTTOM LINE: I wonder if this is safe enough and how it can be improved.
发布评论
评论(4)
您的 SQL 语句存在注入漏洞。 (这是假设“已提交”后缀意味着该变量尚未对其进行任何过滤。)如果恶意用户要提交
'[电子邮件受保护]' AND 1=1;--
作为电子邮件地址,他们可以使用“[电子邮件受保护]",无论密码如何。我建议保护 SQL 的输入和/或使用存储过程。我还建议仅加载您绝对需要的列;它将提高查询速度并允许更少的状态在数据库外部暂停。此外,对密码进行加盐处理。如果有人要从数据库中检索用户的数据,密码将很容易成为暴力破解和字典攻击(如彩虹表)的目标。如果您真的很偏执,请考虑从 MD5 切换到 SHA 或其他哈希函数。
确保在
php.ini
文件中设置了哪些变量,并将它们设置为您期望的值。根据这些设置,对$_SESSION
的数组分配也是不安全的。一些旧的 Web 应用程序利用 PHP“功能”,使查询字符串中的变量成为 Web 应用程序中的全局变量,这意味着当执行 $_SESSION['userid'] = $userid; 时,如果恶意用户将?userid=1
附加到其查询字符串中,他们将成为用户 ID 为 1 的用户,这通常是第一个用户(或管理员)。Your SQL statement has an injection vulnerability in it. (This is under the assumption that the "submitted" suffix means the variable hasn't had any filtering done on it.) If a malicious user were to submit
'[email protected]' AND 1=1;--
as an email address, they could log in with the credentials of "[email protected]", irrespective of the password. I'd suggest to secure the input to the SQL and/or use stored procedures. I'd also suggest loading only the columns that you absolutely need; it will improve the speed of the query and allow less state to be held in suspension outside of the database.Additionally, implement salting on the password. If someone were to retrieve the user's data from the database, the passwords would be an easy target for bruteforce and dictionary attacks (like rainbow tables). If you're really paranoid, consider switching from MD5 to SHA or another hashing function.
Make sure of which variables are set in your
php.ini
file and that they are set to values you expect. Depending on those settings, the array assignment to$_SESSION
is also insecure. Some old web applications utilized a PHP 'feature' which made variables in the query string become global variables in the web application, which meant that when it executed$_SESSION['userid'] = $userid;
, if a malicious user attached?userid=1
to their query string, they would become the user with the user ID of 1, which often was the first user (or administrator).总体逻辑是可以的,是的。然而,简单的密码md5并不好。
不对密码加盐会使哈希对彩虹表查找开放。
md5 通常不被认为是一种好的密码哈希机制。我鼓励您查看 http://www.openwall.com/phpass/
Side-注意:您的 SQL似乎对 SQL 注入开放。
The general logic is ok, yes. However, A simple md5 of the password is not good.
Not salting the password leaves the hash open to rainbow table lookups.
md5 is generally not considered a good hashing mechanism for passwords. I encourage you to take a look at http://www.openwall.com/phpass/
Side-note: Your SQL appears to be open to SQL injection.
除了前面提到的 SQL 注入之外,我建议您不要检查数组是否大于零,而是检查数组是否等于 1。
原因是,假设有人修改了您的数据库,只是运行一个简单的查询来清除所有密码或将它们设置为特定条目,然后检查是否等于 1 将阻止这种情况。
另外,假设多个用户具有相同的密码,并且他们以某种方式 SQL 注入用户名,或者您忘记检查用户名,那么您将再次安全地检查等于 1。
归根结底,这是一件小事,但在安全方面,每一点都很重要。
On top of the previously mentioned SQL injections I would recommend that you not check if the array is greater than zero, but instead if the array is equal to one.
The reason is that let's say somebody does modify your database and just runs a simple query to clear all of the passwords or set them to a specific entry, then checking for equal to one would stop that.
Also, let's say multiple users have the same password and they somehow SQL inject the username or you forget to check the username, then once again you will be safe with checking equal to one.
Ultimately, it is a minor thing, but when it comes to security every little bit counts.
我注意到的第一件事是您将 MD5 哈希应用于 php 变量。
这让我认为密码在频道上是清晰的。
您应该在 js 中应用 MD5 哈希客户端,这里是一个示例:
http://phpjs.org/functions/md5 /
如果您想添加另一层安全性,除了标准哈希之外,您还应该考虑使用盐。这将使您免受任何字典攻击或反向攻击(请参阅:http://tools.benramsey.com/md5 /)
The first thing i note is that you apply the MD5 hash to a php variable.
That makes me think the password travels clear on the channel.
You should apply the MD5 Hash client-side with js here an example:
http://phpjs.org/functions/md5/
If you want to add another layer of security you should also consider using a salt in addition to the standard hash. This will shield you from any dictyonary attack or reverse hasing (see this: http://tools.benramsey.com/md5/)