講完 session 之後,接下來這幾天要來講講跟密碼有關的安全性議題,畢竟如果使用者的密碼不小心被駭客偷了去,那不管網站的流量管制做得多好、session 安全性有多高,最後也都會是功虧一簣
從使用者的角度來看,我想大家應該都有過忘記密碼的經驗,那為什麼當你按下「忘記密碼」時,網站總是要求你重設密碼(除了某和X租車 ?),而不直接把密碼寄到你的信箱呢?答案就是因為網站根本不知道你的密碼是什麼!
大部分人第一次聽到這個答案時都會非常錯愕,心想「如果網站不知道我的密碼是什麼,那他要怎麼知道我輸入的密碼對不對」,這就是密碼學的神奇之處了,網站確實可以在不儲存密碼明碼的情況下,驗證你輸入的是不是正確的密碼,這個待會我們再來細講
而從網站開發者的角度看,雖然直接在網站資料庫儲存所有使用者的密碼非常方便,反正使用者輸入密碼之後就到資料庫裡面比對一下就好了,但其實這樣做有非常大的風險,萬一哪天網站的資料庫被駭客入侵,或是被內部員工有意無意洩漏出去,那就會有非常多使用者被盜用,造成無法估計的損失
所以說關於儲存密碼這件事,雖然大多網站開發者都覺得自己家的資料庫很安全,絕對不可能被駭客入侵,但還是應該要做好準備,盡量做到「即使資料庫被駭了,使用者的密碼也不會洩漏出去」這樣的程度才對
如果直接把使用者的密碼明碼存起來太不安全,那先加密起來再存可以嗎?這樣即便資料庫被攻破,只要駭客拿不到密碼,應該就不可能得到原本的密碼吧
以現今最流行的對稱式加密法 AES256 為例,如果把資料庫裡面所有的密碼用 pa55w0rd
作為 key 加密起來,大概會長成這個樣子
如此一來即便整個資料庫都洩漏出去了,只要駭客不知道加密用的 key 是什麼,就無法還原出原本的密碼,因此會比原本直接存明碼來得安全
雖然說是這麼說,但其實也沒安全到哪裡去,因爲使用者要登入時,後端必須確認使用者輸入的密碼正確,所以還是必須把 key 放在 server 上用來解密。既然是放在 server 上,那駭客就還是有機會拿到,你想想他都能偷到你家資料庫了,拿到加密用的 key 其實也不是太難的事情
而且這樣做還有另一個隱憂:因為公司內的員工可能會知道 key,所以就可以從資料庫得到使用者的密碼。如果你知道 Facebook 的工程師只要想要就能得到所有人的密碼,應該也不太放心吧,尤其很多人都在多個網站使用同樣的密碼
所以結論就是因為無法保證 key 的安全,所以不建議用加密的方式保存密碼
我聽說雜湊(hash)是不可逆的,那用雜湊總可以了吧?
不太熟悉編碼、雜湊、加密三者區別的話,可以先看完 「一次搞懂密碼學中的三兄弟 — Encode、Encrypt 跟 Hash」 再往下看,比較不會搞混哦
沒錯!雜湊是不可逆的,下圖三個密碼就是經過 SHA1 雜湊過的結果,像 Luka 的密碼 hash 過後是 1785bf0ed0f6346210af2d64b310a99b4024ce44
,而這串東西無法經由運算反推回原密碼
對於雜湊函數而言,相同的輸入一定會得到相同的輸出,因此當使用者 Luka 要登入時,API Server 就把他輸入的密碼拿去經過 SHA1 雜湊,如果算出來的雜湊值跟資料庫內那一大串一樣,那就代表 Luka 有極高機率輸入了正確的密碼,所以就放行讓他登入
但可別忘記了,雖然雜湊值無法直接反推回原密碼,但你可以用電腦把長度為 8 的字串都用 SHA1 雜湊過一遍,譬如說從 00000000
一路算到 zzzzzzzz
,然後建一個表
如下圖,因為 SHA1 的碰撞機率極低,如果計算的過程中找到某字串 hash 後剛好是 1785bf0ed0f6346210af2d64b310a99b4024ce44
,那該字串 love1234 就非常有可能是 Luka 的密碼
雖然這聽起來很不可思議,真的要做也是一個大工程,但因為現在電腦的運算速度非常快,所以已經有人做過了。只要到 MD5Hashing.net 輸入你想要破解的雜湊值,甚至不需要告訴他是哪一種演算法,他就會幫你查表找出來。像我輸入 Luka 那一串 1785bf0ed0f6346210af2d64b310a99b4024ce44
,就能知道他是 love1234
經過 SHA1 雜湊的結果,超厲害的
而且這個網站支援的雜湊演算法有超過六十種,包括大家最常用的 MD5、SHA1、SHA256 跟 Tiger128 等等,所以你換其他雜湊法也沒有用,只要駭客拿到密碼雜湊值,要得到原本的密碼也不會太難
今天雖然沒有總結出到底該怎麼儲存密碼,但我們明天會繼續往下探討其他解決方法,如果對於今天的內容有什麼問題歡迎在下方留言,沒有的話我們就明天見啦