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

2.1.1 & 1.7.0

The Apache CouchDB development community is proud to announce the immediate availability of versions 2.1.1 and 1.7.0 1.7.1 (update: November 11th, 2017).

Both releases are security releases and fix multiple CRITICAL issues. Updates are mandatory.

Due to the severity of the issues and the limited options for workarounds, we will delay the release of detailed descriptions by seven (7) days and publish a full report on Tuesday, November 14th. We expect all CouchDB users to update their installations before then.

We are working with various package managers to ensure a smooth update path, but we can not make any promises. We advise all users to prepare to update from source, instructions can be found in the CouchDB documentation: http://docs.couchdb.org/en/2.1.1/install/index.html (2.1.1) and https://github.com/apache/couchdb/tree/1.7.0/share/doc/src/install (1.7.0 1.7.1).

For download options, see the download section of the main CouchDB website:

http://couchdb.apache.org/#download

Release Details

In addition to the security fix, both releases include a number of additional features and bugfixes.

New features in 2.1.1

  • Support compilation and running under Erlang/OTP 20.x.
  • Improve compaction speed by 10-40%.
  • Improve design doc cache performance.
  • Add support for partial indexes in Mango.
  • Add bookmark pagination to Mango.
  • Add execution_stats option to Mango queries for performance analysis.
  • The cookie domain for AuthSession cookies, used in a proxy authentication configuration, can now be customised via the ini file
  • The current node’s local interface can now be accessed at /_node/_local/{endpoint} as well as at /_node/<nodename>@<hostname>/{endpoint}.
  • Fauxton now uses a version of React with a BSD license.
  • See the full list here: http://docs.couchdb.org/en/2.1.1/whatsnew/2.1.html

Other Bug Fixes in 2.1.1

  • The couch_peruser functionality is now really fixed. Really.
  • It is now possible to modify shard maps for system databases.
  • Fix issue on macOS with mounted volumes that have a space in their name.
  • 50+ bug fixes and performance improvements, see the full list here: http://docs.couchdb.org/en/2.1.1/whatsnew/2.1.html

Bug fix in 1.7.1 (Update: November 11th, 2017)

New features in 1.7.0

Other Bug Fixes in 1.7.0