如何兼具人性與安全的管理密碼?

Share This Post

所謂「安全的密碼」?

若從資訊安全的角度,會建議取的密碼「愈複雜愈好」:

使用者的角度:安全與便利的平衡點?

密碼使用的惰性難以抵抗…

  • 使用大量的安全措施,其實違反人性與人類記憶能力
    • 誤用安全規則或理解不夠的話,反而可能搞出人類難以記憶卻容易被電腦破解的「偽安全」密碼
    • 理想上每組密碼應該要不一樣,但實際上除非註冊使用的服務很少,不然不可能全部直接記住
    • 因密碼難以記憶而用外部的管理器或紙本等工具,反而又會受制於工具,等於你自己也不知道密碼,甚至工具因漏洞或保存不當外洩時,無法在第一時間得知與處理…
    • 至於定期更改密碼,既使因要求而執行,實際上卻可能怕麻煩而沒有徹底更改(如只變動一小部分),更別提可以不用改還懶得改的情況,效果因而大打折扣…
  • 另外,若加上2FA、生物識別、U2F等額外手段搭配驗證,不僅開發與維持服務的成本上升,用戶也需要更多的硬體搭配…
  • 題外話,如果網站服務有忘記密碼重設功能,對總是忘記(或不想記)密碼的人來說,算是變相的OTP…?

