Code Monkey home page Code Monkey logo

Comments (10)

IepIweidieng avatar IepIweidieng commented on July 18, 2024 3

第一限制:fcrypt() 的實作(採用 DES hashing)

在常見的 DES hashing 實作中,密碼明碼僅有前 8 字元的 7-bit 部份有效。

在 PttBBS 中的實作,請見 https://github.com/ptt/pttbbs/blob/master/common/sys/crypt.c

由於 glibc 的 crypt 函式庫爲了最佳化的執行速度而使用的全域加速 table 佔用了太多記憶體空間(下述),PttBBS,恰如同一些 FireBird BBS 分支,改採用其它空間需求較少的函式庫來提供 DES hashing 之功能。

  • FireBird BBS 分支中的範例:https://github.com/bmybbs/bmybbs/blob/master/libytht/crypt.c
  • 在單個使用者的連線過程中,使用次數寥寥無幾的全域加速 table:100KB per 處理程序 ≈ 1GB per 10000 使用者 (據 crypt.c,以線性插值推論)
  • 註:在保留了 MapleBBS 系列甚至其前身的較舊特徵的一些專案中,BBS 伺服器程式會使用 -lcrypt 對 libcrypt 進行 靜態 連結,故每一處理程序中皆存有一個加速 table。
    • 雖然 Linux 的 fork() 採用了 copy-on-write 機制,但由於此加速 table 在 hashing 運算中會被更動(據 crypt.c),仍會觸發複製,浪費無法避免。
  • 註:某些 FireBird BBS 分支在採用此方式前,曾經使用暫時 fork() 出額外的處理程序,並在其中呼叫 crypt() 的方式,來達到釋放加速 table 所佔用的記憶體空間的效果。 (暫時忘了資訊來源 (楓橋驛站《SysSuggest》某傳信文,或?);僅依稀記得原文有「不用再 fork……」什麼的字句)

後來的 glibc 的 crypt() 尚增加了如 MD5、SHA-256、等等較現代化的 hashing 方式,但礙於記憶體空間,此函式無法直接於 PttBBS 使用。
可見 https://man7.org/linux/man-pages/man3/crypt.3.html

※ DreamBBS 直接使用了 glibc 的 crypt() ,故有記憶體使用量上的疑慮。

可能的解決方法擧隅

  • 在專案中新增支援 SHA-256 hashing 的函式庫
  • 若要改用 glibc 的 crypt(),或可嘗試待呼叫時再以動態載入的方式載入 libcrypt 函式庫,呼叫完畢後即解除載入此函式庫,以避免記憶體空間之浪費。

第二限制:userec_t::passwd[] 的大小(= PASSLEN = 14)

如果要用 32 至 64 個 bytes 長的可輸入字串 (假設爲 Big5 編碼) 作爲密碼的話,理論上至少需要 ⌈32 ⋅ log₂(95 + 128) ÷ 8⌉ = 32 至 ⌈64 ⋅ log₂(95 + 128) ÷ 8⌉ = 63 個 bytes 大的空間。

又,因需儲存 hash 資訊,實際需要的空間更大。

※ DreamBBS 儲存 SHA-256-hashed 密碼時,將 hash 資訊與 hashed 密碼分開儲存,其中 hash 資訊沿用欄位 passwd[],而 hashed 密碼的空間 (passhash[]) 則是將已不再使用的大資料欄位變更用途而來的。
- 但 PttBBS 的 userec_t 應無此類不使用的大欄位,故不適用此修改方式。

可能的解決方法擧隅

  • 將使用者密碼資訊以另外的資料結構儲存。
    • 注意在 MapleBBS 3.xx 系統中,使用者資訊是分檔儲存於各使用者目錄下的。使用者索引檔僅儲存使用者 ID 與其編號。若將使用者密碼資訊分開儲存,則將趨於 MapleBBS 3.xx 系統的設計。或可借鏡。

第三限制:使用者(?)

只增加支援 > 8 bytes 8-bit 密碼明碼還不足夠,還需使用者主動修改密碼。

