github twitter linkedin email rss
Lisk MITM Vulnerability Report
Jun 28, 2017

I reported multiple practical attacks that could have been carried out on Lisk users due to the lack of encrypted or validated communication in their Lisk Nano client. If exploited, the vulnerabilities could have put users’ privacy, funds, and security at risk.

The Lisk team was a pleasure to work with and took speedy action to fix the issues.

Report

Because all communications between Lisk Nano and the official nodes were unencrypted, they could have been intercepted, monitored, and modified by malicious actors. Additionally, because there was little to no client side validation of information received, the client had few protections against these attacks.

I implemented and tested the exploits detailed below. They required an attacker to have access to the communications between the Lisk public nodes and the application (e.g. someone on the same wifi network, corporations/schools/etc with network monitoring software, ISPs, or government actors surveilling any of the aforementioned attack points).

User Identity Unmasking

An individual with the ability to monitor internet communications could identify the Lisk address of a certain user. Most calls the client makes to the API include the user’s address as a parameter (e.g. /api/accounts?address=3960480236702516981L). The address could have been personally tied to a user and allowed their transactions to be surveilled. This nullified almost any privacy protections offered by the currency. For example, a government could serve a warrant to an ISP to reveal the PII of the user of an anonymous address. Similarly, a criminal at a coffee shop could monitor if anyone present owns a substantial amount of Lisk and attempt to steal it from them.

Personal Address Falsification

An attacker could modify the the GUI’s displayed receiving address to another arbitrary address regardless of what the actual account of the user is. When a user logs into the client, it makes a call to /api/accounts?address=address, which returns something like:

{
    "account": {
        "address": "3960480236702516981L",
        "balance": "120432791",
        "multisignatures": [],
        "publicKey": "b0a5124c1f8e8b6198c63b9e7ea81307a68a738806161b0efa9ebeeef3af3a64",
        "secondPublicKey": null,
        "secondSignature": 0,
        "u_multisignatures": [],
        "unconfirmedBalance": "120432791",
        "unconfirmedSignature": 0
    },
    "success": true
}

If the response were intercepted and the returned “address” value changed to a different value, the returned address would have been displayed in the GUI’s address field, despite the user having no control over that address. An attacker could trick a user’s wallet to display their own address. Because very few users memorize their addresses, this attack could lead to users withdrawing funds to and giving out the attacker’s address instead of their own.

Transaction Fabrication

Every few seconds, the Nano client calls the Lisk api at /api/transactions?senderId=3960480236702516981L&recipientId=3960480236702516981L to obtain the address’ recent transactions. This call returns an array of transactions from the users wallet. Anyone who can MITM the call can display arbitrary fake transactions at will by responding with something like:

{
   "success":true,
   "transactions":[
      {
         "id":"faketransaction",
         "height": 9007199254740992,
         "blockId":"17064341383280419457",
         "type":0,
         "timestamp":32437235,
         "senderPublicKey":"fake",
         "senderId":"fake",
         "recipientId":"fake",
         "recipientPublicKey":"fake",
         "amount":1234,
         "fee":10000,
         "signature":"fake",
         "signatures":[],
         "confirmations":0,
         "asset":{
         }
      }
   ],
   "count":"1"
}

This transaction would show up in the wallet even though it’s obviously invalid. A store accepting Lisk or an individual doing a p2p transaction could be tricked into thinking they received funds or that a transaction confirmed when it didn’t actually exist on the blockchain.

Fix

The Lisk team fixed the vulnerability by connecting to peers via SSL by default. The pull request can be viewed here: https://github.com/LiskHQ/Lisk-js/pull/131.

Timeline

  • June 4, 2017: Exploit reported
  • June 9, 2017: Exploit acknowledged by Lisk
  • June 11, 2017: Exploit fixed
  • June 12, 2017: Lisk awarded a 200 Lisk (~$800) bounty

Back to posts