2011-11-21 43 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而不是<?