2015-11-03 147 views
2

我想寫一個註冊腳本,用戶應該激活他的電子郵件。 所以我有activate.php用activate.php激活電子郵件

邏輯在改變md5 hash1activated colomn。所以用戶可以登錄後。

但是即使我嘗試用正確的md5 hash我的頁面激活說Wrong activation code.

我看不出什麼錯,沒有數據庫的問題。我檢查了十次。

有沒有人可以幫我一把嗎?

activate.php

<?php require_once('config.php'); 
try { 
    $handler = new PDO('mysql:host='. DB_HOST .';dbname='. DB_NAME . ';charset=utf8', DB_USER, DB_PASS); 
    $handler->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
} catch (PDOException $e) { 
    echo $e->getMessage(); 
    die(); 
} 

//The Activation key will always be 32 since it is MD5 Hash 
if (isset($_GET['key']) && (strlen($_GET['key']) == 32)) 
{ $key = $_GET['key']; } 

    $search = $handler->query("SELECT activated FROM members WHERE activated='$key'"); 
    $match = $search->fetchColumn(); 

    if($match > 0){ 

// Update the database to set the "activation" field to 1 

$result = $handler->query("UPDATE members SET activated = 1 WHERE activated='$key' LIMIT 1"); 

     if($result){ 
      echo "Activated";  
     } 

     else{ 
      echo "database problem."; 
     } 

} 
     elseif($match == 0){ 
      echo "Wrong activation code."; 
     } 

?> 

當我訪問activate.php??key=d85516205a57dcf1cfd228c19e3f3effActivated但是,它的Wrong activation code.

我在哪裏錯了?

+2

您可以[** SQL注入**](https://www.owasp.org/index.php/SQL_Injection)。如果URL是'activate.php?key = x'%20or%201 =%20 - '(即'key'是'x'或1 = 1 --')這將激活每個用戶。這只是一個例子。你需要使用準備好的語句。 –

+0

謝謝埃德,我試過了,但沒有按照你的想法工作。這是我得到的結果。 '致命錯誤:帶有消息'SQLSTATE [42000]的未捕獲異常'PDOException':語法錯誤或訪問衝突' – Lukasz

+0

其實,我有一點錯字;攻擊者需要在密鑰的末尾添加一個空格('activate.php?key = x'%20or%201 = 1%20 - %20')。我原來的評論中的例子將導致包含' - ''和'--LIMIT 1'的查詢,這會引發語法錯誤。用空格(' - ''和' - LIMIT 1')他們不會。關鍵是這個代碼可以用一個非常明顯的方式來利用;如果你把它放在野外,它將會被利用。 –

回答

2

安全第一。

使用PDO預準備語句來避免SQL注入。

試試這個代碼,讓我們看看它是否會工作。

<?php require_once('config.php'); 
try { 
    $handler = new PDO('mysql:host='. DB_HOST .';dbname='. DB_NAME . ';charset=utf8', DB_USER, DB_PASS); 
    $handler->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
} catch (PDOException $e) { 
    echo $e->getMessage(); 
    die(); 
} 

//collect value from the url 
$key = trim($_GET['key']); 

//if key is set, not empty and 32 characters. 
if(isset($key) && !empty($key) && (strlen($key) == 32)){ 

    //update users record set the activated column to "1" where the key value match the one provided in url 
    $stmt = $handler->prepare("UPDATE members SET activated = '1' WHERE activated = :key LIMIT 1"); 
    $stmt->execute(array(
     ':key' => $key 
    )); 

    //if the row was updated redirect the user 
    if($stmt->rowCount() == 1){ 

     //good news 
     echo "Your account is activated."; 
     exit; 

    } else { 
     echo "Your account could not be activated."; 
    } 

} else { 
    echo "We need right code to confirm your membership."; 
} 
?> 
+0

它工作完美。非常感謝你。它看起來也對埃德安全:) – Lukasz