由於依 hashed 密碼直接回推原密碼明碼,再以新方式 hash,需要一定的計算資源(下述),又因爲 DES hashing 只看密碼明碼 7-bit 的部份,如果使用者的密碼明碼包含特殊字元,會回推錯誤,造成使用者以同樣的密碼明碼無法登入之窘況。

  • 即使是「脆弱的」 DES hash,暴力破解某一密碼也需最多 128⁸ = 7.2057594×10¹⁶ 次嘗試。若電腦一秒能嘗試 10⁹ 次,最多需約 834.00 天的時間才可破解 單一 使用者的密碼。
    • 保守估計,若使用者平均使用 6 碼英數與空白字元作爲密碼,則平均須嘗試 63⁶ = 6.2523502209×10¹⁰ 次(),而在同樣的運算速度下,平均需 62.5 秒的時間。何況批踢踢可能有超過 100 萬位已註冊使用者,需約 723.38 天才可轉換完成。
    • (註:包含短於 6 碼的情況的話,是 63¹ + 63² + … + 63⁶ 次,但此處不計以求簡潔)
    • 若嘗試使用多機器進行平行運算,則有資訊安全問題之虞。
    • 即使不論以上各點,對使用者密碼的破解本身就有相當大的侵犯隱私之疑慮。

因此站方尚需加以宣導,鼓勵使用者利用新密碼 hash 的方式,方可發揮 > 8 bytes 8-bit 密碼的優點。

from pttbbs.

robertabcd avatar robertabcd commented on July 18, 2024 3

所以這時要讓使用者再輸入一次確認?

我覺得可以有個宣導期,過了之後登入強迫改密碼。

from pttbbs.

kcwu avatar kcwu commented on July 18, 2024 1
  1. ptt 的 crypt 函式是我換的, 該函式的確只支援 DES crypt, 不過我想另外找一個 library 來用應該不是太大的問題. 當然 @IepIweidieng 建議的解法也可以嘗試.
  2. passwd[] 大小的確不夠, 因此需要擴增欄位, 關站轉換檔案格式. 不過因為只需要存密碼的 salt 跟 hash, 空間不一定需要用到 @IepIweidieng 說的那麼大.
    p.s. 如果要做, 記得 "取備份" 這功能要特別處理, 以免拿舊欄位蓋掉新的資料, 可能會造成資料錯亂的問題.
  3. 基本上不會採用逆推原密碼的方式處理這個問題. 比較簡單的做法是, 同時支援新舊方式, 當使用者上站時, 密碼驗證通過之後當場轉成新的 hash funciton 寫回檔案. 由於帳號太久沒用會被砍掉, 所以理論上幾個月之後全站就能轉換完成.

from pttbbs.

wens avatar wens commented on July 18, 2024

DES crypt...

from pttbbs.

robertabcd avatar robertabcd commented on July 18, 2024
  1. 基本上不會採用逆推原密碼的方式處理這個問題. 比較簡單的做法是, 同時支援新舊方式, 當使用者上站時, 密碼驗證通過之後當場轉成新的 hash funciton 寫回檔案. 由於帳號太久沒用會被砍掉, 所以理論上幾個月之後全站就能轉換完成.

直接在背後轉換會有問題,因為 crypt 現在只吃 8 碼,但登入可以打超過 8 碼(logind 吃 14 碼),在背後轉無法確認超過的部分是不是使用者想要的,如果在轉換的那次不小心 8 位以後輸入錯誤,之後會無法登入。

from pttbbs.

kcwu avatar kcwu commented on July 18, 2024

直接在背後轉換會有問題,因為 crypt 現在只吃 8 碼,但登入可以打超過 8 碼(logind 吃 14 碼),在背後轉無法確認超過的部分是不是使用者想要的,如果在轉換的那次不小心 8 位以後輸入錯誤,之後會無法登入。

good point. 所以這時要讓使用者再輸入一次確認? 不過這樣大概會讓很多做自動 login 的 app 壞掉 XD

from pttbbs.

IepIweidieng avatar IepIweidieng commented on July 18, 2024
  1. passwd[] 大小的確不夠, 因此需要擴增欄位, 關站轉換檔案格式. 不過因為只需要存密碼的 salt 跟 hash, 空間不一定需要用到 @IepIweidieng 說的那麼大.

吾忘 hash 會撞,因此 32–63 實指「無 collisions」所需之 passwd[] 最小空間。
crypt() 各模式之 hash 長度:https://man7.org/linux/man-pages/man3/crypt.3.html#NOTES

因不愼假設資料結構需向舊相容,我未列入擴大其欄位之方法。
DreamBBS 將 crypt() 回傳的總 hash 分割儲存:

  • SHA-256:passwd[]: 3 ($5$) + 10 (salt) + 1 (\0) = 14 (= PASSSIZE);passhash[]: 1 ($) + 43 (hashed 密碼) + 1 (\0) = 45 (= PASSHASHSIZE)。
  • DES:只看 passwd[],忽略 passhash[]

