2009-03-05 112 views
4

在過去的幾天裏它一直在我的腦海中運行,但我閱讀了一些關於如何讓PHP會話更安全的文章。幾乎所有這些文章都表示,您需要在會話中使用額外的salt來保存useragent。類似這樣的:PHP Sessions + Useragent with salt

$fingerprint = md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']); 

鹽會讓攻擊者更難以劫持或任何會話。但是,爲什麼每次添加鹽,你會檢查它是這樣的:

md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']) == $_SESSION [ 'fingerprint' ] 

那麼,爲什麼鹽使其更加安全,因爲攻擊者仍然只需要用戶代理(這是relativly一小套不同useragents的)和sessionid?

也許小東西我俯瞰,但無法弄清楚,我逼瘋了,哈哈

謝謝!

回答

0

我也這樣做到partially protect from session impersonation attacks。您還需要包含IP地址。

請記住,當客戶端的瀏覽器會自動更新用戶代理的改變,你會認爲他的會議已被劫持;)

+0

包括會話指紋中的IP地址是不好的,因爲它會阻止用戶合法更改IP地址,例如斷開 – Guss 2009-03-05 21:40:29

+0

@Guss的DSL線路:發生這種情況時(或用戶代理的瀏覽器自動更新時),則I會話失效。沒什麼大不了的,用戶必須重新登錄。 – cherouvim 2009-03-05 21:42:51

0

由於指紋存儲在服務器端,你不需要使用鹽醃散列。 「正常」散列足以減少數據。

+0

salt = good:D看到我的回答 – Mez 2009-03-05 21:27:52

+0

花了我一會兒才輸入:D – Mez 2009-03-05 21:48:01

+0

鹽沒用,看我的評論給你的回答。 – Guss 2009-03-05 21:53:08

0

請記住,如果你這樣做,你迫使人們再次登錄,如果他們升級他們的瀏覽器。這可以,但確保它是你的意圖。

使用用戶的遠程地址也不是沒有問題。許多人使用來自不同地點的同一臺計算機。移動設備,在家中和工作中使用的筆記本電腦,在Wifi熱點中使用的筆記本電腦等。恕我直言,這是一個壞主意,以這樣的方式使用IP地址,新的IP地址需要登錄,除非你處理高度敏感的信息如網上銀行。是這樣嗎?

您關心什麼?外部攻擊?或者在共享主機的情況下,有人可以閱讀您的會話信息?

如果是後者,解決方案很簡單:只是不要在會話中存儲任何敏感內容。任何敏感的東西都應該存儲在數據庫中。

就創建祕密鹽而言,您需要使用不可猜測的東西。我會去創建一個像創建用戶時創建的隨機字符串。如果有必要,每次會話失效時重新創建它。

至於什麼使它更安全,你自己說:有限的用戶代理字符串(少於100個可能會覆蓋99.99%的用戶)。鹽只是增加了可能性的數量。話雖如此,如果你在所有會議中使用相同的鹽,那麼在蠻力中發現它只是一個時間問題。

7

建議添加鹽的原因很簡單。一般來說,當你創建這個「指紋」時 - 如果你只使用一個有限數據集的數據項,那麼它會使外部黑客更容易產生這個數據,並劫持會話。

在上例中,如果攻擊者同時擁有「指紋」和用戶代理,則他們將能夠劫持會話。

加入鹽只能使得攻擊者更難生成指紋,它是:「如果他們都只有一個資料片,那麼信息的最後一塊毫無用處)

我的情況下, d建議你在vBulletin(一個我曾經使用過的項目)中添加更多的東西,會話ID散列(基本上與指紋相同)用下面的代碼生成:

define('SESSION_IDHASH', md5($_SERVER['HTTP_USER_AGENT'] . $this->fetch_substr_ip($registry->alt_ip))); // this should *never* change during a session 

此外,會話哈希使用

md5(uniqid(microtime(), true)); 

這些都是當試圖

所以識別會話,劫持會話時,人會需要知道服務器上的以下

  • 的時間(精確地)託運時創建會話是
  • 用戶的瀏覽器代理字符串
  • 用戶的IP地址

他們也必須欺騙IP地址(或至少前2/3個八位字節)才能做到這一點。

如果他們確實處於能夠獲得上述信息的地步,那麼他們可能會以其他方式進行攻擊,而不僅僅是會話劫持。 vBulletin實際上並沒有使用「salt」本身,但在上面的例子中,鹽只是添加了有限的熵,最好總能找到儘可能多的熵。

例如,在我正在用python編寫的東西中,我使用XSRF保護生成哈希值。以下是我使用的。

self.key = sha1(
     self.user.username + 
     self.user.password + 
     settings.SECRET_KEY + 
     strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime()) 
    ).hexdigest() 

這取用戶的用戶名和密碼,當前時間,以及預設的鹽來生成這個。對於攻擊者而言,由於鹽和時間的緣故,攻擊者很難生成(儘管如此,請注意,只有在它被使用後纔會發生變化,隨着時間的推移,如果它沒有改變,爲特定用戶破解這個)

2

如果我理解正確,你想阻止遠程攻擊者會話劫持,猜測會話ID?

如果情況並非如此,那麼你就深深地陷入了困境 - 一個可以窺探流量的攻擊者也可以模仿用戶代理,而一個攻擊者可以獲得對會話存儲的訪問權限。

如果存儲用戶代理字符串以將會話「鎖定」到當前用戶代理,那麼對它進行散列確實毫無意義 - 對完整用戶代理字符串的字符串比較更快(然後散列和比較)並且在存儲方面不會更昂貴。

我不認爲存儲用戶代理正在提供足夠的區別 - 更好的做法是在會話開始時生成更大的ID(可能包含更多位)(可能是當前時間戳+用戶名+用戶代理+然後將其存儲在cookie中以及會話中,並在每個附加請求上進行匹配。這並沒有太多的改變攻擊向量(你仍然需要猜測一些數字),但是通過大量增加攻擊的難度,它很容易顯着增加必須爲成功攻擊而猜測的比特數。

0

好了,例如我用下面的代碼虛構:

<?php 

// The sessionid cookie is now a certain hash 
if (array_key_exists ($_COOKIE [ 'sessionid' ])) 
{ 
    // Get the session from database 
    $db_sessid = $pdo -> getStuff ('session_database', $_COOKIE [ 'sessionid' ]); 

    if ($db_sessid !== null && $db_sessid [ 'fingerprint' ] == sha1 ('SOMESALT' . $_SERVER [ 'HTTP_USER_AGENT' ])) 
    { 
     set_cookie (...); // New sessionid and write also to DB 

     // User is now logged in, execute some user stuff 
    } 
    else 
    { 
     // Session doesn't exist, or the fingerprint does not match 
    } 
} 

現在,攻擊者只是仍然需要會話ID,這是在cookie中(以及HTTP頭髮送)和用戶代理。那麼額外的鹽還有什麼意義呢?

檢查IP的也是在我看來不是一個很好的選擇,有些提供商或代理服務器改變他們的每一個請求。

由於到目前爲止( - :

3

如果你是你自己的服務器上,加密會話變量是沒有意義的,因爲他們不出去服務器的更多信息,請參見Linead答案What do I need to store in the php session when user logged in?。如果您在共享服務器中,除了會話ID之外,您可能需要加密每個會話變量,因爲它們存儲在您的鄰居正在使用的同一Web服務器可讀的臨時文件中。真的擔心安全問題,你用自己的(虛擬的或不是)服務器更好,所以危險只會來自你的服務器外部。

風險到您的會議的一些例子:

  • 您的服務器的URL發送會話ID和用戶遵循以badguys.com他們將在服務器變量的引用者獲得一個鏈接(完整的URL,包括會話ID),瀏覽器和用戶的IP地址。如果您沒有檢查IP,或者您的用戶使用開放式代理,則只需安裝相同的瀏覽器版本,粘貼網址即可完成。
  • 用戶轉到公共電腦登錄,然後離開而不關閉他的會話(嘿,他畢竟是人類)。該行中的下一個人打開瀏覽器,查看歷史記錄並找到公開會話。呸。

所以,有些措施可以採取,由我通常偏好:

  1. 不要發送的URL中的會話ID;在PHP中啓用session.use_only_cookies。缺點:用戶需要啓用cookie。
    • 關於危險操作(更改密碼,下單......),請再次詢問用戶密碼。你也可以定期做。缺點:煩人。
    • 快速超時會話。缺點:在大多數網站中,這會迫使用戶經常登錄,煩人。
    • 使用SSL(只有這樣才能避免'中間人'攻擊)。缺點:慢。愚蠢的瀏覽器消息。在服務器上需要SSL。
    • 檢查IP。缺點:對使用公共代理的訪問者無效。煩人的動態IP。
    • 檢查用戶代理(瀏覽器)。缺點:幾乎沒用,UA很容易得到和模仿。

(我認爲是理所當然你還沒有PHP配置最大的安全性)。

一些更極端的措施:

  • 維護服務器和瀏覽器,例如之間的永久連接使用Java小程序。沒有連接,沒有會話。缺點:用戶需要Java,ActiveX或任何你使用的。會話關閉瀏覽器(這可以很好)。不適用於連接速度很慢的情況。服務器負載較高。您需要打開端口,爲applet創建一個特殊的服務器。
  • 同樣的,但使用異步請求(例如AJAX)非常頻繁地刷新會話,以及非常短的超時。或者刷新隱藏的IFRAME。缺點:用戶需要JavaScript。不適用於連接速度很慢的情況。服務器負載較高。
  • 相同,但重新加載整個頁面。缺點:用戶需要JavaScript。當你正在閱讀一個頁面時自動重新加載煩人。

在某些情況下,您可以忘記會話並使用Apache身份驗證。最簡單的解決方案,但有很多限制。

1

我看到一個目的是醃製指紋。如果一個壞人抓住了你的session-db(天知道爲什麼)而不是你的代碼,他不能通過嘗試普通的用戶代理來「猜測」你的指紋方法。