预备知识:
数据库跟excl非常像 每个database相当于excl文件,table相当于excl文件中的表,column相当于表中的一列。
information_schema 这是一个数据库,其他所有数据库的主要信息在该数据库中都有存,如数据库名,表名,列名
select 选取数据
union 前后的生气了语句一起执行
where 限定选择数据的条件,比如我要3号表中第四列的数据,这句话中的3号表和第四列就是限制条件
group_concat() 能够让查询到的数据合并成一条数据显示(中间会有‘,‘间隔,不必担心可读性)
注释符号,能够让系统将该符号后的内容当作注释
具体操作:(此处拿字符型注入作为演示)
第一步 确定回显位置及字段数
1‘ order by 1#
第二个数字可以一直往上加,直到出错为止,那个数减一就是字段数,我们注入时,返回的字段数必须跟正常显示时的字段数一致才能正常显示。
第二步 构造payload 判断当前在哪个数据库
0‘ union select 1,database()#
这里第一个数字输入0的原因在于,只有返回了与正常显示时一样的字段数,页面才会显示你所查询的数据,然而只要前面的数据是有效的,那么返
回的字段数必定大于正常显示的字段数。在这里,我们采用了0,这一无效数据,从而使后面语句所返回的数据可见。另:database()是sql内置函数
,其作用为返回当前数据库名
第三步查询所有数据库名
0‘ union select 1,group_concat(schema_name) from information_schema.schemata#
group_concat在之前已介绍,不再解释。 information_schema.schemata数据库 information_schema中的一张表,里面的列schema_name,
存着所有的数据库名,进行到这一步,我们就能够得到所有的数据库名
第四步 查询表名
0‘ union select 1,group_concat(table_name) from information_schema.tables where table_schema=‘sqli‘#
与第三步同理,只不过这次查询的是表名,然后where限定了查询为‘sqli‘的数据库的表,当然这个名字也可以换为其他的,假如这里面没有你感兴趣的数据
第五步 查询列名
0‘ union select 1,group_concat(column_name) from information_schema.columns where table_name=‘flag‘#
同理,不再赘述
第六步 开心的查询所有你想查询的数据
0‘ union select group_concat(flag) from sqli.flag#
(此处只是例子 你也可以把sqli与flag换成其他东西)
最后,再来讲下这个漏洞的成因
我们假定前端传来的要查询的变量是a一般情况下,查询语句会是这么写的select ‘a‘
然而假如传过来的a中包含了sql语句,以第二步为例,它就变成了这样:select ‘0‘ union select 1,database()#‘
这样一来就有可能被恶意执行代码。
实际开发中要杜绝这种情况的发生,就我所知,一般有以下做法(我是小白):过滤,预编译
这两种方式应该可以防止sql注入的发生(没做过,不敢轻下结论)
至此,本文结束。