Security/Reviews/B2G/FirefoxAccounts

< Security‎ | Reviews‎ | B2G

Contents

Overview

Firefox Accounts Review Details

  • Scope: Firefox Accounts Gaia & Gecko Code
  • Review Date: May and June 2014
  • Review Lead: Christiane Ruetten, cr@mozilla.com

Documentation

Context

Firefox Accounts is an identity service landing in FxOS 2.0. It provides single-sign-on to local FxOS apps and services, authentication to third parties, and derivation of encryption keys. It is to replace PAKE in Firefox Sync after the ongoing transitional phase, and Find My Device will authenticate against FxA. Other apps and services will follow.

Since most of the FxA code for FxOS has been written from scratch over the past months, its upcoming 2.0 landing merits a full security review. The security of several apps and FxOS services will depend on the code covered in this review.

A previous review started in late 2013 was deferred as the code wasn't stable. A Firefox Accounts Security Design Review which doesn't cover the FxOS components was conducted in April 2014.

Scope

This review covers Firefox Accounts from a Firefox OS perspective only (mobile or desktop client code is not covered except for where it is shared with FxOS).

The following components were reviewed:

  • Gaia
    • FxA component of FTU
    • FxA component in the Settings app
    • FxA IAC Client
  • Gecko
    • FxA B2G component FxAccountsMgmtService
    • FxA B2G component FxAccountsUIGlue
    • FxA Gecko service
  • DOM
    • FxA interface through navigator.mozId

The following items were not reviewed:

  • HTML files
  • tests
  • OnePW encryption key derivation
  • FxA component of Firefox Sync
  • FxA portions of FindMyDevice (will be covered in separate review)
  • The Hawk protocol and implementation (covered in separate review)

Architecture

Architectural overview

FxA's security is heavily rooted in the OnePW protocol design, as well as the server-side database. Its server API is secured with the Hawk query authentication scheme. The OnePW protocol is documented in detail in the fxa-auth-server wiki.

The FxA code provided in Firefox OS 2.0 can be separated into three major units: Gecko-based functional core, Gaia-based UI core, and a mozId API exposed to Gaia apps.

Basic flow for signing in to Firefox Accounts is:

  1. User signs-in to Firefox Accounts in either the First Time Use (FTU), the Settings app, or when a Relying Party requests FxA auth through the navigator.mozId interface and the user hasn't already been signed in.
  2. FTU and Settings communicate user ID (e-mail address) and password to the system app via IAC
  3. The system app sends credentials to gecko via custom events
  4. Gecko (FirefoxAccountsManagerService) communicates with api.accounts.firefox.com to validate the credentials
Overview of the FirefoxAccounts architecture in FirefoxOS

We identified three main data paths in and out of the FxA code:

  1. The IAC interface between certified apps and the FxA Gaia/System code
  2. The navigator.mozId DOM interface between Relying Parties (gaia apps) and the FxA Gecko code
  3. The HTTPS connection between the FxA API server run by Mozilla and FxA Gecko code and

Gecko Components

The core of FxA on FxOS lives in the FxA Gecko service. It implements the client side of the OnePW protocol in FxAccountsClient.jsm.

FxAccountsManager.jsm

The Gecko-side FxAccountsManager.jsm is the central piece of code that handles FxA status and triggers code paths that for example authenticate the user with the API server or display a FxA login screen should they become necessary.

Derivation of tokens, most importantly the authPW token which is derived of e-mail and password and used to proove knowledge of the Password to the FxA server, happens in Gecko. The authPW does not leave the Gecko portion of the code with the exception of being transferred to the FxA API server.

FxAccountsMgmtService.jsm

Some specific apps (currently just the certified FTU and Settings apps) need access to FxA functionality that allows them to manage the account (this is mostly sign up, sign in, re-sign in, logout and delete) and query information about the current config and state.

This service listens for IAC requests coming from these apps, triggers the appropriate Fx Accounts flows (sign up, login, re-authenticate...) and sends a reponse back to the UI.

The communication mechanism is based in mozFxAccountsContentEvent (for messages coming from the UI) and mozFxAccountsChromeEvent (for messages sent from the chrome side) custom events.

FxAccounts.jsm

Implements the FxAccounts API between FxAccountsManager and FxAccountsClient. Defines AccountState object that handles sign-in promises, and it also defines the internal FxAccounts API:

 26 // All properties exposed by the public FxAccounts API.
 27 let publicProperties = [
 28   "getAccountsClient",
 29   "getAccountsSignInURI",
 30   "getAccountsSignUpURI",
 31   "getAssertion",
 32   "getKeys",
 33   "getSignedInUser",
 34   "loadAndPoll",
 35   "localtimeOffsetMsec",
 36   "now",
 37   "promiseAccountsForceSigninURI",
 38   "resendVerificationEmail",
 39   "setSignedInUser",
 40   "signOut",
 41   "version",
 42   "whenVerified"
 43 ];

