在約 15 年前有嘗試想要自己做一個縮網址服務 (現在我做加長網址服務 XD),當時用來產生 string ID 的方法有弱點,被學弟抓出來打爆 (可以被預測下一個產生出來的 ID,然後建立 unliminted redirection)。最近摸到 crunch 這個工具,在重新思考以後,終於搞清楚向 ppt.cc 請教時得到的說明是什麼意思。
先說明有問題的作法,先建立 valid characters list,URL 有部份特出字元是 reserve character (RFC3986),所以像是 ?
、=
、@
等字元有特殊用途不能被拿來當作參數傳遞,然後做「N 進位」轉成 string ID:
<?php $char = ['a', 'b', 'c', '.....', '7', '8', '9', '0'];
例如:數字是 1
時,產生出來的 ID 是 a
、數字是 116
時產生出來的 ID 是 a1
。當時我是依照流水號,所以 ID 是可以被預測的,導致弱點被利用。
當時得到 ptt.cc 的回覆是「先產生完 key 再隨機選取可用的 key」。
這陣子才搞懂這個說明,先用 crunch 之類的工具把所有可用的 string 都先產生出來,然後需要時再隨機選取一個 string 來當作 key/ID 使用。這個作法有些優點:
- 不需要先產生所有的 key,因為大概可以推算出大概可用的 ID 數量
- 隨機挑選 key 就無法被猜到未來會被用到的 key,不容易被攻擊
接下來要傷腦筋的,大概就是怎麼樣有效率的從 DB 隨機取 key 了。
ps. 目前使用 3 個 digits,大概就有 20 多萬個 unique string 可用了,爽。