Critical vulnerability in Grin 1.0.1 and older (fixed in 1.0.2)

#1

Contents

Summary

On Friday February 22nd we were notified of a critical security vulnerability through our responsible disclosure process. A fix was released as part of v1.0.2 three days later, on Monday Feb 25 and CVE-2019-9195 reserved. This document provides details on the vulnerability, the fix, and what measures we have taken to protect Grin users.

The vulnerability was discovered by the security firm we hired for our audit, Coinspect. It is related to the node syncing process and made it possible for a remote attacker to obtain write access to any part of the filesystem the node process had privileges to. This issue was fixed as part of the release of v1.0.2 and therefore we urge you to upgrade to v1.0.2 immediately. Users who are running this version or greater are not exposed. We have not seen any signs of the attack having been exploited, but we cannot know for sure that it has not been either.

At the time of this writing, Mainnet Grin is ~49 days old. Its simple design, minimal cryptographic assumptions, and implementation in Rust, avoid many pitfalls. And whilst user safety is a high priority for us and we do our best to ensure it, it’s important to underline that Grin is still highly experimental software that is bound to have many bugs.

Recommended action check-list

  1. Consider any environment that a v1.0.1 node or below was running in and had privileges to as potentially exposed.
  2. Boot up v1.0.2 nodes in a new environment.
  3. Never run grin as root.

Background

Third party disclosure

On Tuesday, Feb 26, the vulnerability was disclosed on keybase to known Grin exchanges, Grin mining pools, and selected MimbleWimble implementations, revealing that the vulnerability is related to the syncing process and makes it possible for a remote attacker to obtain file system write access to any part of the filesystem the node process has privileges to, and urging an upgrade to 1.0.2

Timeline of events

  • Feb 22nd - responsible disclosure by coinspect
  • Feb 25th - fix released with v1.0.2, CVE assigned
  • Feb 26th - limited disclosure to mining pools and exchanges
  • Mar 5th - Public disclosure

Technical details of CVE-2019-9195

The vulnerability makes it possible for a remote attacker to obtain file system write access to any part of the filesystem the node process has privileges to, and subsequent arbitrary code execution if a binary is replaced (for example the grin binary itself). This is caused by a Zip Slip in the extraction process of the zip that contains the blockchain state, necessary for a node to get synchronized with the latest chain.

To exploit the vulnerability, an attacker needs to provide a forged zip file to a Grin node that’s trying to synchronize itself with the latest state of the blockchain. This can happen either on first startup, or subsequently is a node is stopped for more than a few days and then restarted.

Detailed Fix Description

In short, remediating the vulnerability was done with 2 fixes:

  1. Detect paths that would result in creating a file outside of the directory
    the zip is being extracted into and skip the corresponding zip file.
  2. Filter files extracted from the zip from a whitelist of the data files we
    expect in a Grin state archive.

The txhashset zip file obtained from peers should only contain paths

kernel/pmmr_data.bin
kernel/pmmr_hash.bin
rangeproof/pmmr_prun.bin
rangeproof/pmmr_leaf.bin.<blockhash>
rangeproof/pmmr_data.bin
rangeproof/pmmr_hash.bin
output/pmmr_prun.bin
output/pmmr_leaf.bin.<blockhash>
output/pmmr_data.bin
output/pmmr_hash.bin

where <blockhash> is a block hash shortened to the first 12 hex digits, such as 0000045a7af3.

A bad zip file could however contain a path

../../../grin/target/release/grin

to try and overwrite the grin executable. The old zip::decompress function in util/src/zip.rs had no safeguard against such paths.

The fixed version in util/src/zip.rs has an additional 3rd argument string of expected filepaths,
which function expected_file in chain/src/txhashset/txhashset.rs computes as

    format!(
      r#"^({}|{}|{})(/pmmr_(hash|data|leaf|prun)\.bin(\.\w*)?)?$"#,
      OUTPUT_SUBDIR, KERNEL_SUBDIR, RANGE_PROOF_SUBDIR
    )
    .as_str()

capturing the above file paths.

When iterating over all file paths in the zip file, the fixed code applies function sanitized_name to each one. The zip-rs crate documentation describes its function as:

Get the name of the file in a sanitized form. It truncates the name to the first NULL byte, removes a leading ‘/’ and removes .. parts.

If its sanitized name differs from the filepath (as is the necessarily the case when escaping the target directory) or if the sanitized name doesn’t satisfy the regular expression, then we log

info!("ignoring a suspicious file: {}", file.name());

and skip the file.

13 Likes
Please help evaluate: Grin's security process
pinned globally #2
#4

Thanks. Got it done, after my mind ‘slipping a gear’ (I think I’m so burned out from the old days-where you had to compile everything by hand-that I sometimes forget how easy Git is :slight_smile:
I started editing by hand, then had to rename the files, because Git won’t let you pull unless you commit or rename files.
In any case, I appreciate all the efforts by the dev team :slight_smile:

1 Like
#5

Hi, Igno. Crypto journalist here. We have spoken before :slight_smile: Nice work in implementing a fix to this issue so quickly. Is someone available to explain what was at stake with this vulnerability & how the team was able to provide a fix?

#6

Is wallet 713 also affected?
@jaspervdm

#7

Over 24 hours after this critical security vulnerability notice:

  • Looks on a node with 101 peers: only 39% nodes upgraded.
  • On another node with 171 peers: only 55.5% nodes upgraded.

Looks like there’re about 45% ~ 60% people still don’t receive this critical notice, or they received and just ignored?

But upgrading is quite simple and can be done in a few minutes:

  1. download the binary from v1.0.2
  2. tar zxvf grin-v1.0.2-xxx.tgz
  3. move that grin binary to overwrite the server running binary
  4. restart the grin server

Please don’t leave the hole open there to get a chance to be hacked :slight_smile:

#8

@gary binary dont work in some systems. Just building it

#9

No, this is a node sync issue not a wallet issue

#10

Thanks for the heads up! Great support, I will switch it later tonight.

#11

This post goes unanswered for a month, finally gets and answer, but which doesn’t explain much, and everyone wonders why there are still people running the old node versions. We’re not all linux wizards. I haven’t found clear instruction for newbs about how to upgrade the wallet and node versions. So, don’t be surprised if the network has insecure nodes.

#12

You don’t need to be a linux wizard to kill your node process, replace the old binary with the new, restart your node.