2012-04-02 98 views
2

我一直在想,也許我的登錄系統並不像我想的那樣安全。首先,我要用口頭向你解釋我在做什麼。密碼「鹽」 - 我做對了嗎?

當用戶註冊時,會生成16個字符的鹽。 我的鹽儲存在一個字段中的數據庫稱爲「鹽」 我存儲哈希密碼+鹽(它們被散列一起hash("sha256", $salt.$password);)在一個被稱爲「密碼」域

當用戶試圖登錄,我從數據庫中獲取「密碼」字段和「鹽」字段以及其他一些內容。

要檢查,如果他們進入他們的密碼正確,我這樣做:

$hashed = hash("sha256", $row['salt'].$pass); 
if ($row['password'] == $hashed) { 
//success 

($行是從數據庫$行[「鹽」]所取得的數組是在數據庫中,$鹽pass是他們輸入的密碼,而$ row [「password」]是數據庫中的哈希合格+ salt)

我在想,它在我看來,我的鹽提供很少(或沒有)所有。我向你們提出的所有問題僅僅是:我的方法是否提供了額外的安全性(或者它甚至可以保護所有安全嗎?)

另外,我還有第二個'問題'。我想驗證這個「檢查登錄」腳本不能被欺騙/欺騙,以便在沒有他們的密碼的情況下進入某人的賬戶。

session_start(); 
require_once 'db_connect.php'; 
//If the session variable "id" isn't set (i.e. they aren't logged in) 
if (!isset($_SESSION['id'])) { 
    //Check if they wanted to be "remembered" (so they have 2 cookies 
    if (isset($_COOKIE['rem_user']) && isset($_COOKIE['rem_pass'])) 
    { 
     $query = "SELECT 
         id, 
         password, 
         auth, 
         email, 
         username 
        FROM users 
        WHERE 
         username='".$_COOKIE['rem_user']."' 
        AND active IS NULL" 
     $res = mysql_query($query); 
     if (mysql_num_rows($res) == 1) 
     { 
      $row = mysql_fetch_array($res); 
      // If the "remember me" cookie containing their password 
      // is equal to the one in the database, log them back in. 
      if ($_COOKIE['rem_pass'] == $row['password']) 
      { 
       $_SESSION['id'] = $row['id']; 
       $_SESSION['username'] = $row['username']; 
       $_SESSION['auth'] = $row['auth']; 
       $_SESSION['email'] = $row['email']; 
       $logged_in = 1; 
      } 
     } 
    } 
    else 
     $logged_in = 0; 
} 
else 
    //Since the session variable "id" WAS set, they ARE logged in. 
    $logged_in = 1; 

我認爲,只有這樣,才能就是登錄...

  1. 欺騙,我不認爲這是可能的,而不服務器訪問
  2. 欺騙帶有cookie的會話變量加密的密碼+ salt,我相信這幾乎不可能訪問數據庫。

反饋將不勝感激。我想確保我的系統是安全的。 :)

謝謝!

+0

如果你自己在做:不,它是*不*正確的:)好吧,這有點sn,,但這個同樣的問題不斷出現在不同的形式,並展示了許多問題,自己的安全。 – 2012-04-02 23:55:05

+3

如果攻擊者獲得了直接訪問數據庫的權限,他們將無法使用預先生成的彩虹表(或類似)來查找與密碼哈希值相沖突的問題,從而爲您提供安全性。 – 2012-04-02 23:55:39

+0

pst,怎麼樣?什麼會更好? o3o @Oli Charlesworth好的,這很有道理,但是鹽是用來做什麼的?我一直認爲會有更多的安全性。 – fruitcup 2012-04-02 23:57:33

回答

6

好吧,在這裏它... 不要 roll-your-own安全。這裏有一些與上面的問題:

  1. 散列密碼存儲爲cookie。 這是沒有不同然後存儲/通過一個平文文本密碼,因爲它被驗證爲沒有應用散列函數功能。

  2. 該cookie是一個SQL注入攻擊向量。

  3. 使用SHx進行散列。 (使用bcrypt,scrypt,hmac等)

