# NEAR Hackount ***Disclaimer*** *1. I have been working in the NEAR Protocol ecosystem for about 2 years and for a long time I have been wanting to do this experiment and document it.* *2. The goals for both this report and experiment are not to spread FUD, but to help increase users' safety and awareness of the software products they use on a daily basis.* *3. There are many alternatives to web-based wallets today on the NEAR ecosystem. Make a preference using hardware wallets when you can.* *4. This document was produced as an educational material for developers and users interested in security.* *5. NEAR accounts support key rotation, this means that compromised keys can get deleted very easily.* --- Certain browser extensions may pose a threat to NEAR web-based wallets. An experiment was conducted to test the account safety when using web-based wallets. The goal of the experiment was to get sensitive information stored within the wallet application, specifically FullAccess keys. Take a look at the following demo: {%youtube 2xk4IGN3lFc %} - Mirror Arweave: [5dKPAm6uTrk7-JrgSVa86-7tZx-XnZTizhfKCKLtNTo](https://arweave.net/5dKPAm6uTrk7-JrgSVa86-7tZx-XnZTizhfKCKLtNTo) - Mirror IPFS: [bafybeigtzdqw7n622r7erot6iar4hfdk3phjnaday4vqlgoggoy3tes6qu](https://bafybeigtzdqw7n622r7erot6iar4hfdk3phjnaday4vqlgoggoy3tes6qu.ipfs.nftstorage.link/) ## NEAR web-based wallet providers One of the ways users can use to access their accounts on NEAR is via web-based wallets. Two examples of these are [NEAR Wallet](https://wallet.near.org) and [MyNearWallet](https://mynearwallet.com/). Web-based wallets store [**FullAccess**](https://docs.near.org/concepts/basics/accounts/access-keys#full-access-keys) keys in [Local Storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage). It is widely known that web-based wallets are not the most secure wallet providers, but users end up using them for the sake of a good user experience. The key used to store a FullAccess key as an item on Local Storage follows this pattern `nearlib:keystore:<account_id>:default`. The corresponding value is a private key. ## Chrome extension Extensions are software programs, built on web technologies (such as HTML, CSS, and JavaScript) that enable users to customize the Chrome browsing experience. This experiment was conducted on Chrome with the version 107.0.5304.110, but it should work for most [Chromium-based browsers](https://en.wikipedia.org/wiki/Chromium_(web_browser)) such as Brave, Chromium and Edge. ## The experiment The experiment consisted on developing a [Chrome extension](https://github.com/microchipgnu/near-web-hackount) that would get access to the web-based wallet Local Storage. In the initial screen a user can select which wallet provider they want to load. Notice that it is required user interaction here, but certain extensions may not require that. Extensions may react to events, such as [`onInstalled`](https://developer.chrome.com/docs/extensions/reference/runtime/#event-onInstalled) in which fire when the extension is installed, in this case extensions would not require user interaction. As soon as the user selects the wallet prodiver, a new tab opens and loads the wallet application. Notice that the new tab opens in an imperceptible way. Once the tab opens, a script is injected. This script will filter and return the keys stored on Local Storage. Once the script finishes running, all the accounts filtered and their respective private keys get displayed. This shows how an extension with a set of similar permissions may compromise accounts. The wallet tab is then closed. ![](https://i.imgur.com/HcefXex.png) ### Permissions The permissions required for the experiment to work are standard permissions. This is an excerpt of the [Manifest V3](https://developer.chrome.com/docs/extensions/mv3/intro/) file. ```json { "permissions": [ "tabs", "scripting" ], "host_permissions": ["<all_urls>"] } ``` The set of permissions above are enough to allow an extension opening a new tab with an arbitrary URL and run scripts. This translates in this: ![](https://i.imgur.com/Utxgdrd.png) By visiting [chrome://extensions](chrome://extensions) it can be noted that the requested permissions are similar to popular extensions. ![](https://i.imgur.com/DKODuWJ.png) ### Script Given the `scripting` permission, the extension just simply needs to execute `getKeys` to retrieve all accounts. Note that in this example it is only retrieving the localstorage item keys and not the corresponding values (private keys) -- doing so would be trivial and it can be seen in the [GitHub repo](https://github.com/microchipgnu/near-web-hackount) code. ```jsx const getKeys = () => { return Object.keys(localStorage) .filter((key: string) => key.includes("nearlib")) } chrome.scripting.executeScript( { target: { tabId: <target_tab_id> }, func: getKeys, }, (results: any) => { // do something with the results } ) ``` ## Install the extension *No data is getting transfered when using this extension. Read the source code. Do your own research.* 1. Download the folder extension in https://github.com/microchipgnu/near-web-hackount 2. Navigate to [chrome://extensions/](chrome://extensions/) 3. Activate `Developer mode` 4. Select `Load unpacked` 5. Choose the downloaded extension folder ## Source code The code is accessible here: https://github.com/microchipgnu/near-web-hackount All the information provided in both the repo and this report serves for educational purposes only. The creator of this content is in no way responsible for any misuse of the information. --- *If you have thoughts or questions about this, please reach out to me on Twitter or Telegram (@microchipgnu).* Arweave mirror: https://arweave.net/Q2KqO9VeIWbBIMdeTRaO8pcHoylxwe65f1ihLGGRxzk