在Web框架技术日益成熟的今天,如正则过滤、WAF等守卫让SQL注入逐渐变得不可能,但笔者坚信,只要是人开发出来的东西,就一定会存在漏洞。正如采用过滤非法字符的方式防范SQL注入一样,SQL注入时也可采用注释、URL编码等方式绕过过滤。只要没有颠覆原有基础知识体系,重新创造出新的结构体系,SQL注入与防御技术只会在两者的对抗中不断发展。
因此笔者将会以解题的方式,模拟SQL注入的过程,如果明白了SQL注入攻击的方式,无论是对测试人员还是开发人员,都是大有裨益的。这里笔者推荐靶场:sqli-labs。虽然Github上的源码已经多年未曾更新,但该靶场基本涵盖了各种经典常见的SQL注入漏洞,其具体搭建方式本篇不做赘述。万丈高楼平地起,本篇将会从最基础的level1开始,逐步深入剖析,与诸君共同了解学习SQL注入。话不多说,接下来进入正题。
level1的题目首页如下:
划红线提示句子大概意思为让你输入id作为参数。那我们就输入id=1查询看看会发生什么神奇的事吧。输入id=1查询后界面如下:
好家伙,直接账号密码都出来了,但是并没有什么用(hhhhh)。接下来逐个查询id=2、id=3……在id=13之前,查询的到的均类似与id=1的样式,当查询id=13时,出现如下界面:
表明id=13之后均无内容。
以上便是本题大概题意,让我们来梳理目前已有信息:该网站可以根据用户传入的id参数不同,在页面显示查询得到的内容。
为了更方便大家理解与代入,接下来我们模拟一个实际场景。你刚应聘成为这个网站的管理员,但给你的权限非常低,你现在只能查看用户的账号和密码,其它的信息你什么也看不了。一开始你还能忍住自己的好奇心,让自己不去想存放信息的这张表到底是什么样的呢,表里还有其它怎样的信息呢?但慢慢地,你因为这件事吃也吃不好,睡也睡不好。
终于有一天,你决定动手了,你要看看这张表到底是什么样的!你大手一挥,祭出了SQLMap,但不知为何今日宝器却不听使唤,无奈之下只得自己动手。
你绞尽脑汁想啊想,终于想起了第一式:判断有无可注入漏洞。
最经典的判断方式有以下两种:
1.加单引号法,看是否会带入数据库查询;
2.利用逻辑关系:
and 1=1, and 1=2;(or同上)
于是你在末尾输入了个’(英文的英文的英文的!),结果如下:
你坏坏地一笑,好家伙竟然还非常贴心的把错误给打印出来了。你细细地品味这这个错误:
’‘1’‘ LIMIT 0,1’
去掉前后成对的单引号之后语句如下:
1’ LIMIT 1,0
这时你非常惊讶,这个单引号不就是你自己输入的吗,想不到网站在根据用户输入的参数进行查询时没有做任何处理,直接带入数据库进行查找。这也就意味着你输入的东西在送往数据库途中是没有经过任何检查的哦。你不经狂喜,这样不就可以输入SQL语句直接对数据库进行操作了吗?
确认存在漏洞后,你又将目光投到了语句 LIMIT 0,1 上。该语句涉及limit()函数,用于查找记录,limit m,n表示:从第m条记录开始取n条记录(注:m从0开始,n从1开始)。
在找到漏洞后,你又发愁了:该用什么方式来注入呢?你盯着屏幕不禁陷入了沉思,突然灵光乍现。网站采用的是直接在页面返回查询的数据,那不就可以采取union注入了嘛。但union注入需要知道当前表的字段数,这个怎么办呢?当然是采用order by进行字段查询啦。
使用方式:order by n(n>1)。
当n+1出现与之前不同页面时,则n为该表字段数。于是你开始了枯燥乏味的查询过程。
当输入 order by 1时结果如下:
(n=2,3时结果与1一致。)
当输入order by 4时出现如下界面:
表明该表字段数为3,这么短真是太好了……
接下来就能进行union查询啦。使用方式如下:union select 1,2,3……n,
输入 union select 1,2,3 order by 1 结果如下:
诶?为什么跟之前的结果没啥区别呢?仔细一看,原来是id=1的查询结果把后面给覆盖了,只需让id=一个无法查询到结果的数就行了,这里令id=0,结果如下:
表明在2和3的位置是可以进行SQL注入的,这可把你激动坏了。
接下来就是重头戏啦,你现在想知道数据库的名字和MySQL版本,那直接在2和3的位置查询即可!
注入方式:
union select 1,database(),version() order by 1
结果如下:
这时你还想知道当前数据库用户是谁,又觉得再查询一次user()太麻烦了,能不能一次查询很多个呢?当然是有的啦,用concat_ws()函数就行啦.
用法:concat_ws(“连接符号”,str1,str2)
在2的位置输入:concat_ws("-",database(),version(),user())
结果如下:
知道这些基本信息后就可以开始获得数据库中的内容了。你已知表中的信息是用户账号和密码,通过之前的查询得知字段数为3,所以还有一列数据你是未知的,就先从这里下手吧。
查询函数:group_concat(str);
因此要查询剩下的一列数据时,只需输入:
union select 1,group_concat(column_name),3 from information_schema.coulmns order by 1
所得结果:
现在你已经知道了原有的那张表的所有内容。但这时你又产生了一个疑问:还有没有其它的表呢?有的话存的又是什么信息呢?于是你又忍不住对这个小破站的数据库伸出了魔爪。
输入:union select 1,group_concat(table_name) from information_schema.tables where table_schema=‘security’,3 order by 1
结果如下:
接下来的操作就与之前的一致。
至此,本题完。
在本次SQL注入模拟中,由于网站设计时没有对用户输入的参数进行处理,导致产生SQL注入漏洞,直接危害数据库安全。通过本次模拟,相信大家已经明白了SQL产生的原因,对SQL注入攻击的流程有了大概的理解,明白了如何挖掘简单的SQL漏洞。希望能对大家有所帮助,我们下篇见。