根據 Macworld 在 2012/6/6 所發表的一篇文章, 一位俄羅斯駭客聲稱已駭進 LinkedIn 的資料庫並盜走帳號資料, 然後把六百五十萬 (實際數字為 6,458,020) 個密碼公布在一個俄羅斯的論壇中作為證據 (僅公布密碼資料, 並無關連的帳戶名稱及其它資料)。這些密碼事實上並不是明文, 而是已經過 SHA-1 (SHA 是 Secure Hash Algorithm 的縮寫; SHA-1 是在 1995 年發表) 方式加密的...
根據 Macworld 在 2012/6/6 所發表的一篇文章, 一位駭客聲稱已駭進 LinkedIn 的資料庫並盜走帳號資料, 然後把六百五十萬 (實際數字為 6,458,020) 個密碼公布在一個俄羅斯的論壇中作為證據 (僅公布密碼資料, 並無關連的帳戶名稱及其它資料) 並請求其他網友協助破解。這些密碼事實上並不是明文, 而是已經過 SHA-1 方式加密的。SHA 是 Secure Hash Algorithm 的縮寫, 中文翻譯為安全雜湊演算法; SHA-1 是在 1995 年發表, 另有 SHA-224、SHA-256、SHA-384 和 SHA-512 等演算法 (後四者常被併稱為 SHA-2)。
在這篇文章中, 也提及另一起關於 LinkedIn 的 iOS App 的個人隱私外洩事件。不過我認為那是單純的程式邏輯問題, 跟我在這裡想談的網站安全策略無關, 所以就此略過。
關於 LinkedIn
LinkedIn 是一個知名的社交網站, 成立於 2002 年, 成員大約有一億六千萬人, 平均年齡為 43 歲, 其中有超過四分之三是比較高階的職場人士。雖然它的知名度遠遠比不上 FaceBook, 但在特定網路族群中, 仍然是一個相當有規模, 而且影響力很大的網站。
大部份人加入 LinkedIn 的最大理由, 是因為 LinkedIn 是一個有利於工作機會互相交流的所在。有許多 Head Hunter 把 LinkedIn 當做人才庫在使用, 算是一個可以到處挖角的寶庫。許多跨國大公司也都習慣在 LinkedIn 刊登各種工作機會, 甚至可以直接應徵。對於有志人士而言, 這是一個能夠同時尋求本國與外國工作機會的好地方。
可惜的是, 由於 LinkedIn 並沒有中文界面, 網站的使用習慣又跟類似網站非常的不一樣, 所以在台灣並不像 FaceBook 那樣普及。但儘管如此, 我個人還是曾經在 LinkedIn 找到幾位過去的同事。這代表台灣人還是有一些人在使用 LinkedIn。
LinkedIn 密碼外洩事件始末
根據報導, 2012/6/4 有一位化名為 dwdm 的人在某個俄羅斯論壇開始公布總數多達八百萬筆的密碼資料, 邀請網友協助破解。他聲稱其中有六百五十萬筆來自 LinkedIn, 另有一百五十萬筆來自 eHarmony (美國的交友網站)。而 LinkedIn 於 2012/6/6 證實其中有部份密碼的確是來自 LinkedIn, 並建議會員盡速變更密碼。LinkedIn 負責人 Vicente Silveira 也在部落格中證實此事。
LinkedIn 並未說明密碼遭竊的過程, 其他人也無從推斷究竟 LinkedIn 的網站出了什麼問題。不過根據這些已被公布的密碼, 可以推斷出這些密碼使用了 SHA-1 雜湊表函式進行加密, 而且使用了「未調味」(Unsalted) 的方法。有人發現自己專用於 LinkedIn 的密碼被列在這些密碼裡面, 所以這次外洩事件是可以被證實的。
此外, 由於 dwdm 只公布了密碼, 並未同時公布關連的使用者帳戶資料, 所以取得密碼的人, 即使予以破解, 也無法拿這些密碼來登入。然而, 這並不表示 dwdm 手中並沒有帳戶資料, 所以 LinkedIn 和 eHarmony 等網站的使用者仍有遭到冒用的風險。
分析與推斷
以下, 我把這次洩密事件拿來做幾個分析。
我們先從好的方向來看。首先, 雖然 SHA-1 被國內外媒體講得好像有多麼糟糕一樣, 實際上 SHA-1 公布於 1995 年, 是從 SHA-0 改善而來, 算是一種相當安全的加密方法。
但是在學理上, 如果某種加密演算法上能使用比暴力式破解法更小的運算次數予以破解, 就代表這演算法已被攻破。因為已經陸續有人提出能在 2 的 63 次方個計算複雜度以內破解 SHA-1, 於是學術界就有人認定 SHA-1 已經屬於「不安全」的加密方式。
話說回來, 2 的 63 次方是多少? 實際上 2^63 = 1.84467441e19, 也就是一千八百四十四萬六千七百四十四兆 - 請注意最後面那個「兆」字。由於這個數字太大, 已經不是電腦上常用的最大整數可以表示, 而必須使用科學記號來表示。
光是要破解一個密碼, 你就必須執行這個破解程式那麼多次。我算了一下, 如果你家裡的電腦一秒鐘可以運算十次的話, 那麼破解一個密碼的時間是 1.84467441e18 / 60/60/24/365=5.84942418e10 年, 也就是五百八十四億九千四百二十四萬一千八百年 - 同樣的, 請注意最後面那個「年」字!
假設 dwdm 這位駭客能在網路上號召五百八十四億九千四百二十四萬一千八百個電腦同時幫他做平行運算 (不討論如何做切割及合併, 也不討論世界上有沒有那麼多部電腦), 也得花上整整一年的時間, 才能破解一個密碼。如果你想挑戰我, 說有些超級電腦的運算速度快很多, 那也無妨, 我歡迎你去計算一下究竟要花上多久 (你可以套用我已經在上面寫好的算式, 只需要把每秒十次改掉即可)。無論如何, 一個天文數字如果不能用另一個天文來除, 那麼它仍然是天文數字 - 尤其跟人類的平均壽命來比的話。
何況遭竊的密碼並不是一筆, 而是六百五十萬筆!
所以, 我到現在還是很悠哉, 並沒有急著去改我的 LinkedIn 密碼。雖然我最後還是會去改。
以上, 我們講的是 best case。很可惜, 若要分析安全風險, 我們向來應該分析的都不是 best case, 而是 worst case。
在最壞的情況下, 我也可以告訴你, 儘管我在上面講了很多安慰人的話, 你的密碼卻有可能在一秒之內被破解。
大家想想, 我不是駭客, 我都知道破解密碼需要費那麼大勁兒, 難道駭客不知道嗎? 你覺得駭客會笨到去乖乖的花天文數字的時間去破解你的密碼? 駭客會那麼「守規矩」? 如果是這樣, 這位駭客也不叫做駭客了。
LinkedIn 密碼遭竊事件中, 最糟糕的並不是密碼遭竊, 而是密碼不但遭竊, 而且還被發現使用的是 Unsalted SHA-1!
當你使用的加密方式已被鎖定, 那麼「敵暗我明」的情勢就已經明朗, 你當肉靶當定了!
因為你所使用的加密函式, 別人也有, 所以, 例如你的密碼是 "123456", 那麼得到的 hash 就是 "d0a970cc71d15aa10b07584a7bd31ff6"; 別人只要使用後者來查, 就能很快的反推出你的密碼就是 "123456"。
每位駭客手裡都有一本字典 (這本字典裡沒有「放棄」), 收集了各種大家常用的懶人密碼, 例如前述的 "123456", 或者 "abcdef", 還有像是常見的人名、日期等等。想必 dwdm 所號召的其他駭客, 現在都在瘋狂的拿自己的字典在做比對吧!
所以, 這六百五十萬筆密碼資料對於駭客而言, 這個龐大的數目不但不是負擔, 恐怕還是練功力的最佳標的! 就算不把這些資料拿來犯罪, 也勢必可以拿來充實自己的字典的內容和邏輯。
此外, 曾經有駭客宣稱, 即使不用字典比對的方式, 他也有辦法藉著使用兩個 NVIDIA Tesla "Fermi" M2050 GPU, 經由內建的平行運算功能, 把任何 1 到 6 字元長度的以 Unsalted SHA-1 加密的密碼在 49 分鐘內破解 (不過如果密碼愈長, 破解的時間就會顯著地跟著變長)。他並沒有宣稱他可以破解「任何」字元組合的密碼, 而且我懷疑他並不是真的「破解」了這些密碼, 而是使用所謂的「踫撞」方式去得到相同的 hash 值 (意思是他可以使用不同的密碼, 卻得到相同的 hash 組合, 如此也可以達到破解密碼的相同目的)。
此外, 隨著時代的演進, 今天的 CPU 運算能力已經不是吳下阿蒙; 除了上面提到的 NVIDIA M2050, 現在光是一個配備有 AMD Radeon HD7970 GPU 的電腦, 就可以執行每秒達 82 億次破解密碼的動作 (而不是前面為了安慰你而說的十次), 這已經是過去只有超級電腦才能辦到的。甚至, 若再加上多處理器以進行平行運算的能力, 其運算速度更可以倍速增長。
如果你有 LinkediN 帳號, 而你的 LinkedIn 密碼是短短的懶人密碼, 而且你看到這裡還不趕快去改密碼的話, 你就對不起我了喔!
對策
對於網站的開發人員而言, 我們應該怎麼提升網站的安全性? 從 LinkedIn 的洩密事件中, 我們學到什麼教訓?
在比較正式的軟體開發計畫中, 總是必須有一部份是探討 Risk Assessment (危機評估) 或 Risk Management (危機管理) 的 (見 IEEE Std 1540-2001 和 IEEE Std 730-2002)。網站的安全當然是 Risk Assessment 的最重要一環。
那麼, 我們應該怎麼評估網站的安全性?
我們可以從最壞的情況開始分析。我們在這裡不討論 Disaster 等級的風險 (像地震、海嘯或者核彈攻擊等等), 光是就 Critical 等級的風險來評估好了。
在最壞的情況下, 網站的資料庫被整碗捧去 (不考慮是經由何種方法), 連同網站的原始碼也被盜走。基本上, 這是一個非常嚴重的情況, 如果此種情況發生, 我想這家公司恐怕都要倒店了。不過由於此種情況已經超過本文的範疇, 就此打住。
在次壞的情況下, 會員資料庫被整個或部份盜走。那麼, 駭客將有可能進行資料庫的分析, 基本上是可以為所欲為的。這種情況大致上就是此次 LinkedIn 遇到的情況。如果在這種情況下, 我們能做什麼事情予以預防?
首先, 如果網站把客戶的密碼以明文 (Plain Text) 方式儲存的話, 或者甚至把客戶的帳號 (ID) 儲存在同一個資料表中, 那麼客戶資料就等於詳盡地奉送給駭客了。
但是如果網站的設計者聰明一點的話, 可以選擇把密碼欄位予以加密。如此, 即使駭客拿到了加密後的密碼, 也不能輕易地看出密碼實際上是什麼。就像上面所舉的例子, 原來的 "123456" 被加密成 "d0a970cc71d15aa10b07584a7bd31ff6"。
然而, 就如同在這次 LinkedIn 洩密事件中遇到的狀況, 如果被駭客得知你的加密方式, 那麼他們仍然可以運用上面已經講到的方法猜測出使用者的密碼。
因此, 相對於 Unsalted SHA-1 方法, 如果我們使用 Salted SHA-1, 安全性是不是就提高了呢? 所謂的 "Salted", 意思就是不直接拿原來的密碼 (假設密碼是 "B") 去加密, 而是把它加料以後再去加密, 例如取 "A" + "B" 去加密 (這裡的 "A" 指的就是 Salt)。如此, 駭客必須額外知悉你加了什麼料, 才有辦法施行破解。
而且, 你也不一定要乖乖的使用 "A" + "B" 的方式去加密, 你可以改用 "B" + "A" 的方式去加密, 或者任何變形的方法。你甚至可以給它 Salt 兩次 (吃重鹹?) 或更多次, 使得駭客根本無從猜測你的加密邏輯。
你也可以運用相同的做法去處理每個關連的資料表, 使得駭客即使拿到整個資料庫, 他也根本沒辦法知道到底哪一筆資料是對應到哪一筆帳號。如果你更狠一點, 你甚至可以乾脆把每一個重要欄位都予以加密 (同時使用不同的 Salt 跟邏輯), 如此將使得駭客拿到整個資料庫, 也不能拿來做什麼。當然, 你必須考量網站的整體效能, 量力而為。
當然, 以上我們分析的都是以資料庫被盜走為前題。那麼, 如何不讓資料庫被盜走, 不是更重要、更需要預防嗎?
問題在於, 由於截止目前為止的新聞報導中, 都沒有提及 LinkedIn 資料遭竊的確實管道是什麼, 所以我們根本無從分析起。雖然大筆資料被竊走的原因不難猜測得出來, 但如果我們只是憑想像而妄加揣度, 恐怕有毀謗之嫌, 對 LinkedIn 也不盡公平。所以, 我們只能基於已知的事實來分析。而且從最近外國新聞媒體對這件事的報導中, 也都沒有看見對 LinkedIn 遽下定論的指責。
不過, 原則上, 如果駭客事實上已經取得 LinkedIn 資料庫的完全控制權, 基本上你採什麼加密法都無濟於事了。他甚至不用花力氣去破解密碼。例如,如果他把你的密碼欄位內容改成 "d0a970cc71d15aa10b07584a7bd31ff6", 那麼你的密碼就變成 "123456"。就算網站的 Salt 邏輯再複雜, 他還是可以很簡單地把自己的密碼內容貼到你的密碼欄位, 然後你的密碼就變成他的。等他要做的事情做好, 他再把原來的密碼覆蓋回去, 如此一來, 甚至不會有人知道他進來過 (假設他沒有忘記把 log 也一併刪除的話)。我想, 這個討論就到此為止, 否則這篇文章恐怕會變成駭客教學, 那可不是本文的初衷。
ASP.NET 的做法
如果你在網站中不考慮採用複雜的 Salt 方法, 那麼使用 ASP.NET 的內建 Membership 模型已經非常足夠了。
當你建立一個 ASP.NET 網站時, 除非你另外做了設定 (請參考 PasswordFormat 屬性, 以及「成員資格的 providers 項目」這篇說明), 否則它已經預設採用 Salted SHA-1 加密方式。換句話說, 你根本不需要做什麼, ASP.NET 網站的預設安全性已經相當的高。但是如果你要建置一個商業網站, 或許你需要更高層級的安全性架構, 那麼你可能必須自行設計資料庫架構和 MembershipProvider, 而這就不在本文的討論範疇裡了。