Security Incident on July 19, 2023

Summary

This report discloses a discovered vulnerability within the Harmony blockchain protocol, specifically in the staking precompile implementation and handling state reverts. The vulnerability was initially observed during the synchronization of a testnet node from scratch. This process was halted due to an error named “invalid merkle root”, indicating a discrepancy between the state of the local node and the state reported by a remote node. The problematic block was identified as block 2058022.

Details

The block contained a transaction to a Yield Warrior NFT (a runner-up in the Encode Club Hackathon). Inference from the block data revealed that the Yield Warrior NFT used the staking precompile from a smart contract to participate in staking. Transactions from this block showed one transaction related to the Yield Warrior NFT that failed and reverted, while the following transaction, also associated with staking, was successful. This observation raised a hypothesis of a potential problem in the code handling state reverts.

Detailed examination pointed towards PR #4374, a significant part of the Ethereum statedb code to Harmony. The specific problem stemmed from a change that unintentionally modified the handling of reverts, leading to a vulnerability where state reverts were not processed correctly.

Vulnerability Proof of Concept

If the revert of the validator wrapper failed, but the state database revert succeeded, it would be possible for an actor to create delegated ONEs without an actual transfer of tokens. This could be achieved by delegating through a smart contract and then causing it to revert, costing only the transaction gas. This scenario could be exploited indefinitely if the actor had a minimum of 100 ONE (+ gas).

An example of this is illustrated below:

function exploitTest(address validatorAddress) public payable {
    delegate(validatorAddress, msg.value);
    revert();
}

This allowed the contract to retain its original balance of ONE tokens while having additional staked tokens that could be undelegated.

Fix

A patch was designed and implemented to correct this vulnerability by restoring the removed line of code from PR #4374. The patch ensured that the correct state was restored in case of reverts.

diff --git a/core/state/journal.go b/core/state/journal.go
index 210f3880..c5e3f743 100644
--- a/core/state/journal.go
+++ b/core/state/journal.go
@@ -156,7 +156,8 @@ func (v validatorWrapperChange) dirtied() *common.Address {
}

// revert undoes the changes introduced by this journal entry.
-func (v validatorWrapperChange) revert(*DB) {
+func (v validatorWrapperChange) revert(s *DB) {
+ s.stateValidators[*(v.address)] = v.prev
}

func (ch createObjectChange) revert(s *DB) {

Impact and Exploitation Analysis

The vulnerability was introduced with the release of version 2023.2.1. However, due to the inability to achieve consensus with this version, it was not widely deployed across the validator network. The vulnerability became more exposed when the consensus issue was resolved with the release of version 2023.2.4. There existed a potential period during which an actor, aware of the issue and possessing the technical expertise, could have garnered the necessary quorum to exploit this vulnerability.

A thorough review of transactions and the explorer revealed no evidence of exploitation. However, this conclusion is not definitive due to the lack of internal transactions in the explorer. To confirm that no exploitation occurred, a process of syncing an older version of the database using the patched binary was initiated. This process should identify instances where the vulnerability was exploited, as the patched binary will reject such blocks.

Preventive Measures

A corrective patch was developed promptly upon the discovery of the vulnerability. This patch was merged into a subsequent update (v8090-v2023.2.1–430-gc7a63bab-dirty) and deployed to all internal nodes. While planning to upgrade external nodes, the vulnerability was not disclosed publicly until all validators had completed the upgrade. An analysis of the network’s transactions showed that the network was not exploited.

Prevention of Similar Issues

Future prevention of similar issues includes submitting smaller pull requests to ensure that changes are easier to review and less prone to error. Greater reviewer involvement is also suggested to increase the likelihood of identifying potential problems. Including test cases for these specific scenarios is also recommended for any PR testing to ensure the expected behavior occurs.

Conclusion

While this incident was unfortunate, it has presented a valuable learning opportunity, contributing to the robustness and security of the Harmony protocol. Through our collective efforts, we identified and corrected this vulnerability, safeguarding our community’s and users’ interests. We continue to strive for and uphold the highest standards in all aspects of our work and sincerely appreciate the community’s continued support and trust.

2 Likes