遇到這種狀況, 開發團隊的辯解通常是:
1. 這已經用 https 保護了, JSON 內容先被加密才傳輸出去
2. 這放在 POST Payload 裡面, 不是 GET, 一般人看不到
但, 資安的原則是:
不論任何情況, 都不應該在網路上傳輸帳密 (Credential)
---不論內容有沒有加密+不管用哪一種 HTTP Method.
從 DevSecOps 的角度來看:
依賴 HTTPS 做保護, 代表你是在:
DevOps 8 個階段中的 Deploy Pipeline 才開始啟動保護, 這樣違反 DevSecOps 原則
(正確應該是在前面的 Plan/Code/Build 這幾個階段都要做)
資安講究的是:
洋蔥式的層層防禦; 而不是只有一道銅牆鐵壁:
在合理的成本下, 防禦越多層, 安全的程度就越高.
資安極少會有那種:
我只要做一件事情, 就可以抵抗所有威脅
這樣的方便事.
另外一個觀念是:
有威脅存在, 才需要保護弱點.
如果沒有威脅, 即使有弱點也不一定要保護.
資安不能盲目的做;盲目無上限的做, 只會得到極大的成本負擔+自己都不知道的漏洞;
我們一定要知道: 為了甚麼威脅而做這件事情?
回到這個主題, 應該先問:
我們保護 Credential 的傳輸, 是為了要對抗甚麼威脅?
主要的威脅來自於:
中間人攻擊 (簡稱: MITM),
我們擔心有中間人攔截封包, 解讀後得到密碼.
那麼下個問題就是:
光靠 HTTPS 加密, 能否抵抗得了 MITM?
以下是一個用 MITM 技術, 攔截 HTTPS 的實作案例:
How to Man in the Middle HTTPS Using mitmproxy
她藉由偷塞假的 CA Root 到 Client 端電腦之後, 偽造假的 SSL 憑證, 建立一個不被瀏覽器懷疑的 HTTPS 假象, 而成功獲得攔截中間封包的機會.
由上述案例可知:
如果用樓主所述的方法來傳輸帳密, 只要經由上述手法, 中間人就可以獲得明碼.
要對抗這個 MITM 的威脅, 除了上面已經被破解的 HTTPS 方案之外, 還可以有這些:
1. 改用 Hash 傳輸密碼的雜湊 (而不是密碼本身):
無論如何都不應該在網路上傳輸密碼, 那我們要驗身分怎麼辦?
答案是:傳輸密碼的 Hash 值就好.
其實後端在儲存的時候, 也不應該儲存完整的密碼明碼, 資料庫裡面只要存 Hash 值, 密碼的明碼就可以丟棄. 當網頁前端要驗證的時候, 也是算好傳 Hash 值過來, 從資料庫中取出 Hash 來比對, 正確就是過關.
要產出安全性高的 Hash 值, 業界普遍建議採用 bcrypt 函式庫實作:
[Day-29] (實作)bcrypt將使用者密碼加雜湊
這種方式, 只有前端瀏覽器會接觸到密碼的明碼 (因為網頁上面仍然需要接受明碼輸入), 瀏覽器讀取輸入完成的明碼之後, 馬上由前端程式算出 Hash, 接下來, 只把 Hash 傳輸給後端 (密碼則直接丟棄, 不傳送也不儲存).
所以: 傳輸過程、後端程式、後端資料庫、甚至開發人員, 測試人員, 維運人員, 最高管理者...等等, 都沒有辦法看到真正的明碼; 不過: 卻可以用來完成身分驗證.
在這種設計下, 所有人都看不到明碼, 用戶想要改密碼, 只能重設一個新的進去, 不能拿出舊密碼來顯示或更改. (這是在 DevSecOps 的 Plan 階段就完成, 然後 Code 階段根據這個設計來寫碼)
不過, 中間人還是可以看到 Hash 對不對?
只是她沒辦法從 Hash 反推成密碼的明碼?
對嗎?
這說法只對一半, 理論上, 若用 Brute Force 硬算比對, 雖然無法短時間反推密碼, 但是如果對方手上有彩虹表, 而且使用者慣用特定意義的語言文字來建構密碼的話, 有可能在短時間之內, 透過彩虹表可以比對出真正的密碼明碼.
下圖是用 Brute Force 方式硬算 Hash 反推明碼所需的時間, 密碼越長, 時間越久:
(這是以 2022 年的 GPU 算力來破解 MD5 Hash)
所以這樣還不夠, 我們需要下一層防禦.
2. 加鹽 (Salt) 後再算雜湊:
這只是把 Hash 的程序改一下, 多加一道: 當拿到密碼明碼之後, 先加自定義的 Salt 值進去之後, 再開始演算 Hash. 加鹽的實作和維運成本都不高, 但獲得的資安效果非常好.
由於資料庫裏面的 Hash 也是加過鹽的, 前端送過來之前, 也預先加了鹽, 所以只要前端輸入的密碼相同, 兩者比對出來, 會是相同的 Hash 值. 她可以完成驗證任務.
可是當 MITM 的中間人拿到這個 Hash 之後, 即便她可以反解出明碼, 如果她不知道 Salt 的內容, 她仍然無法獲得使用者正確的密碼明碼
加了 Salt 就夠難破解了嗎? 並沒有喔....
如果我們只使用靜態固定的 Salt 值, 當 MITM 收集到來自不同用戶的 Hash 之後, 有足夠多的 Hash 反解個案, 她其實可以從裡面抽出真正的靜態 Salt 明碼來. 這樣她仍然可以在去除 Salt 之後, 獲得真正的密碼明碼.
所以又需要多加一層:
3. 將加過鹽的 Hash 再加密:
這裡可以有兩種方式: 對稱式或非對稱式加密
對稱式例如: 採用軍事等級的 AES 256 加密(美國國防部要求, 已成為聯邦政府標準), 傳輸過程 MITM 只能拿到加密過的 Hash, 但中間人並不知道加密 Key, 所以無法反解出正確的 Hash 內容.
非對稱式則是: 採用 PKI 架構 做公開金鑰加密: 先製作一支 Private Key (私鑰) 放在後端, 然後產出多隻不同的 Public Key (公鑰) 給每一個用戶, 用戶的前端程式將 Hash 用 Public Key 加密之後才傳輸, 後端則用她自己的 Private Key 將她解密之後, 得到正確的 Hash 值.
寫到這裡我也累了, 還有沒有更多防禦的手法?
當然有 (例如: bcrypt hash 加 Round)...
不過再疊加上去, 成本是否划算? 你們可以自行去研究....
不知為何最近台灣狂被攻擊
真的快被煩死