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-08-08 18:42 UTC

I have added the exact filesystem locations / paths to the relevant Jaxx local storage file to the demonstration section.

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 using the sqlite3 tool, or if you prefer GUIs you can use sqlitebrowser. You can find this file at the following locations depending on your operating system, and whether you’re using the desktop app or the chrome extension:

  • Linux desktop: $HOME/.config/Jaxx/Local\ Storage/file__0.localstorage
  • Linux chrome extension: $HOME/.config/google-chrome/Default/Local Storage/chrome-extension_ancbofgphhmhcchnaognahmjfajaecmo_0.localstorage
  • macOS desktop: /Users/[username]/Library/Application Support/Jaxx/Local Storage/file__0.localstorage, thanks to Manuel in the comments;
  • Windows desktop: C:\Users\<Your Computer's User Name>\AppData\Roaming\Jaxx\Local Storage
  • Windows chrome extension: C:\Users\<Your Computer's User Name>\Local\Google\Chrome\User Data\Default\Local Storage\chrome-extension_ancbofgphhmhcchnaognahmjfajaecmo_0.localstorage

At the sqlite3 prompt, do the following:

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

(If you opted for sqlitebrowser, just copy out the value of the mnemonic key.)

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.)

68 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. 🙂

      1. Hey I was hoping you could help me. I created a Jaxx account and the app crashed as I was receiving my 12 word phrase and now I am locked out. I have all the other transaction data from my transfer form coinbase to prove it’s mine. Would you be able to help me extract this phrase from my app? I’d be happy to pay for this service as I have locked myself out of a decent amount of money. I’ve tried everything and Jaxx support won’t do anything.

        1. I have updated the “demonstration” section with the full paths to the sqlite / localstorage files.

          Does that help? Can you open the relevant localstorage file and read out the “mnemonic” value?

        2. Andrew, are you stupid? Why didn’t you write your recovery phrase down BEFORE YOU DEPOSIT >ANY< MONEY INTO YOUR WALLET??? It's just as stupid as making a random Paypal password and then don't save it!

          Did you just skip the wallet-setup steps or what???

          A quick 10 minute Youtube video would have showed you, how to setup a wallet PROPERLY!

          Well, now you're fu**ed…

    2. This also applies for the Android-App!
      I was able to replicate my security pin and backup phrase by doing the following:

      Use “adb backup” to perform an app-backup for com.kryptokit.jaxx and extract backup using “dd”
      Open local storage database located in “com.kryptokit.jaxx\r\app_webview\Local Storage” within an sql browser
      Browse “ItemTable” and search for pin
      Paste value into https://crackstation.net/ and receive “security” pin

  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?

        2. It does not work for me. I extracted the blob value of the userPin key but every online de-hashing website tells me the provided string is not a valid hash.

    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. 🙂

      1. Would it be possible to give a complete path for a chrome extension of Jaxx on windows 7? I keep getting ” The system cannot find the path specified”. I am lost and the path forward looks dim.

        1. Hi there James,

          I have updated the post with the exact filenames in the demonstration section. There are two paths for Windows: One for the standalone Jaxx app, and one for the Chrome extension. It sounds like you have the latter so use that one.

          1. I was so happy to see the path for chrome extension. Unfortunately I have tried it 3 times making sure it was entered correctly and it was bounced 3 times. The error msg didn’t say no path instead ask for me to the check spelling. I noticed that Jaxx is not mention in the path. How does the C drive know which chrome extension it is looking for? I have 4 different ones beside Jaxx.

            1. For chrome extensions, the only important thing is the extension ID. In your “Local Storage” directory, one of the filenames should be chrome-extension_ancbofgphhmhcchnaognahmjfajaecmo_0.localstorage

              (ancbofgphh…. is the extension’s unique ID)

              If that file is not there, it means your Jaxx extension is either not installed, or installed but not activated. In both cases, there’s no data to analyse.

              1. I was able to get down to the file by using C:\Users\\AppData\Local\Google\Chrome\User Data\Default\Local Storage\chrome-extension_ancbofgphhmhcchnaognahmjfajaecmo_0.localstorage but then I was asked which program I wanted to use to open it. Stumped again. I thought it would be Chrome but it seems not one of my options.

                1. Brief history – Around mid July everyone who had bitcoins on coinbase was advised to move them off the exchange to an user controlled wallet for the up coming BTC fork. I did this and picked Jaxx as the wallet. The version I had was 1.2.17 or 18. At the end of month check the wallet, everything okay, the next day couldn’t open the wallet. Jaxx support advised everyone on their blog about what turned out to be 2+ day problem. On the morning before the fork when I opened Jaxx it wasn’t my wallet but a new version 1.2.20 and I was asked to pick 1 of 2 choices, new wallet or type in 12 words for old one. I stopped the process and did not pick either of the 2. Searched for the paper I wrote the 12 words on without success. Found your article with a search and was amazed. I finally work down to 2 files in localstorage.One file (the journal) 0KB the other 5KB. Up to this point I always believed that the 12 words were stored on my machine and Jaxx program sent them for validation before starting up and as long as I don’t pick one of the 2 choices the old wallet 12 words was still in memory on my machine. I now believe he wipes the localstorage as a setup to installing the rest of the program. I think he doesn’t need the info.One choice he assigns it the other you provide it. The only question I have is what happens to those BTC coinx Jaxx holds but no one can ever claim also includes the BCC coins from the fork?

  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….

  14. Big thanks for this warning!
    Since the Jaxx developers don’t see a problem in this und thus don’t want to fix it, the best long term solution is to switch to Exodus, I’d say…
    Bummer – but what can you do…?

    1. At least you can still use the same wallet if u recover it in Exodus with the given 12-word-backup-phrase.
      But don’t forget to remove the Jaxx data folder afterwards….

  15. I just saw your Update, how exactly do you know exodus encrypts your private keys? they create your wallet before even asking for your password, in fact, you cannot set a password until you transfer money to your wallet, if someone would to investigate this, it would be clear that either they use a hard coded encryption key, or they generate a random one and store it somewhere on the disk in a reversible manner.
    Security through obscurity. I urge you not to use exodus/Jaxx without properly securing your wallet on your own (file encryption using veracrypt containers for example), it seems they cannot take care of such a simple task, and we need to do it by ourselves.

  16. Does anyone know exactly what this file does ?
    Unless I’m missing something, the passphrase is held cloud based or blockchain based so you can restore your wallet in case of total hardware loss. So what’s the point of this file, and if you delete it can you still use the desktop Wallet ?

  17. So I answered one of my own questions through testing – removing the two files means Jaxx has “lost” your money. Re-running Jaxx again after moving the files away started the whole Jaxx initial wallet setup again.

    However moving the files back caused no issues, and re-opening Jaxx showed my full balances again.

    Based on this, a simpler workaround would be to encrypt these files in place using something like 7-Zip or move them to an encrypted container such as Veracrypt. You’d need to manually unzip/copy from Veracrypt to use Jaxx, but it’s an easy albeit annoying step and at least everything is secure while you aren’t using Jaxx while this is being (hopefully) fixed.

  18. using a chromebook the file is (chronos@localhost):
    /home/user/c1b02c025a7894ff389c2eee3343f16cc5621999/Local\ Storage/chrome-extension_ancbofgphhmhcchnaognahmjfajaecmo_0.localstorage

    the directory c1b02c025a7894ff389c2eee3343f16cc5621999 may be different on your machine.

    I was able to extract my forgotten PIN as described above using sqlite3.

  19. Would it be possible to give a complete path for a chrome extension of Jaxx on windows 7? I keep getting ” The system cannot find the path specified”. I am lost and the path forward looks dim.

  20. What you can do to securely save the complete Jaxx folder in macOS Sierra is the following:
    • Create a (100 Mb. or so) 256bit AES encrypted and password protected .dmg file in Disk Utility;
    • Name that disk image “Jaxx wallet”;
    • Copy the complete Jaxx folder from /Users/[username]/Library/Application Support/ to the disk image, and deleted the Jaxx folder from the Application Support folder;
    • Make a symlink to the copied Jaxx folder on the DMG with the SymbolicLinker tool (or use the Terminal to do it: just Google how to);
    • Rename the symlink to “Jaxx” and place it in the Application Support folder;
    • Now, every time you start Jaxx without opening the Disk image first, you get an error message, remembering you to open the disk image first. After opening the disk image, Jaxx runs without problems;
    • I also made a simple automator script called “Start Jaxx”. This opens the disk image (prompting me for the password) and starts Jaxx immediately after that.

    I only need to remember to eject the disk image after quitting Jaxx, which I could probably add to the Automator script as wel.

  21. his this vulnerability been fixed yet? I’ve been trying the instructions but i can’t seem to get it to work. I could really use some help getting the back phrases. windows 10 did a update and its locked me out of my wallet and i can’t find my phrases. all my funds are in that wallet ;-;

Leave a Reply

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