2011-11-21 56 views
0

我目前正在测试一个简单的登录系统。脚本所做的是检查我输入的用户名和密码以及我的数据库中输入的用户名和密码,如果它们都匹配,则会将用户名设置为会话变量。当我转到“仅限会员”页面时,它将检查会话变量是否存在,如果不存在,则用户无法查看内容。它似乎按预期工作。基于以上信息,这里是我的问题:我可以用cookie改进我的PHP登录系统吗?

  1. 我的方法有哪些漏洞/缺陷?

  2. 饼干可以使它更安全吗?如果是这样,它将如何与我的代码相关?

这里就是我有这么远的工作:

的用户名和密码检查:

<? 
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

1)巨大的脆弱性:SQL注入! 2)md5有更好的选择(比如sha1()或者甚至更好,bcrypt)3)Cookies不会使任何事情更安全(如果有的话,相反); 4)也要注意XSS攻击 –

回答

5

目前最大的安全问题是SQL注入是当前脚本中的一个巨大缺陷。任何人都可以在没有任何凭证的情况下登录您发布的脚本。改变这一行:

$username = $_POST['username']; 

的样子:

$username = mysql_real_escape_string($_POST['username']); 

至于饼干去,会话使用cookie,那么您已经在使用它们。其次,任何你放入cookie的东西都会通过电线传输,所以它们不安全。

其他的安全措施是好的,就是使用bcrypt或至少一个sha2变体,而不是md5来散列密码。

在通过电线发送密码之前,最好使用JavaScript对密码进行哈希处理,如果您不使用SSL,这一点非常重要。

这会让你开始。在您处理这些问题后,您可以转到CSRF和会话劫持攻击。

1

我建议您使用PDO类PHP的为您查询,原因是多方面的:如果你改变你的DBMS

  • ,你就不必编辑所有mysql_query()mysql_numrows()
  • 出于安全原因,因为PDO有一些预先集成的功能来防止安全问题。
  • ...

因此,与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注入阻止。 prepare()之后需要​​,但是您可以使用方法query()而不使用​​。

fetch()方法相当于mysql_fetch_array()

这里是PDO DOC:http://www.php.net/manual/en/book.pdo.php

希望我帮助。

注:我更喜欢<?php而不是<?