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.
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.
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?
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
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.
After working with the lead Redis developer Antirez, the CSRF patch was backported to 3.2.7, he was very responsive and helpful!