然後我停下來看。 #1顯示這應該留給現有的經過測試/審查的圖書館。

+0

1.只有當用戶選中「記住我」時,纔會存儲Cookie,我認爲他們會使用它「自負風險」。這是不正確的?好的,很好。 :D 3.沙有什麼問題? – fruitcup 2012-04-03 00:01:31

+2

要擴大#1,如果我要嗅探您的用戶和您的網站之間的會話,並且他們選擇了記住我的Cookie,我現在擁有了他們的用戶名和散列的密碼,因此我可以構建一個相同的cookie併成爲自動以他們的身份登錄。除此之外,沒有安全檢查來確保具有有效cookie的人實際上是原始cookie的擁有者。 – drew010 2012-04-03 00:02:39

+2

爲了記住我的功能,您不應該將自己的密碼存儲爲cookie。相反,生成一個GUID並將其保存爲cookie並將其添加到數據庫。當用戶顯式註銷時,從數據庫中刪除GUID。此外,這允許您通過刪除相應的身份驗證令牌來允許用戶註銷其他可能會登錄的會話。 – xbonez 2012-04-03 00:03:04

1

使用hash_hmac

我用這樣的:hash_hmac($算法中,$密碼$鹽,$ siteKey);

即使攻擊者進入了您的數據庫,他們仍然需要您的sitekey才能成功進行暴力破解,但我不會對衝突發表評論。選擇你的算法/毒藥。 :D

+0

機會是,如果黑客能夠訪問他們可以訪問其中$ siteKey所在的代碼庫。 – 2012-04-03 00:02:24

+1

@MikePurcell使用siteKey的想法是 - 希望 - 它存儲在一個單獨的*「硬化」位置(例如*不是*代碼和*不是*數據庫)。我不確定PHP中有什麼支持,但是在ASP.NET中,它將來自web.config的加密部分。將調用'hash_hmac'(從而可以訪問'$ siteKey')的代碼移動到「加固」位置/庫可能會減少PHP中的篡改(我不使用PHP)。無論如何,我希望HMAC更受僱於*額外*措施,因爲它實際上是一項「免費」操作。 – 2012-04-03 00:09:19

+0

@pst:有趣的是,$ siteKey在這種情況下有意義,我認爲這是常見的做法? – 2012-04-03 00:11:47

1

醃製給你額外的安全嗎?是。如果哈希被破壞,你需要更多的資源來破解密碼,因爲鹽會增加很多組合。所以現在你不能用傳統的老傳統攻擊。在哪裏存放鹽是不同的問題。黑客通常會如何檢索哈希?通過妥協數據庫。如果數據庫受到損害,那麼他也會產生使鹽分效率降低的鹽分。但是如果鹽在腳本中被硬編碼,那麼妥協數據庫將不會產生效果。所以我會強烈考慮在腳本中使用硬編碼鹽或使用兩種鹽 - 硬編碼或數據庫。

第二個問題。不要在cookie中存儲密碼。您可以非常輕鬆地僞裝它們(即使在Chrome高級設置中也是如此)。或者竊取它們(例如XSS漏洞)。將它們存儲在會話中。

+2

如果每個密碼都使用相同的鹽,那麼它的安全性就會降低,因爲如果鹽也受到危害,我可以用鹽進行一次蠻力攻擊以查找所有用戶密碼,而不是一個用戶密碼。因此,您應該爲每個密碼/用戶使用獨特的salt。否則,我認爲答案已經很好地陳述和解釋了。 – drew010 2012-04-03 00:04:16

+0

(和借調什麼drew010說:鹽應該是*大*隨機值的OP表示它是一個[隨機] 16個字符的鹽,每新條目,這應該是足夠了,但較大的鹽很便宜。 ) – 2012-04-03 00:07:04

+0

@ drew010所以salt應該使用一種算法,爲每個用戶創建一個獨特的(或接近唯一的)salt,並且這個salt不應該存儲在數據庫中,而是每次檢查密碼時都會'計算'? – fruitcup 2012-04-03 00:07:20