public here means to other Gecko code, not to web apps. The password isn't exposed through this interface, but user ID and login state, and potentially derived keys are.

Credentials.jsm

Defines a Credentials object that generates the authPW from e-mail address and password and implements the authPW parts of the OnePW protocol.

FxAccountsCommon.js

Defines important protocol constants, as well as the mozId observers:

 51 // Observer notifications.
 52 this.ONLOGIN_NOTIFICATION = "fxaccounts:onlogin";
 53 this.ONVERIFIED_NOTIFICATION = "fxaccounts:onverified";
 54 this.ONLOGOUT_NOTIFICATION = "fxaccounts:onlogout";
 55 
 56 // UI Requests.
 57 this.UI_REQUEST_SIGN_IN_FLOW = "signInFlow";
 58 this.UI_REQUEST_REFRESH_AUTH = "refreshAuthentication";

FxA Gaia components

All user-facing code lives in the Gaia world. This code does not implement FxA-specific functionality other than for the purpose of interacting with the user.

FxA System app

The FxA components in the System app are responsible to coordinate user interaction and to pass on information between IAC apps (FTU and Settings) and the Gecko core. Key component is the FxAccountsManager (beware of the name collision with the Gecko components) that manages state and hubs information.

First Time Use and Settings app

FTU provides screens to configure FxA from the First Time Use dialog. The settings app provides a top-level Menu entry to the same settings. FTU and Settings communicate directly with the Gaia-side FxAccountsManager though the FxAccountsIACClient. E-mail address, password and login-status are passed via IAC between the two sides.

Relying Parties

While living in the Gaia world, Relying Parties do not directly talk to the FxA Gaia components provided by FirefoxOS. Instead they go through the navigator.mozId DOM API for listening to events.

So far there's only FindMyPhone (covered in a separate review) using FxA as a identity issuer. Other services will follow.

Relevant Source Code

Permission Model

  • IAC with the FxA management process is limited to apps with the fxa-mgmt connection defined in the manifest. As of FxOS 2.0, IAC is limited to certified apps, but this might change in the future. To spot apps that talk to FxA via the IAC interface, reviewers just need to search for the fxa-mgmt property in the manifest. This can be easily automated.

https://mxr.mozilla.org/gaia/source/apps/system/manifest.webapp

 86    "connections": {
 …
 103     "fxa-mgmt": {
 104       "description": "Firefox Accounts management API",
 105       "rules": {
 106         "minimumAccessLevel": "certified"
 107       }
 108     }
 109   },
  • navigator.mozID access to the firefox-accounts issuer is restricted to privileged and certified apps. The following code in the child process implements the restriction:

https://mxr.mozilla.org/mozilla-central/source/dom/identity/nsDOMIdentity.js#611

 611     / Currently, we only permit certified and privileged apps to use
 612     / Firefox Accounts.
 613     if (aOptions.wantIssuer == "firefox-accounts" &&
 614         this._appStatus !== principal.APP_STATUS_PRIVILEGED &&
 615         this._appStatus !== principal.APP_STATUS_CERTIFIED) {
 616       message.errors.push("ERROR_NOT_AUTHORIZED_FOR_FIREFOX_ACCOUNTS");
 617     }

/!\ Are there long term plans to expose this to web or hosted apps?

  • Server API access isn't restricted in any way. Any app that implements the Hawk scheme and OnePW protocol can successfully authenticate against our FxA auth server.

Data flow

Data accessible by Relying Parties

"Relying Party" (RP) is mozId terminology for endpoints which are using mozId "Issuers" (so far Persona and FxA). Any privileged or certified FxOS app can use navigator.mozId.watch({ wantIssuer: 'firefox-accounts', ... }) to register callbacks for various events like onlogin, onready, onerror that are triggered by a call to navigator.mozId.request(). This triggers various code paths inside the central FxAccountsManager.jsm Gecko service which then returns the user ID as well as token or key material that can be sent to third parties to proof the user's authentication status and to encrypt data. The most critical potential issue is that any privileged app can read the e-mail address used for the FxA account. This poses a threat to user privacy and should be restricted.

Server communication

FxAccountsClient.js in Gecko implements the OnePW protocol and handles secure communication with the FxAccounts API server run by Mozilla. After the inital signup/login phase which ends with a shared session token being provided by the server, subsequent API access by the client to critical functions is authenticated using the HAWK token scheme inside the HTTPS tunnel.

