We would like in this blog post to highlight two of the most important security enhancements delivered in MongoDB version 4.0: SHA-256 support and TLS improvements.
The General Availability of 4.0 was announced on June 27, 2018 at MongoDB World 2018. Its multi-document ACID transactions, new native type conversions, Kubernetes integration, as well as new tooling and cloud services, make it our most significant release ever!
Now we hope to provide some context and history to explain why the new security features matter and offer you some technical information to help everyone take advantage of them with MongoDB 4.0
SCRAM-SHA-256 “Bigger is Better”
Many people have been asking about what MongoDB is doing regarding the rare and interesting SHA-1 vulnerability--and we’re happy to say that we’ve addressed these concerns in MongoDB 4.0 with support for SHA-256.
Secure Hash Algorithm (SHA) is a hash function used to help ensure data is not modified, by assigning a unique signature to a piece of data. SHA does this by computing a cryptographic value (hash) that both can be quickly generated and also be unique enough that it is not feasible to predict. The algorithm used for this computation is determined by the version of SHA used, which directly affects core hash function properties: speed and uniqueness.
A hash function is considered successful when different data provided to it yields completely unique hash values, such that any change to the data results in a change to the hash values. Comparing hash values thus can be used to reliably check whether your data has been tampered with.
A hash function is considered a failure when different data provided to it yields the exact same resulting hash values. This is called a “collision”, and it means that the function does not achieve the primary goal of uniqueness and, in effect, a signature can be forged.
NIST, for example, had in 2011 begun warning against SHA-1 failure in its Special Publication 800-131A: "SHA-1 shall not be used for digital signature generation after December 31, 2013”.
Hash Function | Use | |
---|---|---|
SHA-1 | Digital Signature Generation | Disallowed (except where specified by NIST protocol-specific guidance) |
Digital Signature Verification | Legacy Use | |
Non-digital Signature | Acceptable | |
SHA-2 family (SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256) | Acceptable for all hash function applications | |
SHA-3 family (SHA3-224, SHA3-256, SHA3-384, SHA3-512) | Acceptable for all hash function applications |
Then in 2012 Intel researcher Jesse Walker famously predicted the cost of performing a collision attack on SHA-1 would be “within the range of organized crime” by 2018, and affordable for university researchers by 2021. This set off a series of recommendations by cryptographers about the need to move to a newer version of SHA.
By 2015 a “Logjam” attack led OpenSSH to recommend discontinuing use of the diffie-hellman-group1-sha1 key exchange algorithm, prompting a move to later groups with a fixed prime for SHA-1.
Walker’s economics prediction by 2017 still looked fairly accurate as news reports titled “The SHA1 hash function is now completely unsafe” were in the mainstream press. Two different PDF files had been created with the same SHA-1 signature (“shattered.it”).
The required attack resources remained very high at this point, despite university research in 2015 to improve attacks, as they reportedly were soaking up “6,500 years of single-CPU computations and 110 years of single-GPU computations” to force a single collision.
Nonetheless, many security experts believed in 2017 a predicted corner had been turned on SHA versions and major browsers began marking SHA-1-signed HTTPS certificates as unsafe.
Naturally at this time customers began asking MongoDB whether SHA-1 was safe to continue using in the secure challenge-response authentication mechanism (SCRAM). This modern authentication mechanism, also known as IETF RFC 5802, had been designed to use any hash function defined by the IANA, and SHA-1 was the first generation that SCRAM deployed.
The SHA-1 crypto primitive weaknesses documented by researchers have not yet impacted such a challenge-response authentication flow, because it relies on quite a bit more than a single iteration of a hashing function. To illustrate better where and how SCRAM uses a hash function, here are the essential steps of authentication:
- Client transmits a username for authentication by server
- Server responds with a salt for that username and the number of iterations required (either generated or based on a lookup for transmitted usernames)
- Client responds with proof that it has a key, without sending the key
- Server responds with signature, as its own proof. If a match, client knows server has the right salted password hash
Both server and client are using Password-Based Key Derivation Function 2 (PBKDF2) to prove they have knowledge of a password by passing back and forth a one-time (nonce) random or pseudo-random number and hashes, after undergoing many thousands of hash-based message authentication code (HMAC) iterations of that password. Finding a collision in this context means overcoming many thousands of iterations thanks to PBKDF2 as well as several layers of unique nonce'd HMAC.
Nonetheless, given the above SP 800-131A guidance as well as the precautionary measure recommendations, we’re pleased to announce SCRAM use of SHA-256 is immediately available in the MongoDB 4.0 release.
Assuming that you’ve already enabled SCRAM-SHA-1 in your database instances prior to your upgrade to MongoDB 4.0, an upgrade to SHA-256 is completely automated. Existing users will individually continue to use SHA-1 without issue and will only begin using SHA-256 when you choose to update the given user’s password, while newly created users will automatically use SHA-256 by default.
After you’ve added SHA-256 support for all of your users, then you can optionally disable SHA-1 globally and prevent client use of SHA-1 hashes using the authenticationMechanisms server parameter (note that any accounts which only support the SCRAM-SHA-256 authentication mechanism will no longer be usable if you perform a downgrade from 4.0 for any reason).
(Note: Internal cluster auth, which uses the built-in __system user, will continue to use SCRAM-SHA-1 in 4.0 if you have not specified x509 for the clusterAuthMode. For optimal security and/or to meet any compliance objectives which require the prevention of all SHA-1 hashes, we recommend using x509 authentication for your clusters.)
Once you’ve upgraded to MongoDB 4.0, you will create new users in the same way that you did before. As you can see, the createUser command remains the same:

mongodb> db.createUser( {user:"matt", pwd:"pass", roles:[{role:"root", db:"admin"}]} )
Successfully added user: {
 "user" : "matt",
 "roles" : [
 {
 "role" : "root",
 "db" : "admin"
 }
 ]
}


But if we look at the resulting user that was created, we can see that the account supports both SCRAM-SHA-1 and SCRAM-SHA-256. SCRAM-SHA-1 will only be used as a fallback mechanism if needed -- for example when talking to older clients -- unless we explicitly disable it entirely using the authenticationMechanisms server parameter.

mongodb> db.runCommand({usersInfo: 1})
{
 "users" : [
 {
 "_id" : "admin.matt",
 "user" : "matt",
 "db" : "admin",
 "roles" : [
 {
 "role" : "root",
 "db" : "admin"
 }
 ],
 "mechanisms" : [
 "SCRAM-SHA-1",
 "SCRAM-SHA-256"
 ]
 }
 ],
 "ok" : 1
}

For existing users, it’s very simple to add SCRAM-SHA-256 as a supported mechanism. First, you can see an example command which can be used to identify those existing users that don’t yet have SCRAM-SHA-256 support:

mongodb> db.runCommand( {usersInfo:{forAllDBs:true}, filter:{mechanisms:{$ne:"SCRAM-SHA-256"}}} )
{
 "users" : [
 {
 "_id" : "admin.oldmatt",
 "user" : "oldmatt",
 "db" : "admin",
 "roles" : [
 {
 "role" : "root",
 "db" : "admin"
 }
 ],
 "mechanisms" : [
 "SCRAM-SHA-1"
 ]
 }
 ],
 "ok" : 1
}

Then once we’ve identified those accounts, we can easily add SCRAM-SHA-256 support simply by re-setting the password for the account:

mongodb> db.updateUser( "oldmatt", {pwd:"pass"} )

