Zcash masks address vulnerabilities or reveals full node IP address (with solution)

The technical battle for anonymous coins is very interesting. For example, KMD core developer Duke Leto has just published a blog post about the vulnerability of Zcash and most of its forked coins, and this vulnerability may reveal the use of blocked addresses ( The full node IP address of zaddr).

It also assigned a Common Vulnerabilities and Exposures (CVE) code CVE-2019-16930 to track this issue.

(The following is the specific disclosure)

Too long to watch: Since the establishment of the Zcash and Zcash protocols, there is a vulnerability in all blocked addresses. It appears in all Zcash source code forks, which allows an attacker to use it to find the ip address of the full node with the masked address (zaddr). In other words, if Alice gives Bob a masked address (zaddr) for payment, it actually allows Bob to discover Alice's IP address, which is against the design of the Zcash protocol.

Affected groups:

Anyone who uses a blocked address (zaddr) and shares a blocked address (zaddr) with a third party, for example:

  1. If you publicly posted your blocked address (zaddr) on social media;
  2. If you gave your shielded address (zaddr) in the github/email/IRC vulnerability report;
  3. If you have told your exchange address (zaddr) to the exchange, the mining pool or the company;
  4. If you have replied to your blocked address (zaddr) in a blocked memo;

Groups not affected by vulnerabilities:

If you have never used zaddr, the vulnerability will not affect you:

  1. If you just sent money to other people who use zaddr, but never received funds, you are safe;
  2. If you use Tor/TAILS, IP metadata leakage is not valuable information for attackers.

Fork-in-garbage-disposal

Affected cryptocurrency (non-exhaustive list):

  1. Zcash (ZEC)
  2. Hush (HUSH)
  3. Pirate (ARRR)
  4. All Komodo (KMD) smart chains with zaddr (enabled by default)
  5. Horizen (ZEN)
  6. Zero (ZER)
  7. VoteCoin (VOT)
  8. Snowgem (XSG)
  9. BitcoinZ (BTCZ)
  10. LitecoinZ (LTZ)
  11. Zelcash (ZEL)
  12. Ycash (YEC)
  13. Arrow (ARW)
  14. Verus (VRSC)
  15. BitcoinPrivate (BTCP)
  16. ZClassic (ZCL)
  17. Anon (ANON)

To clarify, although Bitcoin Gold (BTG) uses the Equihash PoW consensus mechanism provided by Zcash, it is not a fork of the Zcash source code, nor does it use a masked address (zaddr), so it is not affected.

Additional notes: KMD used to use the shielded address (zaddr), but later disabled this feature, Safecoin (SAFE) took a similar route, which currently disables the masked address (zaddr).

Mitigation measures

First, the primary way to prevent this "metadata leak attack" is to use Tor with -onlynet=onion , or better, using the TAILS operating system while using your favorite -onlynet=onion .

Second, users can create a brand new wallet.dat (wallet file) with the new zaddr and send all funds to that address. If the user keeps this new zaddr private, it will not be attacked by this type of attack.

Zcash posted an urgent source code (no binaries) here.

If you don't want to know who your zaddr address knows about your IP address, I suggest you create a new wallet and stop using the old wallet before the software releases the update.

At this point, ordinary users may be able to stop reading.

More suggestions

If you run a mine that supports a shielded address (zaddr), you do not need to provide a public list of all miners and shielded addresses (zaddr). This severely eliminates the privacy of miners due to current metadata breach attacks and other reasons. This has been common in the past, but most mines have stopped this practice due to privacy concerns.

Also don't give zaddr in the github error report! Many tools continually extract potentially sensitive data and open source information from all public code repositories.

For added security, if you have to give a masked address (zaddr), you can isolate them to a separate wallet.dat, which is usually not used and remains offline, and the other has a masked address ( The zaddr) wallet can be used to send funds. This type of vulnerability is unusable for this node because the wallet that sent the funds never issued zaddr.

Code analysis

This vulnerability was introduced in the original Zcash codebase and was submitted in 2016:

45

"Introduce the new "libzcash" zcash protocol API and the cryptographic structure around the zkSNARK circuit."

This submission adds the vulnerability code to the older version of the blocked address, and the new version of the blocked address code copies it.

The vulnerability exists in Zcash's P2P layer (inherited from bitcoin), where nodes exchange data with peer nodes.

Interpretation of the attack:

  1. The attacker node relays the invalid transaction to the mempool of its peer node;
  2. This transaction has invalid serialization for the encrypted memo field;
  3. A node that does not have a private key and does not have a blocked address to view the key, usually reacts to this invalid transaction;
  4. A node with a private key (or view key) will generate a C++ exception;
  5. This C++ exception can lead to different network behaviors, exposing the "identity" of the node;
  6. There are no records of such attacks on the blockchain or browser;

The code to fix the vulnerability is here: https://github.com/zcash/zcash/commit/c1fbf8ab5d73cff5e1f45236995857c75ba4128d

The core changes are as follows:

 - CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); - ss << pt.get(); - SaplingNotePlaintext ret; - ss >> ret; + try { + CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); + ss << pt.get(); + ss >> ret; + assert(ss.size() == 0); + } catch (const boost::thread_interrupted&) { + throw; + } catch (...) { + return boost::none; + } 

The following line of code without try/catch is the core reason for the existence of the vulnerability:

 ss << pt.get(); 

Since pt is data controlled by an attacker, it is being written to the local CDataStream ss object and therefore needs to be processed more carefully.

Now we can see that only the boost::thread_interrupted type of exception bubble, so other exceptions are "destroyed", boost::none will return. This makes the node with the zaddr address private key the same as all other nodes, preventing metadata leakage.

The author notes that there is still a vulnerable code for finding old Sprout addresses.

Some people may think that this kind of attack can only target the peer node of the node, but not the whole network, but it is insignificant to increase the maximum peer node count. It is feasible to study the whole network through one or several nodes.

Advanced attackers will have a zaddr database that they want to connect to IP, then run nodes that are densely connected to the entire network, and periodically send invalid transactions to the mempools of all peers to establish (timestamp, Zaddr, IP address) Triad data history. They can then use the data and link it to other data through quantitative analysis and timing analysis to completely unblock the anonymity of the transaction and bind them directly to the IP address and geographic location.