A CSRF demonstration of stealing local Redis data, and encrypting all Redis instances on a local network
CSS JavaScript HTML Python Nginx
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
kubernetesConfigs
nginx
publisher
redis
subscriber
LICENSE
README.md
docker-compose.yml

README.md

Whatsinmyredis.com

Redis <3.2.7 suffers from CSRF issues which allows an attacker to run arbitrary redis commands on local/internal redis instances. These attacks have been mitagated in the latest versions of redis.

Demoed on this website is the ability to

  • Migrate all redis keys from an internal network to an attacker controlled server.
  • Encrypt all of the contents of local redis instances, which could be leveraged to ransomeware a person or company.

http://whatsinmyredis.com

whatsinmyredis

This release coincided with the release of redis 3.2.7 https://www.reddit.com/r/redis/comments/5r8wxn/redis_327_is_out_important_security_fixes_inside/

How is Redis vulnerable to CSRF?

Redis does not use HTTP to communicate, it uses its own redis ascii, newline delaminated protocol via TCP. One unfortunate property of this protocol is it does not terminate TCP connection when invalid commands are sent to it. This allows for a cleartext HTTP request to be sent to a listening Redis server. Redis will ignore the HTTP headers, and as soon as it sees a valid redis command in the body, it will execute it. Below is an example of running the migrate command on all keys in the redis store.

image2

Note the use of lua script EVAL. Redis supports Lua script, which is a turing complete programming language, sandboxed in the redis environment.

More info on redis CSRF is available here

How can you encrypt redis contents?

As mentioned above, lua script is turing complete. This allows an attacker to implement their own crypto via lua script and send it over to the victim. In this example, bad crypto is used for the purpose of demonstration. An XOR "one time" pad is generated in Javascript, and is used to XOR all contents in redis. This encryption key can then be sent to a malicious server, and can be used to ransom the victims.

imge3

Impact

Because WEBRTC exposes internal IP addresses it's very easy to sweep an entire /24 or /16 from a single user clicking a malicious link. This means if one victim at a company clicks an evil link, every redis instance exposed on the victims network can fall victim to ransomware, data exfiltration, and in certain cases Remote Code Execution.

How can you protect yourself?

Upgrade to Redis <3.2.7 and consider putting authentication on your redis, and pipping it through Stunnel

FAQ

How does the latest version of redis fix this issue?

The latest version of Redis alieses the words POST and HOST to QUIT commands, this when incoming HTTP requests contain those words, they terminate the TCP connection.

The site doesn't work for me, why?

There are a number of reasons it may not work, some listed below

  • The site uses outbound port 11111 for the data exfiltration, this port may be blocked
  • The site utilizes redis commands introduced in 2.6.0 so older versions will fail
  • The website needs websocket support to work
  • Traffic may have knocked it over, I didn't do much load testing, I don't know what it can handle

Why does my redis data look a little messed up?

The way I collect and parse Redis keys is not perfect. This is mostly out of laziness.

Why isn't there TLS on the site?

The site needs to make unencrypted requests to redis, and because mixed contents errors would get thrown otherwise, there is no TLS on the website

Do you save any of the data?

No. The data is temperarily sent to a GCE server, which is used to send that data back to the client via websocket

Why do you need to send the data back to the server?

Once the malformed "HTTP" response is sent from the redis database to the browser, the browser throws a malformed HTTP response error.

I messed up and encrypted data I need, what now?

Fortunetly I'm using really bad crypto here, so you have some options. If you haven't refreshed, hit the encrypt button again, and it will XOR the redis contents with the same key, and your data will be recovered. The decryption key is also saved in the redis key "WIMREncryptionKey". If you encrypted the contents multiple times with multiple keys, there's still hope. If you know what any of the values in the database used to be, you can XOR that value with that current encrypted key to recover your new decryption key.

Special thanks

After working with the lead Redis developer Antirez, the CSRF patch was backported to 3.2.7, he was very responsive and helpful!