In this story I’ll tell you how I found a small problem in RethinkDB, which may lead to gain admin
user privileges and allow you to execute ReQL queries without any restrictions.
RethinkDB is a NoSQL database which is specialized for realtime applications. I love it for the simplicity of deploy and api usage, so you could notice that I use it in my CTF tasks and other projects. Nevertheless, one day I realized that a combination of cool RethinkDB features can lead to catastrophic consequences.
There are two features, which we will use for our attack:
Feel the connection? r.http + 127.0.0.1:8080 = SSRF to web interface. The main idea is pretty simple, so now I’ll show you how it can hurt your app. Here you can find sources of both examples.
This is a small service which helps users to track responses from their services. It takes from user some info about service such as url, http method and request body. HealthChecker logs the response body to RethinkDB once a minute, so users can see if there are any errors.
“Chuck Norris jokes” service is OK
Well, firstly we need to open a connection inside the web interface of RethinkDB. That’s can be done by a POST request to http://127.0.0.1:8080/ajax/reql/open-new-connection
.
here is the connection id
Secondly, we have to make a POST to http://127.0.0.1:8080/ajax/reql/?conn_id={connection_id}
to execute actual query. For example, let’s get the rethinkdb.permissions table data. Query is a JSON like this: [1, [15, [[14, ["rethinkdb"]], "permissions"]], {"binary_format": "raw", "time_format": "raw", "profile": false}]
. Please note that it’s necessary to put \\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00
bytestring before the query. It’s hard to do from browser, so here you can find script which do all things automatically.
Result of the query — retrieved rethinkdb.permissions table
We just retrieved rethinkdb.permissions table data by exploiting SSRF! Besides reading tables, we can do anything which we can normally do with RethinkDB, the only thing you have to do is to make a proper query. The simplest way to get JSON for a query: launch RethinkDB locally, go to Web UI and execute queries you need, then copy their JSON from DevTools Network tab.
Request payload for r.db(“rethinkdb”).info() query
Imagine that you want to share your instance of RethinkDB with untrusted people. Of course, you will create accounts with restricted permissions for them. But do you expect that users with connect
permission will have an admin access to the whole database? The idea remains the same, expect the implementation of the attack. Here is the PoC: