逆向破解随手记前端实现自动化登录、对账全记录
前言
现实中的朋友应该知道我之前实现了一个基于图片识别的自动对账程序。虽然大大减少了月初对账的工作量,但是客观上来看还是不够方便。今天吃的比较空,想要增加自动化登录、读账、转账功能。
逆向客户端说实话难度过高了,纯靠抓包又担心自己技术力不够,但是我发现这玩意是有一个网页端的,于是就想到捡起老安全本行来分析一下web前端。
我作为一个只有二进制安全和业余web开发背景的游戏服务器开发,做这玩意还是费了一点脑细胞的。
本文将省略我烧脑细胞的过程与走的歧路,直接以完成者的身份进行复盘。
登录体验流程并拆分问题
随手记的主登录网站为https://www.sui.com/。

点击登录按钮跳转到https://login.sui.com/。

输入密码后,进入主界面https://www.sui.com/report_index.do。此处用体验账户替代下避免发现我囊中羞涩了。

记一笔界面,可以进行转账

经过流程体验后,可以将两个需求拆分为以下子问题
login.sui.com如何将密码、账号转换成请求发送到服务器认证- 认证流程,是否分为多步,是否需要
cookie中转。是否存在无状态的请求。 login.sui.com认证后如何解决和www.sui.com的跨域问题www.sui.com的数据请求结构。是html中内嵌的数据,还是ajax请求的?www.sui.com如何操作转账,是ajax吗?web app的架构?这可以提供一些标准化分析以外的助力。
登录分析
打开f12打开保留日志功能并重复全过程。

排除没有什么卵用的一些选项后我们筛选出了以下部分。(此处可以按住ctrl多选切页)

这里我发现.do后缀大量出现。于是我做出判断,这玩意是jsp写的。。。(2022年了兄弟,整点阳间活吧)。
浅看以下流程发现登录部分似乎可以分为以下几步
- 请求主网页
- 向登录网页发送一个
https://login.sui.com/auth.do?nnl=yes&returnUrl=https://www.sui.com/sso/jsonp_login.do看上去像是用来进行某种绑定的。 - 发送一个
https://www.sui.com/sso/jsonp_login.do。看见sso,我们顿时明白了,这是个跨域单点登录。这个请求应该是用来对session进行某一种认证,允许带这个session的客户端进行跨域或者别的什么功能。 - 请求
login主网页 - 根据请求时间判断,点击按钮后发送了
https://login.sui.com/login.do?opt=vccode&callback=jsonp1661009746432。这个是个jsonp请求具体我就不说了,功能是向服务器跨域请求vcccode。 - 紧接着发送了一条
https://login.sui.com/login.do?email=这里被我替换了&status=0&password=真的被我替换了哦&uid=0f68替换-2d9f-4c22-9e75-f9f7替换d7b8&callback=jsonp1661009746433。这个都不用说了,一眼鉴定为登录主请求。 - 发送一条
https://login.sui.com/auth.do这个似乎是login的后续操作。 - 顺利访问
分析下login.do这个请求,发现email列是我的手机号也就是账号。

那问题转换为如何获得这个password的签名逻辑和这个uid。
此时我打开启动器标签试图寻找登录主函数,发现是login.sui.com的login函数

此时我去找源代码,发现已经跳转到www.sui.com后不显示login的代码了

于是我返回login页,找到290行的登录函数

非常的言简意赅,毫无加密。于是跳转到fdLogin去找


可以看出上面是个hash函数和base64的源码。中间是个请求vccode和uid的ajax。后面是一个登录主函数。多次签名后上传。
搞清楚功能后,我们继续分析,这个请求的结果。
一个请求的效果只可能是以下几种
- 改变服务器状态
- 改变请求中携带
cookie的某种服务状态 - 改变服务器资源
- 改变请求中携带
- 改变客户端状态
- 传回某种结果
- 设置某种
cookie
首先分析是否存在返回的token

发现respond是空的。
之后检查cookie

这里我一瞬间尬住了,设置__newAuth为空是什么鬼。走了一些弯路后,我去翻了下respond的header。
发现他发了两个setcookie。。。f12害我不浅。

基本可以确认这个__newAuth是某种认证码。但是我们还是需要确认下,是否有某种session被认证了。于是我们看了下cookie发现两个非常可疑的cookie JSESSIONID 和 SESSION_SSO。看名字我们就可以发现,一个是存sessionid的,一个是存跨域session的。于是我们找一下哪里设置到了这个cookie。翻阅了下所有的相关同域的请求,发现前面有一个请求,带着set-cookie。而且这个是个典型的sso请求认证。我们怀疑是在这里将login.sui.com和www.sui.com关联起来的。

我们继续跟进__newAuth,发现他在接下来的auth.do中被使用。

事实上我们翻阅源码的话也能简单发现,他们存在连续关系。

auth.do返回了一个新cookie

之后我们再向下分析可以发现,report_index.do就已经是业务逻辑了

且里面并不含login的session。那么我们就有一个问题,现在www.sui.com怎么知道这个session对应的人就是我们再login.sui.com里经过认证的session对应的人呢。我们猜测一定有一个可以跨域的东西将两者关联起来。但是我们请求了这么多次状态都有点脏了。于是我清除掉login和www的cookie重新进行了f12。
此时我发现在第一条请求www.sui.com的请求中,隐含了一个可疑的cookie。

这个__vistor的域是sui.com,显然某个共享的session。
于是找到第一个https://login.sui.com/auth.do?nnl=yes&returnUrl=https://www.sui.com/sso/jsonp_login.do,果然

我们尝试了一下,登录后不退出直接访问www.sui.com。果然也是经过https://login.sui.com/auth.do?nnl=yes&returnUrl=https://www.sui.com/sso/jsonp_login.do后跳转jsonp_login.do后跳转到正式界面。
此时我们可以确认这个__vistor就是连接login和www的桥梁。
我们找到登录的位置发现,果然认证时也会带着__vistor.

总结
我们可以简单的得出结论。(此处不考虑状态不对,或失败的分支,我们来着是写脚本的,不是来帮随手记理流程图的)。
- 访问
www.sui.com时会发回两个局部的cookie,session、session_cookie,和一个全局cookie__vistor - 之后会带着
__vistor访问login.sui.com的auth.do,如果之前有登陆过还会带着jsessionid和session_sso过去。此时login会根据这三个状态判断,是否为已经认证的有效session。如果是他会跳转到jsonp_login,然后让jsonp跳转到主界面。如果不对,会在发回的cookie中带上jsessionid,session_sso。 - 点击登录跳转到
login.sui.com - 点击登录按钮,请求
vccode和uid。随后将账号、密码、vccode、uid加密后发送到login.sui.com。获得__auth。 jquery触发auth.do,将__auth和__vistor、jsessionid、session_sso,发生到login.sui.com进行认证- 带着
session、session_cookie、__vistor访问主界面。猜测他们服务器内部会根据__vistor去login寻找是否认证,而我们之前认证过了。就会将本地的session认证为合法。 - 之后带着
session、session_cookie、__vistor就有权限访问所有资源了。
这里其实逻辑上还是有缺陷的。因为我没有随手记的源码,也没有进行大规模的试验。因此我是不清楚__vistor在认证中的具体用处,如果session、session_cookie是新发送的,__vistor是旧的,会引发什么问题。session、session_cookie的区别是什么,jsessionid、session_sso具体的区别用处是什么。这些我都不知道的。但是这都是些细枝末节的问题。
说实话这套逻辑还是比较扭曲的,写起来好像容易,但是我当初找逻辑找了半天。。。当然我web知识比较欠缺也有一定的关系。很多知识都是现学的,对于这些比较通用的逻辑也缺乏认知。当然现在一般都是用oauth2了,这种sso逻辑也不多了。
登录实现
我使用postman尝试了总结中的逻辑,可以成功获取权限。之后可以编写自动化代码,就是非常简单的requests和session处理,这里就不贴了。
账本与转账分析
账本分析
切换到账目页

f12中搜索账户名 支付宝。

发现数据在accout.do中。
展开accout.do的代码进行分析

发现这里有一个id-名字列。根据id进行进一步搜索。发现一处形似余额的。

翻开随手记app查了下,余额可以对上,至此,余额提取完毕。
- 根据名称找到ID
- 根据ID找到余额
正则
提取ID "(\d*)": "(.*)",

提取余额
<a href="javascript:;" id="acc-money-(\d*)" onclick="acc\.edit\.click\('amount', (.*)\);" class="j-not edit">
.*<span class="child-r1-money">(.*)<\/span>


代码
请求下来的html套一下正则就行,多的就不说了。
转账分析
试着转一笔
f12监听到请求

查看一下参数

果然就是我们上一步提取出的ID。
使用post模拟发包,可以重现。
进一步使用postman测试发现,不写time,默认为当前服务器时间。
代码
不说了,就是发一个post
感想
- 写的好累,分析+写博客忙了半天。
- 写的好乱,勉强入目,也缺乏条理。
markdown对于这样的多图文章支持有点差只能这样一句一图。而不是和论文一样。写一段中间标注图1图2图3。然后图片缩略嵌在中间。 - 多图杀猫,我还要打马赛克避免个人隐私泄漏。
- 本地
typora写完,上传博客时还得一张张图片上传简直是。。。。 - 手写了一个自动将markdown中不含中文、换行符、空格且不以``包围的英文单词自动加反引号包围的正则,省力多了
- mac键盘习惯了,反而觉得现在茶轴手感差了。也经常按错键。