Apache CouchDB CVE-2017-12635 and CVE-2017-12636

Last week, we announced the release of CouchDB versions 2.1.1 & 1.7.0/1.7.1 and marked them as CRITICAL security updates.

Today we are releasing detailed information about the security issues.

We expect all users to have updated already.

Overview

CVE-2017-12635

Due to differences in CouchDB’s Erlang-based JSON parser and JavaScript-based JSON parser, it is possible to submit _users documents with duplicate keys for roles used for access control within the database, including the special case _admin role, that denotes administrative users. In combination with CVE-2017-12636 (Remote Code Execution), this can be used to give non-admin users access to arbitrary shell commands on the server as the database system user.

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.

We addressed this issue by updating the way CouchDB parses JSON in Erlang, mimicking the JavaScript behaviour of picking the last key, if duplicates exist.

This issue was discovered by Max Justicz.

See also: Max’s own blog post about the issue and the motivation behind his research.

CVE-2017-12636

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.

This issue was discovered by Joan Touzet of the CouchDB Security team during the investigation of CVE-2017-12635.

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.

CouchDB uses JavaScript-based authorisation functions for managing users’ access control. For example, to create a user, a document is inserted into the special-case _users database. The user document must include a top level key 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.

The JavaScript spec for JSON with multiple keys requires parsers to pick the last key they parse to be the one to end up in the JavaScript object constructed from that JSON string.

CouchDB internal and Erlang-level accessor functions pick the first available key.

This difference led to multiple exploit scenarios:

  1. via _users
  2. via _replicator

In the case of the _users database, allowing duplicate keys allowed attackers to submit a _users doc with two roles keys. The first one could include any self-assigned roles, as the JavaScript validation function would only ever see the second key. When authenticating users on subsequent requests, the roles key was read from the Erlang-JSON representation and in that implementation the first roles key was returned. That could now include any roles, including the special case _admin role, giving users admin privileges.

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:password@127.0.0.1:5984/_users/_all_docs?include_docs=true' | grep -E '"roles".+"roles"'

Analogous for _replicator:

curl -s 'admin:password@127.0.0.1:5984/_users/_all_docs?include_docs=true' | grep -E '"_replication_state".+"_replication_state"'

Impact Assessment

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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s