Case Study : CVE-2020–15957 vulnerability discovery in DP-3T COVID-19 contact tracing backend server

As COVID-19 expanded across the globe to hit most nations, wider interest in tracing real-life contacts through Bluetooth are quickly emerging. These include MIT’s SafePaths, Enigma’s SafeTrace or Covid Watch to name a few.

What digital beacons will apps use to trace proximity contacts? Current designs rely on a low power wireless technology known as BLE aka Bluetooth Low Energy which was introduced with Bluetooth 4.0. For tracing apps to work, the Smartphones must continuously broadcast BLE (Bluetooth Low Energy) signals and interoperate between phones regardless of their make. Most Smartphones are either on Apple iOS or Google Android. During normal times Androids and iPhones, being conduits to content, don’t play well together. But these are not normal times. Apple and Google announced a joint effort in contact tracing and published a preliminary specification. Unsurprisingly, it includes a section on privacy.

With great power comes great responsibility

It has spawned initiatives such as Decentralized Privacy-Preserving Proximity Tracing or DP-3T which is one possible protocol for supporting decentralized proximity tracing. In the US, PACT is a comparable protocol which will be available through the SafePaths app and seems to have benefitted from earlier work on Private Kit.

What is DP3T — Decentralized Privacy-Preserving Proximity Tracing?

In this architecture most of the computation needed will be done inside mobile phones and not on a central backend server. Every phone will be broadcasting and storing “bluetooth low energy” beacons: small 16-byte unique strings found around the ether. Now and then phones will process what they have collected to trace and proof the proximity of devices, therefore the proximity is limited by how far these bluetooth signals can reach.

The proximity tracing process is supported by a back-end server that shares infection information with the app running on each phone, but by means of cryptography it will not know who is who nor will be able to track people.

Its four phases are illustrated below:

  • The installation includes set up of an application on a mobile phone which acts as a digital (EphIDs) dispenser and local storage unit.
  • In step two, normal operations, the app does two things: it broadcasts EphIDs to other phones running the app and checks for news with the backend server.
  • The third step addresses the handling of new known patients. They receive a token from a health authority and voluntarily use it to push their EphIDs to the backend server. The data is retained for a limited period of time.
  • The fourth step describes the actual tracing. Apps retrieve published infection data and check encounters against locally stored graphs.
Courtesy : Nicky Case (https://github.com/DP-3T/documents/tree/master/public_engagement/cartoon)

As our phones collect and share breadcrumb data from our proximity networks, privacy concerns arise. Privacy from snoopers, privacy from contacts and privacy from backend operators. There are several ways to define privacy itself. One example is through differential privacy. Differential privacy is an information-theoretical criterion in the context of statistical and machine learning analysis (i.e. where loads of data is captured.) It enables the collection, analysis, and sharing of statistical estimates such as averages or synthetic data, while preventing individual re-identification or record linkage.

These protocols are still work-in-progress and Apps assumed to be based on voluntary use.

Discovery of CVE-2020–15957

When dp3t-sdk-backend is configured to check a JWT before uploading/publishing keys, it was possible to skip the signature check by providing a JWT token with "alg":"none".

This vulnerability would have permitted an attacker to upload his secret keys to the DP-3T backend server without authorization, which can lead users of the contact tracing app to mistakenly think that they have already been exposed to the virus.

This vulnerability was acknowledged and patched by the development team of dp3t, with associated CVE ID — CVE-2020–15957.

The patch consists on changing the parse(String) function to parseClaimsJws(String), to force the JWT to be signed as indicated in this change request https://github.com/DP-3T/dp3t-sdk-backend/pull/208/commits/e967592bf131442b9d9916aefac2f4e42eaddd32

Dp3t-sdk-backend is a sprint boot based java web application based on

  • Java 11+ and Spring Boot 2.2.6
  • JJWT (JSON Web Token for Java and Android)
  • Spring Security OAuth
  • .. amongst other dependencies

The twitter verse was in an uproar after the announcement and a set of interesting opinions followed

Let’s pay attention to Filippo’s and Arkaidy’s tweet above that states

JWT is fine and it’s your fault if you use it wrong” and other bullshit some security people will tell you.
“100% agree with this thread. It isn’t enough to design systems that can be used safely, you have to design systems that can’t be used unsafely

To figure out what is the right way, one would have to comb through docs published by the committers of specific library, revised READMEs in the repo, advisories, blogs, stackoverflow etc . To illustrate the point, refer to the screenshot below from JJWT’s README file.

https://mrsuicideparrot.github.io/security/2020/07/30/CVE-2020-15957.html

JJWT is a pure Java implementation based exclusively on the JWT, JWS, JWE, JWK and JWA RFC specifications and open source under the terms of the Apache 2.0 License. The library was created by Okta’s Senior Architect, Les Hazlewood and is supported and maintained by a community of contributors.

Despite of the fact that committers of JJWT library did their part by emphasizing use of parseClaimsJws instead of parse, yet CVE-2020–15957 happened

So what is JWT and why is it relevant to DP3T ?

JWT tokens consist of 3 parts separated by a period ( . ).
These parts are:

  1. Header
  2. Payload
  3. Signature
https://jwt.io/introduction/

Header

  • HS256 (HMAC + SHA256)
  • RS256 (RSASSA-PKCS1-v1_5 + SHA256)
  • ES256 (ECDSA + P-256 + SHA256)
{
"alg": "HS256",
"typ": "JWT"
}

Payload

  • iss (issuer),
  • exp (expiration time),
  • sub(subject),
  • aud (audience),
  • and others (optional)
{
"iss": "https://XXXXX",
"name": "Mark Spencer",
"sub": "Dispatch Payload",
"iat": 1517890322,
"exp": 1899854334,
"aud": "https://xxx.subd.io"
}

Signature

HMAC-SHA256( base64urlEncoding(header) + '.' +  base64urlEncoding(payload), secret)

Andre Cirne wrote a detailed blog post where he explains the vulnerability and substantiates it with a POC as well.

JWT Security Patterns

Such best practices are defined by experienced architects within an organization or by subject matter experts in the developer community.

It is therefore important to take certain security countermeasures into consideration when designing, testing, and releasing your JWT based authorization schemes

  • The “none” algorithm. JWT specification allows for a “none” algorithm. Tokens using the “none” algorithm are considered as already verified by some implementations. To create such a token, set the algorithm in the decoded header to “none” and use an empty string as the signature. A past consequence of this vulnerability is CVE-2018–1000531 and CVE-2020–15957
  • Use a random complicated key (JWT Secret) to make brute forcing the token very hard.
  • Don’t extract the algorithm from the header. Force the algorithm in the backend (HS256 or RS256)
  • Make token expiration (TTL, RTTL) as short as possible.
  • Don’t store sensitive data in the JWT payload
  • Validate the incoming JWT token. You should do it, even if you’re working on an internal network — where the Authorization Server, the Client and the Resource Server aren’t connected through the Internet.
  • Check the Issuer claim. if the token contains the iss claim you should always confirm that any cryptographic keys used to sign or encrypt the token actually belong to the issuer.
  • Check the Audience claim. An ID Token must contain the client ID in the aud claim (though it can also contain other audiences)
  • Verify Expiration, issued time and clock skew. the exp claim, containing the expiration time, is not the only time-based claim that can be used for verification. The nbf claim contains a "not-before" time. The token should be rejected if the current time is before the time in the nbf claim. Another time-based claim is iat - issued at. You can use this claim to reject tokens which you deem too old to be used with your resource server.
  • Don’t use JWTs for sessions. JWTs where never considered for use with sessions, and using them in such a way may actually lower the security posture of your applications.

It’s not as simple to keep track of these security patterns for a specific component like JWT as there are many such libraries in the ecosystem and each of them adhere to their own implementation patterns. The problem exasperates when we are speaking of multiple open source components that we dependent on as we architect our applications. Each of these evolve/upgrade/deprecate in their own course of time.

Can such best practices be codified as a specification defined in adherence to how an open source framework or library should be used by its consumer?

Formulating Security-As-Code verification using ShiftLeft NG-SAST

Purpose-Built Developer Workflows in ShiftLeft’s NextGen Static Analysis

With our new release of NextGen Static Analysis (NG SAST), we’ve created a security workflow for developers that embodies the above lessons. It’s an automated security feedback loop with every pull request. The experience is similar to unit testing in that developers get immediate and accurate results all without leaving their development environment.

To learn more about ShiftLeft and how NG SAST can increase productivity and security in your organization, please:

Engineer, InfoSec tinkerer, Seed Investor, Founder/CTO of ShiftLeft Inc., (Opinions, my own)