写在开头,这是第一次尝试进行SQL注入,第一次写笔记,排版稍微有些混乱,同时对SQL注入的理解也不深,小白级别,望各位大佬看见能批评指正。
本次注入是在phpstudy的环境下,使用sqlilab的测试环境进行联系。(PHP7.3.4,MySQL5.7.26)。
具体环境搭建下次单独发一篇笔记讲,其实在网上也有很多教程。本篇笔记单独讲自己第一次SQL注入的尝试。
1.打开即将进行SQL注入的页面

2.按照提示,在地址栏输入
?id=1
可看到如下界面

3.尝试输入单引号 ' ,发现报错

由此可见,单引号并没有被过滤,报错中提到MySQL,所以存在SQL注入漏洞。
4.使用--+注释,发现页面正常

根据后面的LIMIT 0,1 推断,id=1后面存在其他语句,使用 -- 将其注释掉。因浏览器地址栏会将空格过滤掉,因此在--后面加上+将其转义为空格。
http://127.0.0.1/sqlilabs/Less-1/?id=1'--+
5.使用order by判断字段数
将后面的语句注释掉就可以在注释前面进行各种骚操作了。在这里首先用order by 判断一下表中的字段数。
输入发现,order by 3 的时候页面正常,order by 4 的时候页面报错,并且提示第四列是不存在的。由此可以判断,表中最多只有三列。


这里普及一下order by 的知识。
ORDER BY 关键字用于对结果集按照一个列或者多个列进行排序。
ORDER BY 关键字默认按照升序对记录进行排序。如果需要按照降序对记录进行排序,您可以使用 DESC 关键字
SQL中 order by 的语法
SELECT column_name,column_name
FROM table_name
ORDER BY column_name,column_name ASC|DESC;
其中,order by num 是省略了字段名称直接使用num数字来代替相应位置的字段名称,即如果该列(字段)不存在,页面会报错,由此可以用来判断表中的字段数。
6.使用 union select 进行联合查询
在地址栏加上
union select 1,2,3
可以看见页面是正常显示

这里需要普及一下 union 的知识。
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。
请注意,UNION 内部的每个 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个 SELECT 语句中的列的顺序必须相同。
也就是说,如果 union select 后面的字段数跟表中不同,即会报错。同时,通过联合查询,可以在应有的字段处加入自己想要查询的内容。
举例,表如下所示

当输入
select * from users where id=1;
获得当id=1时的数据

而如果输入
select * from users where id=1 union select 1,2,3;
则可以得到如下图所示的输出

简单可以理解为,联合查询可以将字段合并到原来的字段。
而如果id的值不见了,或者说查询不到,则会只存在联合查询的字段,如下图
select * from users where id=-1 union select 1,2,3;

了解了这些,我们回到注入。
在地址栏中加上联合查询语句,并且让id的值查询不到
http://127.0.0.1/sqlilabs/Less-1/?id=-1%27%20union%20select%201,2,3--+

可以得知联合查询成功,字段2可以有回显,我们将字段2改成其他SQL函数,如database(),则可以得到数据库的名称,该页面所使用的数据库为security。

这就是联合查询的精髓,可以在联合查询中使用各种SQL语句进行数据库的操作。
7.具体的查询
先了解两个函数
concat_ws()

group_cncat()
语法:group_concat( [distinct] 要连接的字段 [order by 排序字段 asc/desc ] [separator '分隔符'] )
即,这两者都可以用来连接字符串。
接下来再了解一下数据库和表的关系,我们打开数据库可以看到MySQL中包含如下数据库

其中,所有数据库的名称存放在 information_schema 的schemata中,并且由在列名的SCHEMA_NAME下

因此可以通过联合查询查询到数据库的名称,将联合查询的语句修改为
union select 1,group_concat(schema_name),3 from information_schema.schemata
得到如下所示的页面

接下来查询该页面数据库security中有哪些表
union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security'
从哪里查出来的,下面这个图告诉你,代码为什么会这么写。

查询结果如下图所示

所以我们知道,页面所在的数据库security中,有四个表,如果这是一个登陆网站,那么显然users这个表中的数据是我们所需要的。
继续查询
union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'
查询结果得到

很显然,我们只需要继续查询列名中的所有数据,即可得到用户名和密码了。
union select 1,group_concat(id,0x3a,username,0x3a,password),3 from users
查询结果如下

至此,SQL注入渗透结束,最终结果获得用户名和密码。
文中部分字符如%27是转义字符,如0x3a是十六进制的字符,具体可以去网络上查找,这里就不细说了。
写在最后,这是一个小白第一次SQL注入的练习,手法很生疏,而且是先看了一遍教学视频,理解了原理以后,才自己重新一步步操作,最后获得结果。望各位大佬批评指正。
SQL注入要求对数据库比较熟练,精通数据库的语句和函数,因此学好SQL语句是学会SQL注入的基本条件。