对学校学生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 .