我目前正在测试我制作的简单登录系统。该脚本的作用是检查我输入的用户名和密码与我的数据库中的用户名和密码,如果它们都匹配,则将用户名设置为会话变量。当我转到“仅限会员”页面时,它将检查会话变量是否存在,如果它不存在,则用户无法查看内容。它似乎按预期工作。根据以上信息,以下是我的问题:
我的方法有哪些漏洞/漏洞?
Cookie可以让它更安全吗?如果是这样,它与我的代码有什么关系呢?
到目前为止,这是我正在使用的内容:
用户名和密码检查:
<?
session_start();
$username = $_POST['username'];
$password = $_POST['password'];
if ($username && $password){
$query = mysql_query("SELECT * FROM user WHERE username='$username' ");
$numrows = mysql_num_rows($query);
//if user exists
if ($numrows !=0){
while ($row = mysql_fetch_array($query)){
$dbusername = $row['username'];
$dbpassword = $row['password'];
}
if ($username == $dbusername && md5($password) == $dbpassword){
echo 'You\'re in! <a href="member.php">Click</a> here to enter the member page.';
$_SESSION['username'] = $dbusername;
}
else
echo "incorrect password!";
}
else
die("sorry, that user doesn't exist!");
}
?>
仅限会员页面:
<?
session_start();
if ($_SESSION['username']){
echo "Welcome, ".$_SESSION['username']."!<br>
<a href='changepassword.php'>Change password</a>
";
}
else{
echo "please log in";
}
?>
答案 0 :(得分:5)
目前最大的安全问题是SQL注入,这是当前脚本中的一个重大缺陷。任何人都可以使用您发布的脚本在没有任何凭据的情况下登录。改变这一行:
$username = $_POST['username'];
看起来像:
$username = mysql_real_escape_string($_POST['username']);
就cookie而言,会话使用cookie,因此您已经在使用它们。其次,你放入cookie的任何内容都会通过网络传输,因此它们不安全。
其他可能很好的安全措施是使用bcrypt或至少使用sha2变体,而不是使用md5进行散列密码。
最好在通过网络发送密码之前使用javascript对密码进行哈希处理,如果您不使用SSL,这一点非常重要。
那会让你开始。在您处理这些问题之后,您可以继续进行CSRF和会话劫持攻击。
答案 1 :(得分:1)
我建议您使用PHP的PDO类来查询,原因有很多:
mysql_query()
,mysql_numrows()
等。因此,使用PDO,您的代码将是这样的:
<?php
session_start();
$db = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME, DB_USER, DB_PASS);
$username = $_POST['username'];
$password = $_POST['password'];
if ($username && $password){
$query = $db->prepare("SELECT * FROM user WHERE username = :usr");
$query->execute(array('usr' => $username));
$numrows = $query->rowCount();
//if user exists
if ($numrows !=0){
while ($row = $query->fetch()){
$dbusername = $row['username'];
$dbpassword = $row['password'];
}
if ($username == $dbusername && md5($password) == $dbpassword){
echo 'You\'re in! <a href="member.php">Click</a> here to enter the member page.';
$_SESSION['username'] = $dbusername;
}
else
echo "incorrect password!";
}
else
die("sorry, that user doesn't exist!");
}
?>
方法prepare()
可防止SQL注入。 execute()
后需要prepare()
,但您可以使用query()
方法而不execute()
。
fetch()
方法相当于mysql_fetch_array()
。
以下是PDO文档:http://www.php.net/manual/en/book.pdo.php
希望我帮助过。
注意:我更喜欢<?php
而不是<?
。