Besides harmless status information, data exchanged with the server is restricted to e-mail addresses, and tokens or key material encoded as hex byte blobs. The server side implemented in fx-auth-server validates e-mail addresses. Hex material is handled FxOS-side by functions CommonUtils.hexToBytes() and CommonUtils.bytesAsHex() which will fail by producing harmless invalid data when presented with malformed input. Similarly, the key derivation and hashing functions used to implement the OnePW protocol are not adversely affected by malformed input, resulting in authentication failures or invalid tokens in the worst case.

GUI elements

Various GUI elements are used for input and output of FxAccounts data, but we couldn't find unsafe use. User input of the user ID in settings/fxa/elements/fxa-email.html has type="email" and as such undergoes input filtering. We traced-back use of password data to only uncritical use in hash and key derivation functions.

In the System app there are two FxA-related uses of .innerHTML, in fxa/js/fxam_error_overlay.js and fxa/js/screens/fxam_enter_email.js. They contain HTML links, but are both uncritical as their input is built from constant strings only. Server responses containing errors are resolved using static string data as well before being written into the DOM.

Risks and Mitigations

Threat Model overview

Threat Description Mitigation
Leak of authentication token An attacker could re-use the authPW, an unsalted hash of e-mail and password, to authenticate as the user as long as the password is unchanged. SSL pinning, OnePW protocol design
Leak of user ID Unauthorized apps could ID the user by reading the e-mail address of the associated FxA account. Permission model
Leak of encryption keys Apps can derive specific encryption keys, but they could be identical to keys for other apps. OnePW protocol design, proper key handling
Cross-Site Scripting Information sent by apps or the server could lead to XSS when displayed in the DOM. CSP, input validation

Leak of authentication token

The current version of the OnePW protocol heavily relies on SSL security when talking to the API server. Authentication uses the e-mail address and the authPW parameter constituting of an unsalted hash derived from e-mail address and password. Hence if SSL is breached by a man-in-the-middle, the leaked combination of e-mail-address and authPW can be used in a replay attack for impersonating the user. The current desolate state of SSL CA security merits a further hardening of the SSL connection to prevent MITM attacks, for example by state actors.

Leak of user ID

Current implementation allows any privileged FxOS app to use the navigator.mozID. In the code revision under review, the user ID is just leaked to all certified and privileged apps. This should be more restrictive, but we are able to spot potential violations in the app review process conducted by Marketpalce reviewers.

Special care needs to be taken should FxA become exposed to web apps and trusted apps in the future. The user must be enabled to detect and control access to their FxA credentials.

Leak of encryption keys

This is a complex topic beyond the scope of this document, and will be covered in a separate security review of the OnePW protocol. Currently only Sync makes use of the key derivation feature.

Cross-Site Scripting

We could only identify e-mail addresses being displayed in HTML pages, but fx-auth-server validates e-mail addresses before storing them in its database https://github.com/mozilla/fxa-auth-server/issues/402, so persistent XSS is not a problem. However, since SSL security cannot be fully trusted at this point, we are recommending to add e-mail validation to relevant input incoming from the server as well as to input coming through the FxA IAC client.

Actions & Recommendations

  • Validate e-mail address originating from user input and fxa-auth-server when retrying in case of case mismatch
  • Validate hex blobs [0-9][a-f][A-F] originating from fx-auth-server
  • Enable certificate pinning for https://api.accounts.firefox.com
  • Move check to restrict FxA access through mozID to privileged apps from child process (nsDOMIdentity.js) to parent process(DOMIdentity.jsm)
  • Create FxA-specific permission instead of leaking e-mail to all privileged apps.
  • Create means for the user to allow/prevent access to FxA creds on a per-app basis.
  • Instruct reviewers to spot and prevent "fxa-mgmt" connections in app manifests.
  • Instruct reviewers to spot and prevent navigator.mozId.watch() for FxA

Bugzilla references

  • Bug 997361 - Firefox Accounts FxA security review for the FxOS 2.0 release
  • Bug 1028398 - FxA will silently provide user's email to privileged apps in 2.0
  • Bug 1028769 - FxA navigator.mozID API: move access check from child process (nsDOMIdentity.js) to parent process(DOMIdentity.jsm)
  • Bug 1028766 - FxA's HTTP client should validate blobs originating from the server
  • Bug 1028765 - FxA's HTTP client should sanitize email addresses sent from the server
  • Bug 1020485 - enable pinning on accounts.firefox.com