Comments (10)
第一限制: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
),仍會觸發複製,浪費無法避免。
- 雖然 Linux 的
- 註:某些 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.
所以這時要讓使用者再輸入一次確認?
我覺得可以有個宣導期,過了之後登入強迫改密碼。
from pttbbs.
- ptt 的 crypt 函式是我換的, 該函式的確只支援 DES crypt, 不過我想另外找一個 library 來用應該不是太大的問題. 當然 @IepIweidieng 建議的解法也可以嘗試.
passwd[]
大小的確不夠, 因此需要擴增欄位, 關站轉換檔案格式. 不過因為只需要存密碼的 salt 跟 hash, 空間不一定需要用到 @IepIweidieng 說的那麼大.
p.s. 如果要做, 記得 "取備份" 這功能要特別處理, 以免拿舊欄位蓋掉新的資料, 可能會造成資料錯亂的問題.- 基本上不會採用逆推原密碼的方式處理這個問題. 比較簡單的做法是, 同時支援新舊方式, 當使用者上站時, 密碼驗證通過之後當場轉成新的 hash funciton 寫回檔案. 由於帳號太久沒用會被砍掉, 所以理論上幾個月之後全站就能轉換完成.
from pttbbs.
DES crypt...
from pttbbs.
- 基本上不會採用逆推原密碼的方式處理這個問題. 比較簡單的做法是, 同時支援新舊方式, 當使用者上站時, 密碼驗證通過之後當場轉成新的 hash funciton 寫回檔案. 由於帳號太久沒用會被砍掉, 所以理論上幾個月之後全站就能轉換完成.
直接在背後轉換會有問題,因為 crypt 現在只吃 8 碼,但登入可以打超過 8 碼(logind 吃 14 碼),在背後轉無法確認超過的部分是不是使用者想要的,如果在轉換的那次不小心 8 位以後輸入錯誤,之後會無法登入。
from pttbbs.
直接在背後轉換會有問題,因為 crypt 現在只吃 8 碼,但登入可以打超過 8 碼(logind 吃 14 碼),在背後轉無法確認超過的部分是不是使用者想要的,如果在轉換的那次不小心 8 位以後輸入錯誤,之後會無法登入。
good point. 所以這時要讓使用者再輸入一次確認? 不過這樣大概會讓很多做自動 login 的 app 壞掉 XD
from pttbbs.
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[]
的話,大可不必如此切割。
- 基本上不會採用逆推原密碼的方式處理這個問題. 比較簡單的做法是, 同時支援新舊方式, 當使用者上站時, 密碼驗證通過之後當場轉成新的 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.
覺得目前更重要的是如何在 login 成功以後.
在 UI 上如果發現 user 的 password "太簡單".
引導 user 設定"不是太簡單的 password"
對於"不是太簡單的 password"的定義可以再討論. 我的提議是需字數 >= 7 + 含有 non-alnum 的 char.
(或是更高級的就是弄個 dict 把簡單 password set 放進去.)
(不論 crypt system 多強~ 只要 user 設定 password 是 1111 這種爛密碼~. 仍然是很容易被破~)
from pttbbs.
如果要儘可能維持與連線軟體的相容,又要有滾動式密碼自動更新的可靠驗證的話,以下方式或許可行。
假設 PttBBS 將採用 SHA-256 hashing。
- 需要允許在各 BBS 使用者家目錄下建立一個檔案,其內容爲 SHA-256 hashing。假設其名稱爲
sha256.passwd
。- 此資料僅於密碼更改的宣導期間使用,因此不宜併入
userec_t
,否則宣導期結束後需再次更改資料結構,造成維護上的不便。
- 此資料僅於密碼更改的宣導期間使用,因此不宜併入
- 使用者登入時,若密碼驗證成功,爲 DES hashing,且
sha256.passwd
不存在的話,則用原密碼計算對應的 SHA-256 hash 並存入sha256.passwd
。(尚不更改userec_t::passwd[]
) - 使用者下次登入時,若密碼以 DES hashing 驗證成功,且
sha256.passwd
存在的話,就再以 SHA-256 hashing 驗證。- 若 SHA-256 hash 符合的話,就將
userec_t::passwd[]
以sha256.passwd
的內容覆蓋,並刪除sha256.passwd
。 - 若 SHA-256 hash 不符合的話,直接刪除
sha256.passwd
,當作 1. 沒發生。
- 若 SHA-256 hash 符合的話,就將
- 密碼更改的宣導期結束後,如果使用者的密碼仍使用 DES hashing,且存在有效的
sha256.passwd
的話,就以sha256.passwd
的內容直接覆蓋userec_t::passwd[]
,並刪除sha256.passwd
。否則萬一sha256.passwd
存在的話,直接將之刪除。
此外,若以上任一階段被執行時,登入後會顯示相應訊息告知使用者說其密碼發生了什麼變化的話,可幫助使用者掌握其密碼的更新情況。
from pttbbs.
Related Issues (20)
- whence in PttLock should be SEEK_SET? (or PttLock after lseek should set offset as 0?) HOT 4
- 請問如何找回ID和密碼 HOT 5
- (Forwarded from PttBug)「登入次數」的累計盲點 HOT 2
- Some articles in the searching result for the word "初音" are missing in board C_Chat HOT 1
- 可用單一信箱多次認證 HOT 2
- Split out common code for deleting users
- Use ngx.exit(444)
- Add SO_REUSEPORT support to logind HOT 1
- User ID rename does not update regemaildb
- Email input length hardcoded HOT 1
- [Bug] Ptt web search logic error HOT 2
- logind compile error HOT 2
- 使用 Mac 連上 term.ptt.cc,在發表文章/發送站內信時按下 ^ + X 沒有任何反應 HOT 4
- 看板下面的 bar 在特定情況下會消失
- [propose] Replace .PASSWDS with DB (mongodb) HOT 6
- BRD_WARNEL 的註解有錯
- Possible one more i++ in cmsys.strip_nonebig5? HOT 1
- 關於 SHM 沒有加上 volatile 這件事 HOT 10
- [資訊] 如果你收不到認證信的話 HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pttbbs.