5

我的项目出了个高危漏洞,值得注意!

 2 years ago
source link: https://my.oschina.net/u/3944379/blog/5029581
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

你好,我是 yes。

近期我们公司和另一家政府相关的公司搞了个合作。

这个项目是我负责的,在临近上线的时候,他们要求出具第三方安全报告。

这个事之前没说过,不过政府项目也可以理解,那就搞个呗。

总监问我:

那我肯定得回有信心啊,嘴强王者可不是白瞎的。

不过心里真没底,想着这小系统会经受第三方狂风暴雨般的渗透攻击,就发虚。

过了两天,测完了,果然.....

一个高危,直接 GG,但是漏洞点竟然是 SQL 注入,我是没想到的!

在说处理方式之前,还是先介绍一下 SQL 注入吧,并且还有个注入实验,挺有意思的。

先介绍下 SQL 注入

简单地说就是不法分子在请求参数里面填入了别有用心的字符,这样在执行 SQL 的时候在不经意间就把黑客想要执行的命令给执行了。

我举个例子就一目了然了,比如你登录的 SQL 可能是这样写的:

select * from User where username = '{userName}' and password = '{pwd}'

看着没毛病,那假设现在 username 传 yes, password 这个参数传过来是' or 1=1#,那此时的  SQL 就变成了:

select * from User where username = 'yes' and password = '' or 1=1;

#是注释,这样后面的引号就被注释了,所以 SQL 就变成上面这样,得以执行。

这不是傻了吗?合着我的账号有个万能密码:' or 1=1#,所以黑客可以随意登录别人的账号!

这就是 SQL 注入,想想如果后面传的是' or 1=1;DROP DATABASE xxx #,是不是人没了?

我之前还看到 git 上有个 sqli-labs,就是专门来注入玩的!今天就来玩一玩!

这个 sqli-labs 开源项目,就是造出来给我们注入的,称之为 SQL 注入靶场。

首先从 git 上把代码 down下来,解压。

网址:https://github.com/Audi-1/sqli-labs

这是个 php 项目,这个运行需要 mysql 和 apache,简单点用 phpstudy 就可以弄好环境!

注意这个项目比较老,phpstudy 默认 php 是 7.3.9 的,所以得把 php 的版本换一下,换个5点几的版本。

然后把代码拷贝到网站的根目录,点击管理就会有根目录的选项,直接选就行了。

还有一步就是打开项目中的sqli-labs-master\sql-connections目录,找到db-creds.inc,把里面的数据库密码填上了。

然后直接打开浏览器,访问http://localhost/sqli-labs-master/,即可看到下方页面。

SetUp/reset Database for labs,把数据库给初始化好,然后就OK了。我看了看有这么几张表。

再看刚才那个页面,拉到下方可以看到一共有 22 个 SQL 注入实验。

我们直接点 Less-1,会跳到一个页面,它叫我们输入 ID 来作为参数,这个实验是单引号的字符型注入。

我输入一个?id=2,界面返回了安吉丽娜,密码有点意思。

来,咱们试试注入。

比如现在我想知道用户信息和库名。

首先利用 order by 来推断出 select 的字段有几个,这是利用如果 order by 的数字大于 select 的数字则会报错的原理。

比如输入?id=2'order by 4%23,这里注意一下浏览器输入 # 需要 URL 编码一下,# 的 URL 编码就是%23

就这样倒推出来到3的时候就没报错了,所以 select 的字段是有3个。

然后再利用 union 来看看界面上的 name 和 password 分别取的是 select  里面的那一列,注意这里id要取的不存在的,这样才能拿到  union 后面的结果。

比如输入 ?id=-1' union select 1,2,3%23

从结果来看name拿的是第二列,password拿的是第三列。

然后就可以操作了呀!

?id=-1' union select 1,user(),database()­­ %23

用户信息和数据库名都暴露出来了,至于其它注入我就不展示了,太多了。

你们可以自己去玩玩,关于这个实验的代码和环境工具我都打包好了,文末有获取方式。

再回到我负责的项目上来。

我最后的处理方法

其实项目里面对于 SQL 注入是做了处理的,而且基本上所有的 SQL 都是预编译处理。

唯独就一个比较复杂的查询,没有预编译,但是也做了参数过滤,而就是这个查询出了问题。

后面我用 sqlmap 这个工具,自己测试了一下,注入点是 sort 这个参数。

看看,在 sort 中输入了这一串东西,我也看不懂,反正最后得到了当前的数据库名。

后来我去过滤的切面看了看代码,RLIKE 这几个关键字确实没做过滤,于是我把这些关键字都补充了一遍,然后又测了一遍。

结果从直接得到当前数据库名,变成了推断出当前数据库名。

看起来好像进步了一点点,实则没啥用,还是GG。

所以我初步推断项目的过滤类不全,过滤关键字好像搞不过它,可能还是会有遗漏,索性我就把查询改成了预编译,一劳永逸!

所以童鞋们,如果你们做的项目也有利用过滤关键字来防 SQL 注入的,来试试用 sqlmap 注入看看,指不定就中招了!

那预编译为什么能防止注入?

首先需要理解一下数据库执行 SQL 的原理。

一条 SQL 传输给数据库之后要先经过语法分析器生成抽象语法树,就和咱们大脑一样,听别人的话会在大脑中解析一波,来看看他到底在说啥,如果他说:$%@!!# ,你的大脑就解析不了了。

SQL 也是一样,所以如果有语法错误这里就会抛错,还是拿上面的实验作例子,这黄色的字应该很熟悉吧?

生成抽象语法树之后会经过语义分析和优化器的优化,然后生成执行计划,就像你 explain 得到的就是执行计划。

预编译就是把含着占位符的 SQL 先传输到数据库生成执行计划,然后再等着之后具体的值传进来,最后执行 SQL。

所以预编译的重点在于参数传进来之前已经定好要怎么执行 SQL 了,比如预编译的是一个 select 语句,那么执行计划只会 select ,你参数里面传的 delete、drop 啥的都没用,因为计划里面没这个操作!

这就是为什么预编译可以防止 SQL 注入的根本原因。

所以为什么说预编译效率更高?都解析完了,直接来来活就干事了,效率肯定高。

接下来我再简单介绍下 sqlmap 的用法。

sqlmap简介

sqlmap 是一个开源的渗透测试工具,可以自动检测和利用 SQL 注入来接管数据库服务。

简单来说,我们可以利用这个工具来测试我们的产品是否安全,是否有注入点。

使用方式非常简单,首先得有个 python 环境。

然后从官网下载软件之后直接解压,然后命令行进入解压目录,再输入指令即可

比如:python sqlmap.py -u "http://127.0.0.1/sqli-labs-master/Less-1/?id=1"-p id --dbs

这条指令的意思是要测试指定的网址,-p 这个是声明注入点,表明我要注入 id,--dbs,指的是我想注入得知这个产品的所有数据库。

所以直接命令行输入 :

然后裤子就被扒了!

看看,把所有数据库名都捞出来了。

还有很多测试花样,我就不一一演示了,大家可以自己去玩玩。

我个人觉得对 SQL 注入最保险的方法就是预编译了,参数过滤可能会有遗漏。

快去拿 sqlmap 来测试测试你的项目吧,看看会不会注入成功!

还有上面提到的 SQL 注入实验也可以玩玩,还是很有趣的。

欢迎关注我的公众号【yes的练级攻略】,更多硬核文章等你来读。

参考资料:


我是yes,从一点点到亿点点,我们下篇见。

本文分享自微信公众号 - yes的练级攻略(yes_java)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK