记一次Redis被攻击的事件

 

最近几个月非常忙,所以很少有时间写博客,这几天终于闲了一些,于是就在整理平时的一些笔记。恰好这几天Redis服务器发生了问题,就记录一下。

我司有两款分别是2B和2C的App,类似于阿里旺旺的卖家版和买家版,里面有一个聊天的功能模块。双方可以通过这个功能聊天。内部通讯使用了环信,只是将本地账号和环信账号进行了关联。其他的信息,比如用户基本信息,好友关系,群组关系等存在Redis中,为防止Redis出现问题导致数据丢失(尽管配置了持久化),同时使用消息队列将数据写入SQLServer中进行了冗余。这是一种Redis的典型使用场景,从速度和效率上满足要求。

线上环境一直运行正常,但是在上周日(一个本该休息的日子),领导打电话过来说线上环境的用户登录不了,无法聊天,没有群相关信息。我想估计是Redis出现了问题,让领导不要着急,先让运维看看服务是否还在运行,不行的话,把Redis重启一下,因为之前设置过持久化,数据应该不会丢失。于是继续陪夫人吃饭,看电影。

到了晚上,还是打电话过来说有问题,没办法只有来公司一趟。打开机器用RedisClient连Linux环境上的Redis,发现里面的数据全没了,只有几个新注册的孤零零的用户在里面,老用户全没了,我当时惊呆了,以为是运维那边没搞好,是重启的整个服务器而不是重启的Redis,可能是Redis没有及时保存把数据给弄丢了。看到现象之后跟领导电话告知目前的现象和建议的解决方案,在授权下,重新把用户相关数据从SQLServer同步到了Redis中,关键的数据还好没丢失,然后让测试简单测试了一下,一切正常就没有太在意。而且由于Redis是安装在Linux上的,是由运维同事维护的,出问题了我这边也查不了,于是就回去了。

但是事情远没有那么简单,星期一的时候,领导又打电话过来说聊天又不能用了,比较急说要赶紧处理,我说好,于是不紧不慢的收拾好出门去公司。心里非常不爽,前段时间加班太猛,周一周二全公司开发都调休放假的。就我一个开发的来到公司之后,打开远程又发现Redis里面的数据全没了。于是又从SQLServer把数据同步到了Redis里,然后检查代码,把除了和聊天相关之外的其他逻辑,比如Redis定时同步服务相关的可能会影响到的地方都暂停了。因为前段时间做了一次重构,担心是代码导致数据丢失,搞完了之后就回去了。

然而好景不长,消停了一天没出问题。今天早上过来上班,领导走过来语重心长的说,聊天又登不上了,上去一看,Redis里面的数据又没了。正好运维的同事也在,也就一起找下存在的漏洞和可能的原因。

原因

前几天无意在微博上看到了乌云平台发的一条漏洞信息:

然后意识到是不是Redis没有设置密码访问,导致产生了这个漏洞被利用和攻击了。于是自查,发现了如下内容:

里边多了一个名为crackit的字符串,并且db0这个库是没有使用了的,现有的数据和逻辑都在db1上,刚打开的时候,db1是空的,上图是我重新同步过数据之后的结构。

对比乌云报的漏洞的最后一部分:

这简直就是一模一样啊。并且运维那边发现redis的持久化文件被写到了authorized_keys文件中:

确认被攻击之后,于是开始着手修复。之前在开发的时候,其实是有考虑给Redis加访问密码的,不知道后来太忙了,竟然给忘了,也想着公司比较小,应该不会被黑之类的,没想到这次就撞上了。

解决方法

解决方法当然是给Redis加密码,然后在访问的时候,设置密码访问。

最初,访问Redis的客户端我们使用的是ServiceStack.Redis,我之前也写过几篇Redis相关的文章。 由于考虑到授权的原因,使用的是2.0版本的dll,在其API中,从签名看,没有地方可以设置密码:

这个地方只能设置主机名称和端口号。

于是在使用中,比如下面这个删除群组的操作,RedisHelper类是对ServiceStack.Redis的一个封装类,只需要设置主机和端口号:

public static bool DeleteGroup(string groupId)
{
lock (lockDeleteGroup)
{
bool result = true;
using (RedisHelper redis = new RedisHelper(HOST, PORT))
{
var group = redis.GetWhereObj<GroupTable>(GROUPTABLE, x => x.GroupId == groupId);
group.Is_Deleted = true;
result = redis.Update<GroupTable>(GROUPTABLE, x => x.GroupId == groupId, group);
}
return result;
}
}

后面为了安全考虑,需要给Redis设置个密码,于是下载了最新版本的4.0的ServiceStack.Redis,这个是商业化版本的,使用中发现,是有限制的,在其下载页面最下角也有说明:

每小时只能请求6000次,这显然不能满足要求。除了以上限制之外,在使用过程中也出现过一些相当诡异的问题,比如通过Id查找的时候,其只能在1k条范围内进行查询等等,当然,也有可能是因为使用不正确,考虑到以上原因,加之之前的数据组织和结构设计不合理,于是决定重构。

重构的时候,就直接换了另一个C#客户端,StackExchange.Redis。

private static ConnectionMultiplexer _redis;
private static IDatabase _db;
private static IServer _server;
private static bool needSave = false;
private void Init(string host, int port, string pwd, int database)
{
var options = ConfigurationOptions.Parse(host + ":" + port);
options.SyncTimeout = int.MaxValue;
options.AllowAdmin = true;
if (!string.IsNullOrEmpty(pwd))
{
options.Password = pwd;
}
if (_redis == null)
_redis = ConnectionMultiplexer.Connect(options);
if (_server == null)
_server = _redis.GetServer(host + ":" + port);
if (_db == null)
_db = _redis.GetDatabase(database);
needSave = false;
}

这里面,可以直接对options对象设置Password属性。于是对该对象进行了包装,后面使用Redis可以这样,在构造函数里边传入PWD即可,比如下面判断用户是否存在的接口:

public static bool HasShopUser(string userName)
{
bool hasUser = false;
ShopUserEntity userEntity;
userEntity = null;
using (RedisHelper redis = new RedisHelper(HOST, PORT, PWD))
{
userEntity = redis.GetShopUserInfo(userName);
} if (userEntity != null)
{
hasUser = true;
}
return hasUser;
}

在替换Redis客户端访问类的时候,顺便对之前Redis里面的数据结构进行了一次重构,经过这次重构,速度提升很明显。于是,于是就直接弄到正式环境然后就把设置密码这个事情给忘记了。

当然,部署有Redis的Linux服务器也按照漏洞建议做了登陆限制和修复。

总结

其实这是一个很低级的错误,访问Redis没有设置密码(当然也可能是Redis所在的Linux服务器本身没有对登录做限制),也感谢有乌云这么好的一个平台,能够及时发现系统的问题和漏洞,避免出现更大的损失。作为一个码农其实不应该抱有这样的侥幸心理,就像墨菲定律说的那样“会出错的,终将会出错“ 。最后,希望这篇文章能给大家一个提醒和一些帮助。