Just please be aware:
- You need to explicitly specify the user’s password as the SCRAM-SHA-256 credentials need to be generated from that input.
- This means that you’ll need to update existing users one by one.
- And since the DBA should not know the password for each user, this migration likely needs users to take action. But since the account migration happens automatically when the password is updated, the migration can be done as part of your normal password rotation procedures.
In summary, MongoDB 4.0 ensures that you’re easily able to meet any applicable security requirements and compliance objectives by moving to SHA-256 support in its SCRAM authentication mechanism.
TLS “Onwards and Upwards”
Transport Layer Security (TLS) protocol versions below 1.1 should be disabled and MongoDB 4.0 has taken care of this across the board, for all products on all platforms– TLS 1.0 is disabled by default everywhere, whether you run MongoDB yourself or use our fully automated and on-demand Atlas service.
The Secure Sockets Layer (SSL) protocol is practically a dinosaur in Internet time, going back to the mid-1990s. It had a rough early start -- SSL version 1 and 2 were immediately deprecated -- and after it was first formalized in 1996 it even experienced a name change to Transport Layer Security (TLS). The path to widespread adoption came slowly thanks to an evolutionary process of awareness about the benefits of privacy in network traffic. Yet today it is easy to take for granted that security has been integrated behind the scenes in network communications.
With the Internet increasingly serving as the backbone for so much of modern life, TLS followed a cycle of improvements and in 2008 TLS 1.2 was announced. This version persisted another ten years until just this past March 2018 when TLS 1.3 received formal approval.
Going back to the beginnings of SSL, it was a set of serious security flaws in version 1, 2 and 3 that signaled their demise. The market initially reacted slowly. Even though only browsers made before 1997 needed to run SSL version 2, few providers were proactively removing it. Partly the delay was because regulators did not yet step in on behalf of customers, instead letting service providers self-regulate. For example, in section 4.1 of the Payment Card Industry (PCI) Data Security Standard (DSS) the concept of “safe SSL” was left open to interpretation.
Unfortunately, self-regulation didn’t lead to any progress and so an Assessor Update of November 2008 was dropped with a detailed and strict interpretation. After a series of serious privacy breach investigations, SSLv2 was abruptly prohibited: “it is imperative that an ASV identify the use of SSL 2.0 to transmit cardholder data as a failure”.
This was possible because SSLv3 was widely deployed, as well as the later TLSv1. Nonetheless SSLv2 continued to be difficult to eliminate from the Internet at large, beyond the reach of PCI, as giant service providers and the largest software companies moved slowly to remove deprecated protocol versions. Difficult discussions were had in 2009 given TLS version 1.2 had been formalized and there appeared to be no reason to continue with SSLv2. Microsoft Windows Server product managers, for example, left SSLv2 on as a default in spite of regulators’ best attempts.
Fast forward five years to 2014 and TLS version 1.0 also was found to have serious security flaws such as Padding Oracle On Downgraded Legacy Encryption (POODLE). The PCI regulators, reflecting on the deprecation lessons from SSL, took a firm future position to end use and set a deadline in 2016; again large entities’ requested more time to comply and this deadline soon moderated to 2018. Regulators beyond PCI also chimed in, such as the Internet Engineering Task Force (IETF) itself and the National Institute for Standards in Technology (NIST) who issued strong recommendations about discontinuing TLS versions earlier than 1.1.
When will TLS version 1.1 be deprecated? There are few signs yet that regulators will require TLS version 1.2 as the minimum anytime soon. Best estimates for version 1.1 being banned are based on the RFC timeline above, given a natural cycle the IETF follows, and also the fact that an RFC just was published with the URL “tls-oldversions-diediedie”.
Mozilla only very recently has begun offering TLS 1.3 as an option in their Firefox browser. You can type about:config in Firefox’s address bar and confirm the warning message. Then search for security.tls.version and if you see a 4 instead of a 3, you already have TLS 1.3 support. You also can double-click on 3 (TLS 1.2) and change it to 4 if you want to enable TLS 1.3.
The bottom line is that history repeats and starting in the second half of 2018, many companies are required to comply with network protocol safety requirements issued by NIST, IETF and PCI DSS. This means today that versions earlier than TLSv1.1 should be disabled and MongoDB 4.0 has taken care of this across the board, for all products on all platforms – TLS 1.0 is disabled by default everywhere, whether you run MongoDB yourself or use our fully automated and on-demand Atlasservice.
The next question that users often have is: How can I tell which version of TLS my client application is currently using?
A site such as https://www.howsmyssl.com/ is able to tell you whether an application is running a deprecated and unsafe version of TLS. It is an issue both on client and server side, and safe TLS shouldn't be a problem to negotiate in modern releases of client software.
For example, as long as a Python version is built against an OpenSSL version that supports safe TLS, it should see no impact when TLS 1.0 is disabled. Python's Lib/ssl.py comes with documented warnings and "security considerations" that tell you how to make changes for safe TLS to be a default. Note that it does not warn against TLSv1 yet, but it does set the default to TLSv1.2:
SSL versions 2 and 3 are considered insecure and are therefore dangerous to use. If you want maximum compatibility between clients and servers, it is recommended to use PROTOCOL_TLS_CLIENT or PROTOCOL_TLS_SERVER as the protocol version. SSLv2 and SSLv3 are disabled by default.

>>> client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
>>> client_context.options |= ssl.OP_NO_TLSv1
>>> client_context.options |= ssl.OP_NO_TLSv1_1

The SSL context created above will only allow TLSv1.2 and later connections to a server (if your client supports it).
Then, to test with Python whether safe TLS has been configured properly, the following PSF recommended test can be used:

$> python -c "import requests; print(requests.get('https://www.howsmyssl.com/a/check', verify=False).json()['tls_version'])"

As another example the following test will reveal the TLS protocol version used when using Node >= version 6:

$> nodejs -e "const https=require('https');https.get('https://www.howsmyssl.com/a/check', function(res){var body='';res.on('data', function(chunk){body+=chunk;});res.on('end',function(){var r=JSON.parse(body);console.log(r.tls_version);});});"

And the following test for Ruby will reveal the TLS protocol version:

$> ruby -ropen-uri -rjson -e "puts JSON.parse(open('https://www.howsmyssl.com/a/check').read)['tls_version']"

Our TLS implementations in the MongoDB Server also now have been integrated with the native crypto libraries available on each platform: OpenSSL on Linux, Secure Channel on Windows, and Secure Transport on OS X. This ensures that MongoDB is current with the latest crypto library available on the OS, for emerging definitions of safety and strength. It allows us also in the future to take advantage of unique OS crypto features such as leveraging Keychain on OS X.
This new TLS usage covers all communication in MongoDB 4.0 -- between the clients, drivers, and server, as well as the internal cluster communication between nodes -- and we’ve implemented all of this in a way that requires no special upgrade/downgrade procedures.
Conclusion
Even if you have no immediate plans to use Transactions or any of the other great new features in MongoDB 4.0, upgrading is highly recommended because by doing so you will be improving the overall security of your MongoDB based applications.