Heimdall Security Bug Fix

Summary

A Security bug on Heimdall was previously reported and confirmed via the Bug Bounty Program. Under highly specific – and very unlikely – conditions being met, the bug could have potentially allowed a malicious actor to perform a Denial of Service (DoS) on the Heimdall network.

Root Cause

Heimdall needs to acquire specific public keys, which are contained in two messages (ValidatorJoin, SignerUpdate). These keys are crucial for the validator to sign PoS commitments and votes. The validity of these public keys is confirmed against the corresponding Ethereum log in the StakeInfo contract. This process is meant to ensure that the public key aligns with the one selected by the validator.

However, a complication arises due to an implementation nuance in the secp256k1 library utilized in Heimdall/Peppermint. Public keys must include an additional prefix byte, making them a total of 65 bytes long. Unfortunately, Heimdall does not verify the first byte of the public key in any message. This contrasts with the secp256k1 signature validation, which requires the prefix to be 0x04, 0x06, or 0x07; otherwise, validation fails.

The sole validation performed on the public key bytes is to ensure that the slice pubkey[1:] matches the 64-byte public key from the Ethereum log. The initial byte provided in the message is merely copied and stored without validation. Additionally, attempting to verify the address generated by hashing the public key proves futile, as the address is derived from the truncated hash of the 64-byte public key, once again disregarding the prefix byte.

As a result of this lack of validation, whenever a new validator joins the network or an existing validator updates their signing key, a malicious actor can exploit the situation by submitting a message containing a corrupted version of the public key for that validator, such as setting the first byte to 0xff.

This corrupted message will be readily accepted and verified by all validators, including the victim validator. Consequently, each validator will store the corrupted public key. Subsequently, when the victim validator attempts to send a commitment or proposal, all other validators will attempt to verify the signature using the corrupted key, leading to constant verification failures.

This situation renders the victim validator incapable of participating in the PoS protocol until the signing key is updated again, a process that takes 100 epochs. Moreover, even after updating the signing key, the attacker can simply repeat the attack.

Resolution and Recovery

A patch was successfully released on March 14th 2024, with Heimdall tag v1.0.5. It consists of one main PR, where a new method has been introduced. The function, called IsPubKeyFirstByteValid checks the first byte of the validator’s public key every time a SignerUpdate or a ValidatorJoin event is invoked. It basically validates that the first byte of the public key is 0x04, which stands for “uncompressed public key”, the format used by Polygon PoS nodes. The unit tests confirmed the validity of this new method.

The patch was first tested on a devnet, then tested and rolled out on Mumbai and Mainnet nodes. A release announcement was shared, allowing all the validators to upgrade.

1 Like

It’s great to hear that the security bug on Heimdall was identified and patched promptly. The implementation of the new method to validate the first byte of the public key seems like a solid solution. It’s reassuring that the patch went through thorough testing before being rolled out to the mainnet. Thanks for sharing the update! Read More