可參考 https://github.com/ccns/dreambbs/blob/9b3e98f9d7/lib/passwd.c#L89

若可擴大 passwd[] 的話,大可不必如此切割。

  1. 基本上不會採用逆推原密碼的方式處理這個問題. 比較簡單的做法是, 同時支援新舊方式, 當使用者上站時, 密碼驗證通過之後當場轉成新的 hash funciton 寫回檔案. 由於帳號太久沒用會被砍掉, 所以理論上幾個月之後全站就能轉換完成.

function

上述計算顯示暴力逐一破解是 不可行 的(不過忘了寫上結論,還請見諒)。但若破解 6 碼密碼已有一定難度,設定 32–64 碼長的密碼眞的有必要嗎?(不過,由於人造密碼遠弱於隨機密碼,還是需要 > 8 碼密碼以彌補其強度)

DreamBBS 之密碼最長 36 (= PLAINPASSSIZE - 1),一是防 collisions(必要性或可議),二是防 vget() 輸入框溢出畫面(雖後已隱藏顯示),三是防誤按鍵盤過度會連打退格鍵過度(?)。

由於站臺之 社會角色之差異,DreamBBS 未啟用賬號退場機制,也無法有效籍助 忘記密碼 之功能,因此無法採取批踢踢的策略,僅能無限期同時持續支援 DES 與 SHA-256 之 hash 方式,並預設對新密碼使用 SHA-256 hashing。

即使密碼長度不變,改用非 DES hashing 仍有一定作用。考慮 DES hashing 每碼僅 lower 7 bits 有效,8 碼密碼至少可有 2⁸ = 256 種 hash 相同的輸入。超出 8 碼的話,hash 相同的輸入爲 223ⁿ⁻⁸ 倍。
但這也對 滾動式密碼自動更新 造成窒礙。

另外,由於 checkpasswd() 會把原密碼抹除,所以驗證後取不到原密碼(雖然可以修改程式以 類繞過)。見 https://github.com/ptt/pttbbs/blob/2fae7442d4/common/bbs/passwd.c#L224

from pttbbs.

chhsiao1981 avatar chhsiao1981 commented on July 18, 2024

覺得目前更重要的是如何在 login 成功以後.
在 UI 上如果發現 user 的 password "太簡單".
引導 user 設定"不是太簡單的 password"

對於"不是太簡單的 password"的定義可以再討論. 我的提議是需字數 >= 7 + 含有 non-alnum 的 char.
(或是更高級的就是弄個 dict 把簡單 password set 放進去.)

(不論 crypt system 多強~ 只要 user 設定 password 是 1111 這種爛密碼~. 仍然是很容易被破~)

from pttbbs.

IepIweidieng avatar IepIweidieng commented on July 18, 2024

如果要儘可能維持與連線軟體的相容,又要有滾動式密碼自動更新的可靠驗證的話,以下方式或許可行。

假設 PttBBS 將採用 SHA-256 hashing。

  1. 需要允許在各 BBS 使用者家目錄下建立一個檔案,其內容爲 SHA-256 hashing。假設其名稱爲 sha256.passwd
    • 此資料僅於密碼更改的宣導期間使用,因此不宜併入 userec_t,否則宣導期結束後需再次更改資料結構,造成維護上的不便。
  2. 使用者登入時,若密碼驗證成功,爲 DES hashing,且 sha256.passwd 不存在的話,則用原密碼計算對應的 SHA-256 hash 並存入 sha256.passwd。(尚不更改 userec_t::passwd[]
  3. 使用者下次登入時,若密碼以 DES hashing 驗證成功,且 sha256.passwd 存在的話,就再以 SHA-256 hashing 驗證。
    • 若 SHA-256 hash 符合的話,就將 userec_t::passwd[]sha256.passwd 的內容覆蓋,並刪除 sha256.passwd
    • 若 SHA-256 hash 不符合的話,直接刪除 sha256.passwd,當作 1. 沒發生。
  4. 密碼更改的宣導期結束後,如果使用者的密碼仍使用 DES hashing,且存在有效的 sha256.passwd 的話,就以 sha256.passwd 的內容直接覆蓋 userec_t::passwd[],並刪除 sha256.passwd。否則萬一 sha256.passwd 存在的話,直接將之刪除。

此外,若以上任一階段被執行時,登入後會顯示相應訊息告知使用者說其密碼發生了什麼變化的話,可幫助使用者掌握其密碼的更新情況。

from pttbbs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.