Security/Reviews/B2G/FirefoxAccounts
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
- https://wiki.mozilla.org/Identity/Firefox_Accounts
- https://github.com/mozilla/fxa-auth-server/wiki/onepw-protocol
- https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md
- https://mana.mozilla.org/wiki/display/SECURITY/Home
- Flow diagram ("obsolete, but usable") https://mxr.mozilla.org/gaia/source/apps/system/js/fxa_manager.js#23
- https://mana.mozilla.org/wiki/display/SECURITY/Firefox+Accounts+Security+Design+Review
- https://air.mozilla.org/firefox-accounts-and-sync-in-ff29/
- https://wiki.mozilla.org/User:Dria/PiCL_Future_Ideas
- https://developer.mozilla.org/en-US/docs/Firefox-Accounts-on-FirefoxOS
- https://etherpad.mozilla.org/tracing-mozId-API
- Review preparations started in late 2013
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:
- 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.
- FTU and Settings communicate user ID (e-mail address) and password to the system app via IAC
- The system app sends credentials to gecko via custom events
- Gecko (FirefoxAccountsManagerService) communicates with api.accounts.firefox.com to validate the credentials
We identified three main data paths in and out of the FxA code:
- The IAC interface between certified apps and the FxA Gaia/System code
- The navigator.mozId DOM interface between Relying Parties (gaia apps) and the FxA Gecko code
- 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
Gaia
Gecko
Identity API
- Identity API code
- B2G/gecko/toolkit/identity/
- B2G/gecko/toolkit/identity/FirefoxAccounts.jsm
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
- Bug tracking pinning support in Gecko: https://bugzilla.mozilla.org/show_bug.cgi?id=744204
- Bug tracking pinning usage among services: https://bugzilla.mozilla.org/show_bug.cgi?id=1005430
- Pinning on FxA API server: https://bugzilla.mozilla.org/show_bug.cgi?id=1020485
- 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