ptt 最近发了一个功能叫做 /recover
所以我就顺手看了一下相关的 source code: https://github.com/ptt/pttbbs/blob/master/mbbsd/recover.cc
详见: https://www.ptt.cc/bbs/SYSOP/M.1603325969.A.7F6.html
大家都知道 random number 是很容易有机可趁的东西
只要你的 seed 跟算法被知道, 那大多都是可预测的
ptt 的整个登入流程大概是, 接收 client, 然后 fork 出来服务
所以每个 client 都会有独立的 pid
而 ptt 在 login 时就决定了 random seed
详见: https://github.com/ptt/pttbbs/blob/7296640ed0d9885c8494b7d63809858996d9e56d/mbbsd/mbbsd.c#L1433
ptt 的 random 算法则是用 glibc 内标准的算法
https://github.com/ptt/pttbbs/blob/master/include/cmdiet.h
recover 功能的流程大概是这样的:
1. /recover 打下去先给你一段 recaptcha
2. 验证后输入 username 以及 email
3. 发 token 到你的 email
4. 验证 token 并 reset password
其中第一个步骤的 recaptcha 就含有了 random 产生的 text
例如它会给我这段: https://www.ptt.cc/captcha?handle=DefWcEgFufbhWYeGtfTCWaWUaxLWcUwd
handle 后面的 32 位元 text 其实就是由:
https://github.com/ptt/pttbbs/blob/7296640ed0d9885c8494b7d63809858996d9e56d/mbbsd/captcha.c#L190
这里来的, 这意味着我只要透过暴力方式, 先跟 ptt server 上校正好时间, 那剩余的变量就是 pid 了
由于这会是第一个 random text, 所以我只要把 mysrand() 内的 srandom(time(NULL) + getpid());
其中的 getpid() 用暴力法, 然后能产生跟我画面上看到的 32 bytes 字串一样的值
那等于我已经破解了这个 login session 之后会产生的 random text
之后上面流程中的第四步, 就算我不知道正确的 code (不是 email 本人)
也能破解掉任意使用者并 reset password
因为它也 random text 来的 30 bytes: https://github.com/ptt/pttbbs/blob/7296640ed0d9885c8494b7d63809858996d9e56d/mbbsd/recover.cc#L153