JS逆向之5173分析加密password
篇幅有限
完整內容及原始碼關注公眾號:ReverseCode,傳送 衝
抓包
登入URL:
POST https://passport.5173.com/?returnUrl=http%3A//www.5173.com/
引數:
smsLogin: 0
userName: 15806204095
password: 6a771c7ecf7ebe2c3d4c0075cdb96ae5
mobileNo:
smsCaptcha:
category:
passpod:
__validationToken__: 1680e6a3947c43aea45d83e69b0d7291
__validationDna__:
分析
password
password有32位,有可能是md5
搜尋password,出現的地方太多了,懶得看,放棄。
點選登入按鈕,肯定觸發事件傳送請求,搜尋submit-btn
無效結果。
搜尋tnSubmit
加上斷點,點選登入按鈕時,果然斷在了這個function中,不過此刻Network面板的請求包已經發送出去了,gg了,沒能攔截到https://passport.5173.com/?returnUrl=http%3a%2f%2fwww.5173.com%2f
請求傳送前的時間點。
再一次嘗試,在加密password時肯定要獲取該輸入框的值,通過id獲取元素的話,我們搜尋#txtPass
在所出現的位置都打上斷點
點選登入時檢視Network已經攔截在了ValidateSlide請求,還沒有到登入請求
檢視斷點時列印o為aec712a02d8c835b92369e5d7e5494cf
,並直接跳到return $[["ajax"]]
處,檢視此時提交的data中的a[["serialize"]]()
為"smsLogin=0&userName=15806204095&password=aec712a02d8c835b92369e5d7e5494cf&mobileNo=&smsCaptcha=&category=&passpod=&__validationToken__=31004cd552c94687ba27d1c7258576f7&__validationDna__="
由於password=o,現在只需要追蹤這個o引數來源即可。往上追溯是onsubmit: function(f, o)
中作為第二個引數o傳遞進來的,通過呼叫的堆疊檢視上一級呼叫方法submitHandle。
submitHandler這段程式碼返回a.onsubmit(a, c),其中c就是onsubmit: function(f, o)
中的o=password。由於a.usingTpm || a.passwordHash
是true,那麼這個c就是通過a.getPassword(a.pkey)
獲取。
進入getPassword後,this.ready && this.activeTpm && this.usingTpm
為false,必然進入的是else中的c = hex_md5(hex_md5(c).substr(8, 16) + a);
實現加密。
(c = b("#" + this.passwordControlId).val()) && this.passwordHash
賦值必然是true,其中(c = b("#" + this.passwordControlId).val())
的結果為123456,即我們輸入的密碼,由於傳入的a為42m2gl
,所以加密邏輯整理為c = hex_md5(hex_md5("123456").substr(8, 16) + "42m2gl")
那麼問題來了,傳入的a是哪裡來的,通過搜尋42m2gl,原來每次頁面生成的時候頁面會載入PasswordKey,通過PasswordKey和SecurityToken等key實現相互驗證進行校驗。
__validationToken__
__validationToken__這個欄位6b16902a6b134dc9a2c333b965c9405f
在請求裡面無法搜到是因為頁面已經重新整理,通過fiddler抓包https://passport.5173.com/?returnUrl=http%3a%2f%2fwww.5173.com%2f
歷史可以看到首頁載入時傳入該引數
爬蟲實現
首次先請求https://passport.5173.com/?returnUrl=http%3a%2f%2fwww.5173.com%2f
獲取頁面中的PasswordKey的值和SecurityToken的值,通過兩次md5密碼hex_md5(hex_md5("123456").substr(8, 16) + "42m2gl")
拿到password加密結果,發起請求。
def hex_md5(s):
m = hashlib.md5()
m.update(str(s).encode("utf-8"))
return m.hexdigest()
headers = {
'Host': 'passport.5173.com',
'Origin': 'https://passport.5173.com',
'Pragma': 'no-cache',
'Referer': 'https://passport.5173.com/?returnUrl=http%3A//www.5173.com/',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
}
login_url = 'https://passport.5173.com/?returnUrl=http%3A//www.5173.com/'
html = requests.get(login_url).text
# print(html)
securityToken = re.findall('SecurityToken:"(.*?)",', html, re.M | re.S)[0]
passwordKey = re.findall('PasswordKey:"(.*?)",', html, re.M | re.S)[0]
print(passwordKey)
print(securityToken)
# 滑塊 'https://passport.5173.com/Sso/ValidateSlide?token={}'.format(securityToken)
# hex_md5(hex_md5("123456").substr(8, 16) + "42m2gl")
password = hex_md5(hex_md5("123456")[8:8 + 16] + passwordKey)
userName = '15806204096'
data = {
'smsLogin': '0',
'userName': userName,
'password': password,
'mobileNo': '',
'smsCaptcha': '',
'category': '',
'passpod': '',
'__validationToken__': securityToken,
'__validationDna__': ''
}
r = requests.post(login_url, data, headers=headers)
print(r.text)
雖然password邏輯已經破解,不過登入時還需要驗證碼滑塊的校驗,以後有時間再寫吧。。。
本文由部落格一文多發平臺 OpenWrite 釋出!