Putting Redis to Production - Part I - Security

Introduction - An Important Story

If you have set up a Redis locally and got it to work with DXA so far, big applause to you! You now have a Redis in your local Development Environment. Like everything else, a Development Environment is likely to be very different from a Production one, so in this post as the next step, we will cover some practical considerations when using Redis in Production Environment.
 
However before we go on, I feel it is necessary to tell this real story first. My grandfather - I hope SDL would allow me to talk personal life in a technical blog post - is a practical accountant in his working life, then calligrapher and chess player after retiring, and a lovely person (oh I miss him). In his early life, he was in academic and a book-worm. He became much more practical and successful in his later life, because there was this defining moment, that also gave us the young generations the biggest laugh
 
He decided to learn swimming and read about it for a year, but still couldn't swim.
 
So his mother simply kicked him into a river and there he went! 
 
When you keep reading about Redis and Redis in Production (or accountancy, calligraphy and chess for that matter), you can imagine my grand is looking at you from the above and saying
 
Thanks for reading my grandson's blog. But Redis, like swimming, cannot be learnt by just reading about it

Since I have the backing of his spirit, here is a disclaimer. I very much hope these posts would give some practical pointers and save you time when considering Redis in Production, but by no means this will guarantee you have fault-free Production environment. The reason is very simple: there is no "Standard" set of configurations and your project requirement is different from mine.

Security

Endpoint Protection

Redis endpoint should not be exposed to public. Only trusted clients, which likely to be the server that runs your web application, should have access to it.

So set up a firewall rule to allow port 6379 - or to make it more difficult for attackers, 9736 - access only from your SDL Web Presentation Server and / or Deployer Server

Command Protection

If you do not need certain Redis commands, especially those commands that could affect an entire Redis database, or even the entire Redis instance, you can re-name them to make it difficult for attackers, or disable them completely.

For instance,
rename-command FLUSHALL "" (disable FLUSHALL command)
rename-command CONFIG IAMDIFFICULTTOCONFIGFORATTACKERS (rename CONFIG command)
You will need to restart Redis instance once making the changes, and, if you want to call your renamed commands from any client-side libraries, make sure they provide necessary support (for instance, StackExchange.Redis has CommandMap supporting renamed commands).

Authentication

Redis can be username/password protected. Choose a long and strong password to avoid Brute Force Attacks. This is because Redis by its nature responds to AUTH command very fast, which means an attacker can try many different passwords in a very short period of time.
 
Plus the password is stored in redis configuration file in plain text, and un-encrypted. So please secure it with a SSL proxy (stunnel or spiped)

Code Security

Choose a good, well maintained client-side library that supports Redis' security features. StackExchange.Redis is a good example. Commands such as FlushDB and FlushALL are automatically disabled until you initiated Redis connection in an "Admin" mode.

The other consideration is that, although Redis is super fast by design, it is mostly single-threaded. This means when one command is in execution, other commands are being blocked. This in general should not be a concern due to its speed. However, there are commands (such as KEYS or HGETALL) whose computational complexity is O(N). If your code uses these commands, be extra careful with the Denial of Service attack.

For instance, imagine your code logic is the following
  • Take a component id from a query string (can be cookie value, form submission, and so on.)
  • If the Redis key (suppose it is the component id from the query string) exists, get its value as related components
  • If the key does not exist, get related components based on this query string id, may be from an external service or data store, and store these related components in Redis
  • And, in some other page, you made a mistake by using KEYS command (maybe for reporting or debugging purposes, but somehow made public)
Ok now, the attacker could easily mock up traffics to submit millions of random component id query strings, resulting in millions of unnecessary key-value pairs in Redis. It should be OK if all your other code is to get a value from a key, as its time is a constant O(1). The Denial of Service comes into a reality when you use an O(N) command. When the attacker exploits that, all other pages relying on Redis would not respond as their requests are being blocked.

Be Secure from Day 1

Do not expect your Redis is secure if you apply these principles only when you are ready to go live. At your design stage these factors need to be considered, set up your development environment following the security best practice, and application can then be coded accordingly. Apply your penetration testing strategy as you would do normally, and now include Redis as an additional point of vulnerability.

A secure Redis, is impossible to be learnt by just reading about it.