这一篇是基于dvwa下的SQL盲注(SDL Injection(Blind),在已知数据库存在和SDL盲注可行的前提下进行更深一步的操作。这里,我们将会通过python来爆破数据库名。
1.python连接数据库。
(1)首先我们需要查看自己的python是否已经已经安装了pymysql库,如果没有安装,可以通过Win+R打开命令行,输入pip install pymysql进行安装,也可以在pycharm应用中直接安装
找到pychram设置里面的python解释器,点击左上角的加号,输入pymysql,点击安装,等到显示成功就可以了。
安装到用户的站点软件包目录,如果不选择,我们就只能在pycharm的虚拟环境下使用,而且我是在选择python解释器3.8版本下进行安装的,如果我换成了其他的解释器,也是不能运行我们下载在虚拟环境下的库的。
(2)配置好环境后,我们就可以连接我们的库了。
# 数据库配置信息
db_config = {
'host': 'localhost', # 数据库服务器地址,我的直接使用的本机上的数据库
'user': 'root', #用户名
'password': '123456', #密码
'database': 'dvwa', #所要连接的数据库
'port': 3306, # 默认端口
'charset': 'utf8mb4' #连接数据库时使用的字符集
}
# 连接数据库
connection = pymysql.connect(**db_config)
在mysql命令行输入status;可以查看数据库的信息,其中就包括了主机地址和端口号。
(3)建立游标,进行一个简单的数据库查询,看是否成功。
try:
# 创建一个游标对象
with connection.cursor() as cursor:
# 执行 SQL 查询
#从 `users` 表中选取 `user_id` 为 `'1'` 的用户的 `first_name` 和 `last_name`。
sql_query = """
SELECT first_name, last_name
FROM users
WHERE user_id = '1'
"""
#使用execute()方法,执行SQL语句
cursor.execute(sql_query)
# 获取查询结果
#fetchall()函数,它的返回值是多个元组,即返回多个行记录,如果没有结果,返回的是()
result = cursor.fetchall()
# 输出结果
for row in result:
print(f"First Name: {row[0]}, Last Name: {row[1]}")
# 提交事务(如果有写操作)
# 当对数据库进行了一组相关的操作(如插入、更新或删除记录)后,如果想要保存这些更改到数据库中,
#就需要调用 commit() 方法。一旦调用了此方法,所有在当前事务范围内的更改都将永久保存到数据库中。
connection.commit()
except Exception as e:
print(f"Error connecting to the database: {e}")
# 回滚事务(如果有写操作且发生错误)
#在一组数据库操作中,如果有任何错误或者异常发生,导致无法成功完成所有操作,
#此时可以使用 rollback() 方法来撤销之前的所有变更,将数据库状态恢复到事务开始前的状态。
connection.rollback()
finally:
# 关闭数据库连接
connection.close()
在这里,我解释一下游标的作用,在数据库编程中,游标是一种能够从数据库检索出一条或多条记录,并对这些记录进行处理的对象。游标可以被用来逐行读取查询结果,允许程序员像操作单个记录一样操作整个结果集。
当连接数据库后,游标开启的时候,我们就能在python中操作数据库中的内容,并将数据库的内容放回给用户。
除了上述查询结果的方式,还可以使用函数fetchone(),它的返回值是单个的元组,也就是一行记录,如果没有结果,那就会返回null。
如果只是查询数据库的内容就可以将代码简化,就不需要对数据库更改经行保存了。
2.使用二分法爆破数据库长度。
def get_database_length():
l = 0
m = 100
while l < m:
mid = (l + m) // 2
sql_query = """
SELECT 1
FROM users
WHERE user_id = '1' AND (SELECT LENGTH(DATABASE())) > %s
"""
with connection.cursor() as cursor:
cursor.execute(sql_query, (mid,))
result = cursor.fetchone()
if result:
l = mid + 1
else:
m = mid
return l
执行便可以看到运行结果,我这的数据库名的长度为4
3.使用二分法爆破数据库名。
我们的爆破是在我们已经知道数据库是字符串的条件下,而且已知数据库名是由字母组成进行爆破的。
def get_database_name(length):
database_name = ''
for i in range(1, length + 1):
low = 32
high = 127
while low < high:
mid = (low + high) // 2
#ASCII函数是将数据库名的字符转换成ascii码
sql_query = """
SELECT 1
FROM users
WHERE user_id = '1' AND (SELECT ASCII(SUBSTRING(DATABASE(), %s, 1))) > %s
"""
with connection.cursor() as cursor:
cursor.execute(sql_query, (i, mid))
result = cursor.fetchone()
if result:
low = mid+1
else:
high = mid
# 将爆破出的字符添加到database_name中
database_name += chr(low)
return database_name
4.总的代码
import pymysql
# 数据库配置信息
db_config = {
'host': 'localhost', #数据库服务器地址
'user': 'root', #用户名
'password': '123456', #密码
'database': 'dvwa', #数据库名
'port': 3306, #默认端口
'charset': 'utf8mb4' ##连接数据库时使用的字符集
}
# 连接数据库
connection = pymysql.connect(**db_config)
#获得数据库名的长度
def get_database_length():
l = 0
m = 100
while l < m:
mid = (l + m) // 2 #保证mid是个整数
sql_query = """
SELECT 1
FROM users
WHERE user_id = '1' AND (SELECT LENGTH(DATABASE())) > %s
"""
with connection.cursor() as cursor:
cursor.execute(sql_query, (mid,))
result = cursor.fetchone()
if result:
l = mid + 1
else:
m = mid
return l
#获得数据库名
def get_database_name(length):
database_name = ''
for i in range(1, length + 1):
low = 32
high = 127
while low < high:
mid = (low + high) // 2
#ASCII函数是将数据库名转换成ascii码
sql_query = """
SELECT 1
FROM users
WHERE user_id = '1' AND (SELECT ASCII(SUBSTRING(DATABASE(), %s, 1))) > %s
"""
with connection.cursor() as cursor:
cursor.execute(sql_query, (i, mid))
result = cursor.fetchone()
if result:
low = mid+1
else:
high = mid
# 将爆破出的字符添加到database_name里面
database_name += chr(low)
return database_name
try:
# 得到数据库名长度
db_length = get_database_length()
print(f"The length of the database name is: {db_length}")
# 得到数据库名
db_name = get_database_name(db_length)
print(f"The database name is: {db_name}")
finally:
connection.close()
运行结果
5.我们可以将我们所得到的数据到DVWA网页进行验证,看是否正确。
先将其调到最低
在SQL Injection(Blind)输入:
1' AND DATABASE() ='dvwa
用户存在,说明我们爆破出来的数据库名是正确的。
标签:cursor,爆破,name,database,数据库,mid,二分法,connection From: https://blog.csdn.net/weixin_73918008/article/details/142579002