Recently, I had a chance to know more about Shodan search engine by reading the blog post of Sijmen Ruwhof. The post talks about how he utilize Shodan to find a massive data leak of Unilever company in an unintentional and effortless way. For people don’t know about Shodan before, the post is absolutely worthy to read, I suppose :)
About the Redis misconfiguration
From the Redis home page: “ Redis is an open source (BSD licensed), in-memory data structure store, used as database, cache and message broker”. I don’t have a chance to work with Redis before so I don’t know too much about it, just know that if the server administrator didn’t restrict binding to 127.0.0.1 by default then an attacker can connect to Redis instances through a port of a server over the internet to do evil stuff (write files, etc.). Special thanks go to my master for giving me that fact.
Utilizing Shodan search engine
There are thousand of Redis instances exposed to the internet without any authentication as the twitter post of Shodan. Shodan performed a port scan on all of its known servers and try to connect to any exist unprotected Redis instance; that’s why servers which have unprotected Redis instances can be easily found by Shodan search engine.
Using Redis as the searching keyword in Shodan, we retrieve a list of server installed Redis (with the Redis version):
The number of the result is above 9000, however I just have the free account of Shodan, so this search engine limits to only 5 pages result (10 server IP per page). That’s why I have to do some tricks with python to go beyond the limited results.
So the basic idea here is making a request to Shodan server (with proper cookies) to get the raw text response, and then using regex to get the list of vulnerable server IP. In this case, we still get 5 pages per search query as it’s the limitation of free account, however we are in python so the search query can be changed to whatever we want: here I go through a list of country (using the Shodan country filter) inside a list of possible Redis version. Shodan search engine seems to know this trick before, hence without faking the user-agent header in our requests, we can not bypass the Shodan trivial defense.
This method enables me to achieve more than 3000 Redis installed server IP. I know that we can achieve more than that by making the search query being more flexible but it’s enough for me, I suppose (and actually it’s XD ).
The evil plan
My plan was inspired by Antirez post about Redis. In this very detailed post, he talks about the improper Redis configuration and how to use it to exploit a victim. The concept here is: connect to an unprotected Redis instance, flush all of the data inside the memory of Redis, push new data to the memory of Redis (which is a public key of a SSH key pair that we make), set the current directory to the
/home/<username>/.ssh/ folder, write the data in the memory to
authorized_keys file in current directory. After that, we can make a SSH connection to the target Server with the passphrase and private key of our SSH key pair.
In the concept in Antirez’s post, we have to guess the
<username> value in the target Server, so I decided to make a python script to attack all of the found targets Severs (by Shodan) and just set the current directory to
/root/.ssh/ . This idea will only work if the target Sever is running Redis with root privilege (because we can not access
/root/ directory without root permission). Well, if we success in some Servers, then making SSH connection to the victims with root user is cooler, right?!
At the start time, the script require to input the a whatever passphrase for the SSH key pair, and then just let everything go on automatically. The first stage is finding promising targets, which is Servers that we can access to
/root/.ssh directory via Redis instances and have port 22 open (for SSH connection).
After finding all of the promising targets, this script tries to attack all of them and also try to make SSH connection to the targets via created SSH private key and passphrase.
Finally, I got a list of more than 20 Severs that I can make a SSH connection with root user (ಥ﹏ಥ) After go into these Severs with root account, the first thing I do is making a new user (with root privilege) as a backup account in the future and set some rule to the iptables:
iptables -A INPUT -p tcp -s localhost — dport 6379 -j ACCEPT iptables -A INPUT -p tcp -s localhost -m state — state NEW — dport 6379 -j ACCEPT iptables -A INPUT -p tcp — dport 6379 -j DROP
These rules ensure that the Redis instances of these Server won’t be exposed to the Internet anymore ☂. Anw, I didn’t implement rules in some servers with FreeBSD OS because they don’t use iptables as the firewall method.
All of the scripts using in this post are available in my Github repository. There is the user guide inside the repo, otherwise you can take a look at this post of Seclist Worldwide Team for more details information. I didn’t expect that my scripts are known by them before I publish this post ಠ_ರೃ
Update: after having my upgraded Shodan account (by free Academic upgrade program), the number of Severs that I can make a SSH connection with root user is more than 100.