Today we are releasing detailed information about the security issues.
We expect all users to have updated already.
The JSON parser differences result in behaviour that if two roles keys are available in the JSON, the second one will be used for authorising the document write, but the first roles key is used for subsequent authorisation for the newly created user. By design, users can not assign themselves roles. The vulnerability allows non-admin users to give themselves admin privileges.
This issue was discovered by Max Justicz.
See also: Max’s own blog post about the issue and the motivation behind his research.
CouchDB administrative users can configure the database server via HTTP(S). Some of the configuration options include paths for operating system-level binaries that are subsequently launched by CouchDB. This allows a CouchDB admin user to execute arbitrary shell commands as the CouchDB user, including downloading and executing scripts from the public internet.
Details on CVE-2017-12635
CouchDB’s data exchange format is exclusively JSON. Internally, JSON is represented as an Erlang proplist. That implementation detail leads to a nearly unique behaviour in CouchDB when it comes to JSON parsing:: allowing JSON documents with multiple keys of the same name.
roles with a list of strings that gives users extra privileges.
By default, only admin users can set roles, ensuring users themselves can not exceed their assigned privileges. In addition, it is possible to let users sign up anonymously. In that scenario, it is even more important that privilege-granting roles are not self-selected.
CouchDB internal and Erlang-level accessor functions pick the first available key.
This difference led to multiple exploit scenarios:
- via _users
- via _replicator
In the case of the _replicator database, the authentication bypass occurs because the CouchDB replicator assumes it is the only actor that can set the _replication_state field of a replication document. The document validation skips further authentication if that field has a value of false. The duplicate keys bypass now allows users to set the _replication_state field to false to enable arbitrary edits, and then allows to modify the user context (userCtx) of the replication arbitrarily, which then can be used to insert documents into any database. This includes _design documents which could hold further validation and authentication functions that could be disabled that way.
Details on CVE 2017-12636
CouchDB allows the setting of configuration variables via HTTP(S) or by editing configuration files. Changing via HTTP(S) has the advantage of avoiding a process restart. A number of CouchDB’s configuration settings are file paths to executables that are dutifully executed by CouchDB proper on startup or when a new config setting is provided via HTTP(S).
The config API is only available to admin users. Setting arbitrary executable paths allows admins to set any executable through the use of the HTTP(S) API. These executables will run in the scope of the operating system user under which CouchDB runs. This includes read/write access to the database files, and at least read access to its configuration files.
We have mitigated this attack-vector by implementing a blacklist ofconfiguration settings that can not be changed via HTTP(S) and require shell access to modify.
A hard-coded blacklist has the downside of needing to be updated when newly added configuration settings to CouchDB also need blacklisting. We opted for this approach for reasons of expediency. In future, we’ll extend the configuration system that the addition of configuration settings will require explicit marking a variable to be safe for editing via HTTP(S).
In combination with CVE-2017-12635, this allows anonymous users to gain shell access as the operating system user that CouchDB runs under.
Am I impacted?
The easiest way to find out whether you have been targeted with documents that include duplicate keys is to run this command to check the _users database:
curl -s 'admin:email@example.com:5984/_users/_all_docs?include_docs=true' | grep -E '"roles".+"roles"'
Analogous for _replicator:
curl -s 'admin:firstname.lastname@example.org:5984/_users/_all_docs?include_docs=true' | grep -E '"_replication_state".+"_replication_state"'
Due to the severity of these issues and their combination, we have delayed the release of this detailed information, and urged all users to update to the latest releases.
If you still haven’t updated, here’s a short guide to asses whether the vulnerabilities affect you. This is valid for all CouchDB 1.x and 2.x users that aren’t on 2.1.1 or later or 1.7.0/1 or later.
- Public CouchDB instances:
- you should already have updated to the new release.
- if you have enabled require_valid_user AND if you trust all your users with database admin & server shell access: there is no problem
- Internal CouchDB instances:
- if you trust everyone on the network: no problem.
- if you have require_valid_user enabled AND if you trust all your users with database admin & server shell access: no problem
- if you have require_valid_user disabled AND if you trust all your users with database admin & server shell access: enable require_valid_user