对学校学生APP的一次抓包分析
# 前言
本文包含个人主观情绪(被气坏了),非纯教程文章
之前做课表 APP 做上瘾了,但因为教务系统的功能主要还是看课表,抢课教评什么的一学期就那一两次,真正日常常用的功能还是在学校委托第三方(或者是自己开发的?)做的 APP 上。
当然,APP 还是继承国内 APP 的优良传统之典中典 Web APP,所以自己实现难度不大。
其实最主要还是 APP 太 shit 了,有时候启动卡半天不知道在干嘛,还有很多无用的信息(对于我自己来说),因此打算一不做二不休,自己做个第三方的
这次先打个头阵,对 APP 进行抓包分析。
# 初步分析
APP 采用统一 CAS 登录,和教务系统账号独立。
APP 内部所有页面无需重复登录,并且具有登录状态保持能力,因此一定使用了 cookie 或者其他技术保持登录状态,所有功能共享登录状态,而不是依靠浏览器 session
APP 内功能模块动态更新,考虑到是 Web APP,应该是通过更新 Web 页面或者相关 list 信息达到动态新增模块功能
# 抓包分析
# 登录模块
为保(liu)护(dian)隐(lian)私(mian)这里就不透露域名了,仅公布路径
md 一抓就绷不住了。。。
首先使用 POST 请求 /token/mfa/detect
,
header 为普通内容,不带任何具有 session 功能的内容
然后 body 为空
返回值如下
1 | { |
通过路径和返回值可以得出此次请求是获取 mfa 信息的,以便进行 mfa 验证,但是我们学校 app 貌似没 mfa 这个功能,所以这个检查可有可无。
但目前有个巨大的问题,POST 请求 body 为空,那服务器怎么知道用户信息呢?
没错,md 用户名和密码在请求路径中。。。。
完整请求路径为: /token/mfa/detect?username=学号&deviceId=设备ID(暂时未知如何生成)&password=明文密码
看到这我都气笑了,还 POST 什么啊,干脆直接 GET 得了。。。还明文传输密码,我们教务系统虽然用的是 HTTP,但人家至少密码还是通过 自研
算法加密了(不知道是不是单向的,真不如哈希加盐)才传输的,HTTPS 都表示自己无能为力。
言归正传,下面是真正登录请求
使用 POST 请求 /token/password/passwordLogin
请求 header 还是正常普通的 header,密码仍然是内嵌路径(已经懒得喷了),请求参数表如下:
Name | Value |
---|---|
username | 学号 |
password | 明文密码 |
appId | 固定值,为 APP 包名 |
geo | 空,不知道是干嘛的 |
deviceId | 设备 ID,和前面一样,不知道是怎么生成的 |
osType | 系统类型,这里是 Android |
clientId | 客户端 ID,不知道是怎么生成的 |
mfaState | 空 |
返回值如下:
1 | { |
就很好奇居然懂得用 JWT 了,为什么还会犯用 POST 请求路径传输明文密码这种低级错误,就很难蚌。
通过解析 JWT,可以得到下面信息:
JWT Header:
Name | Value |
---|---|
alg | (Algorithm)RS512 (RSASSA-PKCS1-v1_5 using SHA-512) |
JWT Payload:
Name | Value |
---|---|
ATTR_userNo | 学号 |
sub (Subject) | 学号 |
iss (Issuer) | cas 系统 Host |
deviceId | 设备 ID |
ATTR_identityTypeId | 用不上 |
ATTR_accountId | 用户 ID |
ATTR_userId | 用户 ID |
ATTR_identityTypeCode | S02 |
ATTR_identityTypeName | 学生 |
ATTR_organizationName | 班级 |
ATTR_userName | 姓名 |
exp (Expiration Time) | 过期时间,有效期一个月 |
ATTR_organizationId | 用不上 |
iat (Issued At) | 令牌创建时间 |
jti (JWT ID) | Id-Token-xxxxxxxx |
req | 包名 |
ATTR_organizationCode | 用不上 |
成功拿到 JWT 就简单很多了
后面还有个绑定 clientid 以及向 /openplartform/auth/api/token
的请求,不知道干啥用的,后面实测不请求也貌似没什么影响
openplartform 请求返回的 JWT 后面也没用上
# 拉取功能模块
在一堆没用的请求中终于找到了 server list 请求
向 /portal-api/v1/service/list
发送 POST 请求
header 中携带 JWT,具体如下:
1 | X-Device-Info: 我手机的型号 |
主要还是携带 JWT,剩下那几个 X-xxx 的内容都没必要,当然如果是打算伪装的话还是需要一起携带
然后 body 是空。。。
不是,真就不知道 GET 和 POST 怎么用是吧???
建议重新学习前端
返回的 json 包含一个 services
数组,里面就是整个 APP 所有的功能模块
数组内一个对象包含的对象一堆,但有用的就几个:
Name | Value |
---|---|
serviceName | 功能名称 |
servicePicUrl | 图标 |
serviceUrl | 功能页面地址 |
简单试了一下,请求 header 中携带 X-Id-Token: JWT
即可正常访问页面
# 后记
APP 具体开发要等到寒假,最近忙着应付考试完全没有时间(今天才考完汇编,泪目了)
Use this card to join MyBlog and participate in a pleasant discussion together .
Welcome to GoodBoyboy 's Blog,wish you a nice day .