php
  • mysql
  • email
  • 2011-06-17 97 views 2 likes 
    2

    我有一個頁面來激活點擊我發送的電子郵件中的激活鏈接的用戶,該電子郵件包含一個使用GET方法在那裏發送電子郵件地址的URL,我的代碼如下,但是我要求的是這是一種安全的方法或者有沒有什麼方法可以得到保護?謝謝安全的PHP查詢?

    $username = $_GET['email']; 
    
    mysql_query("UPDATE users SET active = 'yes' 
    WHERE email = '$username'") or die('oops!'); 
    
    echo "<meta http-equiv=\"refresh\" content=\"0;URL=/index.php?msg=active\">"; 
    
    +4

    打電話給我[Bobby Tables](http://xkcd.com/327/)。或者使用[PDO](http://stackoverflow.com/questions/6379433/mysql-prepared-statements)。 –

    +0

    另外檢查準備好的聲明:http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html – Phil

    +1

    潛在的最終破壞。至少使用mysql_real_escape_string。我打算以此作爲答案,但十億人已經說過同樣的話。在將其發送到數據庫之前始終驗證您的輸入。 – stephenbayer

    回答

    4

    考慮的$ _GET以下值[ '電子郵件']:

    "'; DELETE FROM users WHERE 1 or username = ''" 
    

    如果用戶提交了這個值,你的腳本將執行下面的SQL語句:

    UPDATE users SET active = 'yes' WHERE email = ''; DELETE FROM users WHERE 1 or username = ''" 
    

    您需要過濾輸入以刪除在SQL設置中具有含義的字符(本例中爲\)。

    通過使用PDO預處理語句或使用mysql_real_escape_string()進行篩選,可以幫助確保查詢的安全。

    此外,您希望創建一個唯一的,不可猜測的值發送給用戶,並期望從$ _GET返回該值。如果您允許用戶提供純文本電子郵件地址,惡意用戶可以激活任意電子郵件地址。 md5()或其他散列函數可用於創建唯一值。

    +3

    雖然這篇文章的一些想法是正確的,但是mysql在一次調用'mysql_query()'的時候實際上不能執行多個語句。SQL注入仍然是一個漏洞,但攻擊者實際上無法從更新語句中刪除所有用戶。 –

    2

    不,這很容易受到SQL注入的影響。我可以在$_GET['email']中放置'並運行我喜歡的任何查詢。

    3

    這並非完全安全。你需要調用mysql_real_escape_string()$username

    $username = mysql_real_escape_string($_GET['email']); 
    

    更好的辦法是使用PDO並通過prepared statement傳遞變量。

    2

    這絕對不是安全的。您需要通過mysql_real_escape_string轉義任何有潛在危險的人物(想想如果有人在他們的電子郵件地址中輸入了'''')。

    2

    這是不安全的。您應該使用存儲過程,或escape the sql

    5

    這不是激活電子郵件的最佳方法。任何人都可以使用假電子郵件註冊並創建自己的GET請求來激活它。你應該使用一個唯一的散列,而不能被猜到。另外,你需要用mysql_real_escape_string轉義你的SQL語句。

    5
    +0

    謝謝,請問爲什麼我應該忘記mysql_real_escape_string? – Liam

    +0

    @Liam看我的編輯。基本上,你必須**總是**記得逃避**一切。** –

    +0

    非常感謝@matt,感謝它! – Liam

    2

    想象一下,我想要做的事對惡意網站的你,現在假設我操縱您的網址,並更改[email protected].php?email=1';SHOW TABLES或者甚至.php?email=1';DROP TABLE USERS;這不會是很漂亮不是嗎?

    防止這種最簡單的方式是包裝所有的輸入值的功能mysql_real_escape_string,這將使您的查詢是這樣的: mysql_query("UPDATE users SET active = 'yes' WHERE email = '" . mysql_real_escape_string($username) .'") or die('oops!');

    我想向你介紹我的朋友鮑比表(From XKCD): enter image description here

    +0

    Thankyou,我很高興我問 – Liam

    0

    雖然大家都在說,在查詢中使用它之前逃避你的字符串是絕對必要的,但我認爲還有更多需要關注的東西。

    這仍然允許非用戶嘗試不同的電子郵件地址,看看會有什麼結果。

    我推薦加密電子郵件,並在URL中使用加密版本的電子郵件。

    所以,當你向他們發送的鏈接:

    $enc_key = 'SOME KEY I USE'; 
    $email = mysql_real_escape_string($email); 
    $result = $db->query("SELECT AES_ENCRYPT('$email', '$enc_key') as email"); 
    $enc_email = mysql_fetch_assoc($result); 
    $enc_email = $enc_email['email']; 
    $url = "http://www.example.com/confirm.html?key=$enc_email"; 
    

    然後檢查是否有用戶在確認您:

    $enc_key = 'SOME KEY I USE'; 
    $enc_email = mysql_real_escape_string($_GET['key']); 
    $result = $db->query("UPDATE users SET active = 1 WHERE AES_ENCRYPT(email, '$enc_key') = '$enc_email'"); 
    
    1
    從其他人提到的SQL注入問題

    除此之外,你有人們能夠僞造自己的激活鏈接並繞過接收電子郵件的需要的問題。

    一個常見的解決方案是在激活之前檢查的URL中包含某種散列值。

    例如 -

    創建激活表。當用戶註冊時,插入電子郵件地址(或其他唯一標識符)和一些非常量的祕密值。這可能是一個隨機數,時間戳和鹽,或類似的。

    當您爲電子郵件生成鏈接時,請包含散列值,該散列值是通過散列電子郵件地址和祕密值而獲得的。

    然後,當用戶點擊鏈接時,您可以從URL中獲取電子郵件地址,使用數據庫中的值對其進行哈希處理,並查看它是否與URL中的哈希匹配。

    這會讓別人僞造激活鏈接變得更難。

    相關問題