可能的折衷思路:公、私鑰的區分與結合

  • 受非對稱式加密啟發
  • 比起固定的密碼,自訂固定的密碼規則更重要
  • 試圖兼具人性與安全,在二者之間求平衡,且保留取捨的調整性質
  • 將個人取密碼的策略調整成二個字串的組合
  • 類似非對稱式加密區分公私鑰的方式,
    • 公鑰:對應註冊服務的名稱
      • 簡易的作法,直接取服務名稱的英文版,或網頁的網域名稱
      • 進階的話則用英文服務明再進一步變化(搭特定規則改寫)
      • 因為看到服務名稱可直接聯想到,甚至是直接挪用,因此算是「公鑰」
    • 私鑰:以安全規則設的密碼
      • 遵守本文第一段「安全的密碼」所設置
      • 沒信心的話,可以到這個網站測試得花幾年破解
      • 因為這組密碼理論上只有你(或少數人)知道,因此算是「私鑰」
  • 實際密碼的產生組合:將密碼的公鑰與私鑰部分,用特定規則放在一起
    • 因為在個別服務註冊的每組密碼,都有根據服務名稱變化的公鑰,可以達成最基本的帳號密碼不重複要求
    • 基本版:除公私鑰的先後放置順序,也可以在二者之間加上特殊符號區隔(較為直觀好用)
      • 舉例:如在Facebook使用”!4f6#6JL5@facebook”、Google使用”!4f6#6JL5@google”
      • 上述為私鑰(!4f6#6JL5)+特殊符號(@)+公鑰(facebook/google)的組合
    • 進階版:將公鑰或私鑰的部分穿插在另一部分,甚至實際使用的是公私鑰組合後再加密或雜湊的結果(更能保障安全但也繁瑣,願意隨時準備產生密碼需要的工具的話)
  • 限制:仍不改密碼的本質
    • 儘管這招較容易產生好記可變化且算安全的密碼,也不是絕不可能外洩或被猜出(儘管機會很低)
    • 仍需要妥善保管密碼,且真有高機敏必要的話仍需再加上定期更改、配合額外驗證方式或生物辨識/實體金鑰等常規方式加強安全

應用服務的角度:應如何處理使用者密碼?

前端(Client):格式的提示與檢查

  • 以表單(form)下type=password<input>標籤輸入送出
  • 關於設置密碼的規則與建議
    • 如果強調安全性,可以將上述常見的密碼規則敘述加到註冊頁面的提示
    • 甚至實作密碼強度驗證,避免使用者設置明顯不安全的密碼
      • 如最短長度、是否兼具數字與大小寫,甚至必用特殊符號
      • 建議在前端以JS實作(可用正規表達式檢查格式),而非發給後端處理再等回傳結果,可節省網路流量與等待時間
    • 但除非有特殊需求或限制,否則某些額外的密碼字元與長度硬性限制,反而讓使用者無法依照個人習慣設密碼
      • 像是長度上限(資料大小限制?)、不能使用特殊符號(防止惡意程式碼注入?)、只能用大/小寫或數字(PIN碼)…
      • 可能讓使用者無法使用習慣的安全密碼規則,得額外記憶或只能交給密碼管理器
  • 註冊的部分,通常會加上重複輸入密碼的驗證,強調密碼的重要性和協助確認、記憶(尤其沒提供其他登入方式甚至重設功能是),也是在前端以JS實作效能體驗較佳
  • 送出密碼時,切忌以明碼的方式傳輸,且需要一定的加密,否則很容易洩露機密資料!!!
    • 以web的概念HTTP method(請求方法)來說,得使用POST而非GET
      • POST可將資料藏在body,GET傳輸的資訊會直接顯示在URL
    • 加密的部分,只要發送時使用HTTPS即有一定的安全性,可不用特別處理
      • 有特殊需求的話,再另外使用其他加/解密方案(但不能用不可逆的雜湊)

後端(Server):雜湊化儲存與驗證

  • 既有帳號驗證 VS 暴力破解
    • 由於註冊必須告知帳號名稱是否被使用,可能讓駭客透過洩露的帳號名稱在其他網站服務猜出攻擊目標
    • 登入功能最好加上錯誤次數限制,避免被用電腦窮舉所有字串組合暴力破解
  • 以不可直接還原的雜湊(hash)儲存使用者密碼
    • 除非你想在背後做壞事(X),否則資料庫直接被駭客侵入的話密碼會直接洩露
    • 正常的網站服務其實不知道確切的使用者密碼,而是透過雜湊值與輸入的密碼比對來驗證身分
    • 因此網站不能主動從資料庫得知使用者密碼明文(能告知密碼的網站反而危險要小心!!!)
    • 至於重設密碼的功能,則是透過註冊時綁定的通訊方式(如電子郵件或手機號碼),確認身分後暫時給予登入狀態來修改密碼(另類OTP的概念?)
      • 即註冊時使用程式自動產生的複雜密碼(可不用記住),每次登入時都選忘記密碼來重設,等於每次都靠email或手機號碼取得登入權限,然後再隨機產生新的密碼

補充

補充1:OTP與2FA

  • OTP(一次性驗證登入)
    • 簡單來說就是透過綁定身分的通訊方式給予一次性授權的密碼,使用後即失效
    • 除非產生後即被攔截,否則更難暴力破解
    • 概念細節可參考維基百科的簡介
  • 2FA(雙重/兩步驟認證)算是MFA(多重要素驗證)較常見的例子
    • 常見方式如以帳號密碼/第三方平台登入後,仍需要OTP再度驗證
    • 可避免帳號被破解後馬上被更改篡奪,相當於多一道鎖
    • 概念細節可參考維基百科的簡介

補充2:社群平台等第三方帳號登入

  • 串接常見的社群帳號(如Facebook、Google),其登入狀態可用於直接註冊新帳號,之後登入也可不用輸入帳密
  • 若應用程式的開發為前後端分離,前端與後端的開發人員須溝通好串接的服務與方式
  • 前端部分點擊後前往第三方平台的登入頁面,首次使用還會有授權確認,授權後即自動註冊帳號並登入
  • 後端實作可使用基於OAuth 2.0的套件,如Laravel的Socialite和Express.js的Passport
  • 第三方登入建立的帳號若無特別設計,其實沒有帳戶對應的密碼(或使用者不知道),無法也使用傳統帳密登入
  • 若考慮讓同一組帳號能使用不同方式登入,則需要讓第三方登入註冊的使用者能另訂密碼,甚至還能綁定其他的第三方帳號

補充3:重點摘要與問題討論

全部展開回到頂部移至底部選擇 Repo

訂閱研究文章

Get updates and learn from the best

More To Explore

Scroll to Top

hurry up !

軟體工程師培訓

限時免費報名中

藉由與「真實世界軟體專案」相同的技術、工具與開發流程,化簡成與商業機密無關、門檻較低更容易上手的「模擬專案」,讓你有機會在職場前輩的陪伴下,完成真槍實彈的練習,動手解決真實的問題,快速累積個人的經驗與作品,而不只是「學習技術」而已。