2021年2月21日 星期日

分享「破解密碼」的經驗

提醒程式開發人員 許多文章及書籍都告戒「密碼應經雜湊(hash)或『經驗證』的強加密演算法處理後再保存

某券商的網路下單系統,在登入後或變更密碼時,會將此密碼編碼並紀錄在Cookie裡,本文將說明如何破解從此Cookie內容而得到明文密碼。基於職業道德,不便提供此下單系統的網址及細部資訊

每次變更密碼後,檢視回應(response)的標頭(header)發現LoginPWD欄位值的長度是4的倍數(圖1),且字元符合BASE64編碼形式,猜測密碼是利用BASE64編碼後再記錄到Cookie,但是解碼LoginPWD的值卻得到亂碼(圖2),而非原來的密碼明文,推測「執行BASE64編碼前,密碼應該還進行其他編碼處理」。既然使用BASE64 to Text得到亂碼,只好改用BASE64 to Hex來觀查解碼後的內容(圖3)。

圖1:檢視回應內容的標頭資訊

 
圖2:直接解碼只得到亂碼
圖3:使用BASE64 to Hex查看解碼後的結果

要破解密碼,當然不會只使用一組資訊,下表是筆者以不同的密碼得出下單系統回傳的LoginPWD值,並和該密碼的BASE64編碼進行比較。

NO 密碼 直接BASE64編碼 密碼的Hex LoginPWD 解碼成Hex
1 AaBbCcDdE012 QWFCYkNjRGRFMDEy 416142624363446445303132 AZiE4EEKG79Npb05nw== 019884E0410A1BBF4DA5BD399F
2 AaBbCcdDe012 QWFCYkNjZERlMDEy 416142624363644465303132 AZiE4EEKO59tpb05nw== 019884E0410A3B9F6DA5BD399F
3 ABC123456789 QUJDMTIzNDU2Nzg5 414243313233343536373839 AbuFszBaa+4+orQynw== 01BB85B3305A6BEE3EA2B4329F
4 abc123456789 YWJjMTIzNDU2Nzg5 616263313233343536373839 IZulszBaa+4+orQynw== 219BA5B3305A6BEE3EA2B4329F
5 ABC123 QUJDMTIz 414243313233 AbuFszBaXw== 01BB85B3305A5F
6 abc123 YWJjMTIz 616263313233 IZulszBaXw== 219BA5B3305A5F

從上表可以找出幾個現象

  1. 當密碼長度不一樣時,LoginPWD的長度也不一樣,但仍維持4的倍數
  2. LoginPWD的長度都比直接BASE64編碼多出4個字元,如上表LowinPWD欄的粗藍字。
  3. 由於筆者測試的密碼都是3的倍數,而LoginPWD出多的4字元之後兩碼皆為==,依照BASE64的規則,代表有2個填充字元,推測下單系統會先在原密碼之後附加1字元再執行編碼。
  4. 比對各組密碼,相同位置相同字元,對應的LoginPWD內容也相同,如項次3及5紅字部分。

開始思考開發者可能使用的編碼方式

  1. 是不是使用對照表轉換BASE64的編碼字元?
    但從上表項次1或2的黃底字看到kN都對應到E,顯然不合理。
  2. 是不是使用特定KEY進行轉碼?
    試著將「密碼的Hex」與「解碼成Hex」的值進行XOR運算(「解碼成Hex」的最後一碼是附加的,故先捨棄),結果如下表的「XOR結果」欄
NO 密碼 密碼的Hex 解碼成Hex XOR結果
1 AaBbCcDdE012 416142624363446445303132 019884E0410A1BBF4DA5BD399F 40F9C68202695FDB08958C0B
2 AaBbCcdDe012 416142624363644465303132 019884E0410A3B9F6DA5BD399F 40F9C68202695FDB08958C0B
3 ABC123456789 414243313233343536373839 01BB85B3305A6BEE3EA2B4329F 40F9C68202695FDB08958C0B
4 abc123456789 616263313233343536373839 219BA5B3305A6BEE3EA2B4329F 40F9C68202695FDB08958C0B
5 ABC123 414243313233 01BB85B3305A5F 40F9C6820269
6 abc123 616263313233 219BA5B3305A5F 40F9C6820269

從上表的「XOR結果」得到如下結論

  1. 從項次1到6的XOR結果,可知下單系統會逐字元進行XOR處理。
  2. 由項次5多出來的「5F」,與項次4同一位置的KEY相同,得知下單系統附加的字元是ASCII的NUL字元(十六進制碼 00)。

目前解得35碼的XOR Key值是「40F9C68202695FDB08958C0B9F74F518BC6361D42F22998F31B2895B67BF64AA505D528E」,亦即「0x40,0xF9,0xC6,0x82,0x02,0x69,0x5F,0xDB,0x08,0x95,0x8C,0x0B,0x9F,0x74,0xF5,0x18,0xBC,0x63,0x61,0xD4,0x2F,0x22,0x99,0x8F,0x31,0xB2,0x89,0x5B,0x67,0xBF,0x64,0xAA,0x50,0x5D,0x52,0x8E」

知道XOR的Key值後,就能對任意LoginPWD進行解碼,步驟如下:

  1. 先將LoginPWD進行BASE64 to Hex解碼,得到十六進制結果,以HEX表示。
  2. HEX的最右邊的Byte捨棄,因它是附加的字元NUL,無關緊要。以HEX2表示。
  3. 從XOR Key的左邊取出和HEX2等長的資料,以KEY2表示。
  4. HEX2KEY2進行XOR
  5. 將得到的十六進制值轉成ASCII即得到密碼明文。

就以「LoginPWD: E62TszBaa+4+orQynw==」為例:

  1. 先將「E62TszBaa+4+orQynw==」進行BASE64 to Hex解碼,得到「13AD93B3305A6BEE3EA2B4329F」。
  2. 將「13AD93B3305A6BEE3EA2B4329F」最右邊的Byte(即9F)捨棄,剩12Byte。
  3. 從XOR Key的左邊取出12Byte,即「40F9C68202695FDB08958C0B」。
  4. 將「13AD93B3305A6BEE3EA2B432」與「40F9C68202695FDB08958C0B」進行XOR即得「535455313233343536373839」。
  5. 將「535455313233343536373839轉成ASCII,得到密碼明文「STU123456789」。

使用的線上工具如下

BASE64 編碼/解碼https://base64.guru/converter/decode/hex

XOR 計算器http://xor.pw/

ASCII/HEX轉換https://www.rapidtables.com/convert/number/hex-to-ascii.html

沒有留言:

張貼留言