一次有趣的賬戶接管漏洞挖掘
這是一枚弱加密配合IDOR利用,從而導致完全接管他人帳戶的漏洞。
為了方便稱呼,以后咱們就統一叫白帽子小哥為“小白”好了。
最近小白同學經常讀到一些帳戶接管漏洞的文章,他們通常是利用“X-Forwarded-Host”頭來竊取用戶Token從而進行賬戶接管,于是乎小白也想著動手嘗試嘗試,他在某個漏洞賞金平臺中接受了一項賞金任務,并嘗試尋找帳戶接管漏洞。當然,他成功了!
漏洞存在于“密碼重置”功能,通過該功能可以完全接管任意帳戶,且無需用戶進行任何交互。
第1步:
用戶通過"example.com/php/login_or_password_forget",在輸入用戶個人ID和姓名后,開始請求重置密碼;
第2步:
他們的用戶ID和姓名得到驗證后,將生成一個“state”參數,像下面這樣:
STATE=eJxdkN1OwzAMhd8lDzA1XffT9GpMDE2gdmKTuIxM4paILilJJhBo747DfjRxlfhzYp9zGpHPBduaryiXzqN8wdeVhz1%2BOv8utxEiMsHFTxATwcJfWYEoEpgKppxtTZfIOJGSSG%2FQRmkGVgXBC8H4ZDYq8hHnfMSnZaL0r3cKekwFTUUrH%2B7SnXT0YLsDdP9aRxo1E6y96hrAR4ueVY3Iy1v1i81abk7Ny8loIWkjKQcLe1bVNDrPBHuDIHuEYGwnyUf0oCKrXkWWhFPfo3KdNd%2Bob6k0FiOt34cLJTvy4wD9FZANCVp7DCFtO4vfPS%2Fq7WK5Wze13DWP93WyOM4FgxJn7VgrBS2fTzVqzDLFVY4cs2Le6vSuTMmESL5P0RT8bHrjXWt68j0M8sl1xjZ%2BAyFQSHrlfOdidJbyO%2F4CvKKcYg%3D%3D55840ad4a2f32819aa5da2cf48288290
第3步:
在這一步中,廠商將向用戶注冊的電子郵箱發送密碼重置鏈接,如下所示:
https://example.com/php/login_or_password_forgotten?k=789c0dc8610a80200c06d0bbec049bc9d26f870921834192a4ffa2bbd7fbf90a029e810c9adeea98a5753287a844e16555b1016150bfafc3cfbaf94eff2450e494a2e640f67ebc89137aade927d25a020ab2535ab4b5c9dc4fd1
第4步:
用戶通過點擊重置鏈接后跳轉至修改密碼界面進行密碼更改。
有趣的部分
這個“?k”參數看起來有不是有點眼熟?小白將其粘貼至CyberChef(經常打CTF比賽的一定對這款工具不陌生吧)中,小白驚訝的發現它確實是一個加密+壓縮的字符串:

這段字符串首先使用zlib壓縮,然后再進行16進制轉換。
經過CyberChef解密后的字符串中,小白發現了兩個重要變量“profile_id”和“timeStamp”,于是小白立即建立了另一個賬號,嘗試偽造第二個賬戶令牌,以期望重置這個賬戶的密碼,偽造的字符串如下:
789c0dc8510a85201005d0bdcc0ac6f25da6eb62427806034992fe457bb7df93b9f0e9dc28c36be923d726c919107ec0aa40ea0c4a69f775f85976ffcb2746891a610693f44ebe171387
但是很遺憾,點擊重置鏈接后,提示該鏈接不可用。

轉折
如果仔細觀察,我們會發現原始令牌和偽造的令牌長度是不一致的:

原始令牌和偽造的令牌相差了32個字符,這是一個很大的問題,因為服務器肯定不會接受任意32個字符,但是兩個令牌被解密后,卻是相同的值,即:
“a:2:{s:9:”timestamp”;i:1614104013;s:10:”profile_id”;s:8:”40884692";}”.
這讓小白同學非常沮喪??,于是他開始查看更多關于Zlib壓縮的文章,在經歷了2小時的各種閱讀后,小白同學發現Zlib包含了一個ADLER32校驗值,如果你在使用Adler-32_checksum()函數后,將會得到“BC89137A”,并且這個校驗值會存在于原始令牌中,在Zlib中,該校驗值之后的所有內容都不是壓縮流的一部分,因此將會被忽略,這就是為什么兩個令牌即使在長度不同,也會產生相同結果的原因!
所以是時候挑戰這個32位的字符串了,因為所有與令牌相關的工作一般都會客戶端進行,所以小白同學嘗試在JS文件中尋找線索。
在查看了幾個小時的JS文件后,小白發現了一處“/php/user”的URL,于是他嘗試爆破目錄,最終小白找到了“https://example.com/php/user/example/”,該URL有一個名為“transctionToken”的字符串,實際上這正是要找的最后32位字符串的內容。
拼接
是時候將字符串進行拼接了,由于每次刷新頁面時“Transaction _Token”都會發生變化,于是小白同學寫了一個Python腳本來自動化整個過程,于是他成功的生成了“受害者“賬戶的令牌,并利用重置鏈接,更改了該用戶的密碼。
心得
- 如果有令牌,那么就存在被破解的可能
- 不要忘記JS文件,因為這些文件往往包含了有關Web的重要信息
- 試著在一些社區詢問技術細節,有時會有你驚喜的結果
- 相信你的直覺,比別人多做一點!