Redis被攻击的更多相关文章

  1. 记一次Redis被攻击的事件

    最近几个月非常忙,所以很少有时间写博客,这几天终于闲了一些,于是就在整理平时的一些笔记.恰好这几天Redis服务器发生了问题,就记录一下. 我司有两款分别是2B和2C的App,类似于阿里旺旺的卖家版和 ...

  2. 公司外网测试服务器 redis 被攻击复盘

    最近 公司外网的测试的 redis 服务器被攻击,最开始是用 docker 搭建的 直接裸奔在外网,任何域名都可以通过 ip+6379来访问,最开始想的是测试服务器也没有啥,后面直接就被人登陆进去改了 ...

  3. redis被攻击,怎么预防

    今天,自己的redis服务器被黑客攻击了,数据全部被删除 从图中可以看到,在db0中多了一个crackit,他就是罪魁祸首,他的值就是ssh无密码连接时需要的authorized_keys. 我们被攻 ...

  4. Windows下Redis缓存服务器的使用 .NET StackExchange.Redis Redis Desktop Manager

    Redis缓存服务器是一款key/value数据库,读110000次/s,写81000次/s,因为是内存操作所以速度飞快,常见用法是存用户token.短信验证码等 官网显示Redis本身并没有Wind ...

  5. 关于 Redis 访问安全性的问题

    升级版本 3.0.2 版本升级到 redis-3.2.0 版本远程无法访问,比较配置文件有些变化,比如默认只能本地的机器才能访问 3.0.2 版本 # By default Redis listens ...

  6. Windows下Redis缓存服务器的使用 .NET StackExchange.Redis Redis Desktop Manager 转发非原创

    Windows下Redis缓存服务器的使用 .NET StackExchange.Redis Redis Desktop Manager   Redis缓存服务器是一款key/value数据库,读11 ...

  7. windows下的redis集群搭建的艰辛历程

    我是参照这两篇教程进行的操作:   1.https://www.cnblogs.com/weiqinl/p/6490372.html   (主) 2.https://blog.csdn.net/qiu ...

  8. C#版-Redis缓存服务器在Windows下的使用

    Redis缓存服务器是一款key/value数据库,读110000次/s,写81000次/s,因为是内存操作所以速度飞快,常见用法是存用户token.短信验证码等 官网显示Redis本身并没有Wind ...

  9. [转]Windows下Redis缓存服务器的使用 .NET StackExchange.Redis Redis Desktop Manager

    转自:http://www.cnblogs.com/oppoic/p/6165581.html Redis缓存服务器是一款key/value数据库,读110000次/s,写81000次/s,因为是内存 ...

随机推荐

  1. cfa,cpa,

    CFA考试内容分为三个不同级别,分别是方式是Level I.Level II和Level III. 考试在全球各个地点统一举行,每个考生必须依次完成三个不同级别的考试.CFA资格考试采用全英文,候选人 ...

  2. H264 编解码框架简单介绍

    阅读完H264/AVC 编解码器的介绍,脑海中仅仅是留下下面三条: 1.H264并没有明白规定一个编解码器怎样实现,仅仅是规定了一个编码后的视频比特流的句法,和该比特流的解码方法,这个与MPEG 类似 ...

  3. The mell hall——坑爹

    The mell hall 题目描述 In HUST,there are always manystudents go to the mell hall at the same time as soo ...

  4. sql server 常用语法

    --1 创建数据库 DROP DATABASE mydb1 CREATE DATABASE mydb1 ON ( NAME ='mydb1',FILENAME='D:\mydb1.mdf') LOG ...

  5. linux下Oracle11g RAC搭建(九)

    linux下Oracle11g RAC搭建(九) 八.创建ASM仓储 相同在图形化界面操作 [root@node1 ~]#  su - grid [grid@node1 ~]$ asmca   //创 ...

  6. centos 安装 使用本地图像文件来安装网络安装

    有时很无奈,无盘,U它只有盘4G而一个centos该盘4.16G,如何将它安装了网络安装,对不起,你想用20M更多的带宽,并注意使用网络启动盘的方法 没有条件,应该创造条件: 网络安装,需要下载图片, ...

  7. hdu2544(自己实现优先队列)

    hdu2544  dij水题,用来测试自己实现优先队列对不对 #include <stdio.h> #include <string.h> #include <stdli ...

  8. Blink: Chromium的新渲染引擎

    编自http://www.chromium.org/blink 关于blink Google Chrome/Chromium 从创始至今一直使用 WebKit(WebCore) 作为 HTML/CSS ...

  9. 程序员之---C语言细节22(函数返回指针注意事项&lt;悬空指针&gt;、查看进程能够分配的内存大小)

    主要内容:函数返回指针注意事项<悬空指针>.查看进程能够分配的内存大小 #include <stdio.h> char * favorite_fruit() { static ...

  10. 发布Ubuntu/Linux系统cache,增加可用内存空间

    桌面Ubuntu总内存4G,但free只有内存有100M 重视top命令检查看到真正的能力free内存.以下是真正的内存使用情况的看法有一个命令. watch -n 1 cat /proc/memin ...