JS逆向之5173password

篇幅有限

完整内容及源码关注公众号:ReverseCode,发送

抓包

登录URL:

POST https://passport.5173.com/?returnUrl=http%3A//www.5173.com/

参数:

1
2
3
4
5
6
7
8
9
smsLogin: 0
userName: 15806204095
password: 6a771c7ecf7ebe2c3d4c0075cdb96ae5
mobileNo:
smsCaptcha:
category:
passpod:
__validationToken__: 1680e6a3947c43aea45d83e69b0d7291
__validationDna__:

分析

password

password有32位,有可能是md5

搜索password,出现的地方太多了,懒得看,放弃。

image-20210417101520224

点击登录按钮,肯定触发事件发送请求,搜索submit-btn无效结果。

image-20210417101653242

搜索tnSubmit加上断点,点击登录按钮时,果然断在了这个function中,不过此刻Network面板的请求包已经发送出去了,gg了,没能拦截到https://passport.5173.com/?returnUrl=http%3a%2f%2fwww.5173.com%2f请求发送前的时间点。

image-20210417101856138

再一次尝试,在加密password时肯定要获取该输入框的值,通过id获取元素的话,我们搜索#txtPass在所出现的位置都打上断点

image-20210417102111667

点击登录时查看Network已经拦截在了ValidateSlide请求,还没有到登录请求

image-20210417102439074

查看断点时打印o为aec712a02d8c835b92369e5d7e5494cf,并直接跳到return $[["ajax"]]处,查看此时提交的data中的a[["serialize"]]()"smsLogin=0&userName=15806204095&password=aec712a02d8c835b92369e5d7e5494cf&mobileNo=&smsCaptcha=&category=&passpod=&__validationToken__=31004cd552c94687ba27d1c7258576f7&__validationDna__=",其中的password就是之前打印的o参数。

image-20210417102816463

由于password=o,现在只需要追踪这个o参数来源即可。往上追溯是onsubmit: function(f, o)中作为第二个参数o传递进来的,通过调用的堆栈查看上一级调用方法submitHandle。

image-20210417103714227

submitHandler这段代码返回a.onsubmit(a, c),其中c就是onsubmit: function(f, o) 中的o=password。由于a.usingTpm || a.passwordHash是true,那么这个c就是通过a.getPassword(a.pkey)获取。

image-20210417104004461

进入getPassword后,this.ready && this.activeTpm && this.usingTpm为false,必然进入的是else中的c = hex_md5(hex_md5(c).substr(8, 16) + a);实现加密。

image-20210417112035000

(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实现相互验证进行校验。

image-20210417113103632

__validationToken__

__validationToken__这个字段6b16902a6b134dc9a2c333b965c9405f在请求里面无法搜到是因为页面已经刷新,通过fiddler抓包https://passport.5173.com/?returnUrl=http%3a%2f%2fwww.5173.com%2f历史可以看到首页加载时传入该参数

image-20210417113838930

爬虫实现

首次先请求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加密结果,发起请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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逻辑已经破解,不过登录时还需要验证码滑块的校验,以后有时间再写吧。。。

文章作者: J
文章链接: http://onejane.github.io/2021/04/17/JS逆向之5173password/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 万物皆可逆向
支付宝打赏
微信打赏