A group of researchers in the Decentralized Systems Lab at UIUC discovered “a series of resource exhaustion vulnerabilities” that affect numerous proof-of-stake networks, including Qtum.

To be clear, no funds were ever at risk. The attack illustrated by the team is a type of denial-of-service (DoS) attack that can only be run against a single node at a time.

Nonetheless, we have been in touch with these researchers for several months through the team’s responsible disclosure of the bug. We appreciate the Decentralized System Lab’s research and the way they went about making us aware so we could fix the issue before it was made public over the past week.

The researchers presented two types of attacks:

“No Stake” — header spam attack

“Spent stake” — full blocks spam (not possible on Qtum)

As stated in the original article, only the “No Stake” vulnerability affected Qtum; however, we have already mitigated the risks of an attack from this vector in our 0.16.2 release.

The “No Stake” attack consisted of two similar but distinct attack vectors that could enable an attacker to cause a peer to run out of memory in the case of the first attack vector or disk space in the case of the second attack vector.

The first of these attack vectors was caused by insufficient validation before storing headers in memory. A potential attacker could, therefore, cause peers to run out of memory by flooding them with invalid headers. The reason why this was possible was that Qtum inherits Bitcoin’s headers-first feature that was introduced in version 0.10.0 of Bitcoin. In Bitcoin, the header’s proof-of-work (PoW) is validated before the header is stored in memory. However, there does not exist any PoW in Qtum’s proof-of-stake (PoS) protocol and the PoS in Qtum can only be fully validated once the full block is received since the coinstake transaction is located in the block. Therefore a potential attack could have been able to create a large number of invalid headers and send them to peers to cause them to run out of memory.

The second of these attack vectors was related to how/when Qtum does full-block validation. In Qtum, full block validation and coinstake validation is performed when a new block is received that has more total chainwork than the previous tip’s chainwork. In effect, this means that full checking of the PoS is done only when a new block is appended to the current tip or when a fork’s tip is received that has more total chainwork than the current tip and therefore triggers a block reorganization. However, In previous versions of Qtum, new blocks were committed to disk if a node received a block with chainwork equal to or greater than the current tip’s chainwork. An attacker could, therefore, make peers commit blocks to disk without the peers fully validating the PoS and cause them to run out of disk space.

Qtum’s v0.16.2, which was a recommended update included improved network security and bug fixes in the form of:

Implement network spam protection

Only request blocks from peers when their chainwork is strictly more significant than the current tip

Add extra header checks for PoS timestamp, block indexes, signature type (LowS), synchronized and rolling checkpoints.

Add recent checkpoints

Update nMinimumChainWork, defaultAssumeValid and chainTxData

Update BLOCK_CHAIN_SIZE

Fix failing Qt tests in make check on OSX Mojave

Fix getblocktemplate RPC for PoS blocks

Fix help messages for walletpassphrase and getnetworkhashps RPC’s

The block/disk attack required only a slight adjustment to when Qtum commits blocks to disk. Blocks are now committed to disk only if the block is part of a chain whose tip’s chainwork is greater than the active tip’s chainwork.

The header/memory attack was mitigated by implementing detection of potential header spam and disconnecting and banning any offending peer. Several checks that were previously only done when the full blocks were received were added to standalone header checking as well. Such as making sure that the signature contained in the header was in the correct format before committing the header to memory as large invalid signatures could be used to amplify header spam.

The network spam protection implemented in v0.16.2 detects peers who are trying to run such “No Stake” attacks and bans them. Now, nodes only request blocks from peers when their chainwork is strictly greater than the current tip. In addition to these countermeasures, we added extra header checks for PoS timestamps, block indexes, signature type (LowS), and synchronized and rolling checkpoints.

We believe that these patches should render any attacks near impossible to execute because of the added complexity and security features implemented. Despite this, we are working on a more comprehensive fix that has passed our initial tests, but since it is a comparatively more substantial change to the protocol, we require more tests.