Skip to content

Bogus signatures in LightClientAttackEvidence #1749

Closed
@insumity

Description

Bug Report (low severity)

At a high level, a malicious validator with more than 1/3 of the voting power could generate LightClientAttackEvidence that contains correct signatures but also contains bogus (e.g., unverifiable) signatures. Such LightClientAttackEvidence can be added to the evidence pool without an issue if the correct signatures stem from validators that have more than 1/3 of the voting power. As a result when we go through the signatures to slash validators we could go through bogus signatures as well and potentially slash innocent validators.

Specifically, the issue has to do in the way that LightClientAttackEvidence is verified before being added to the evidence pool. VerifyLightClientAttack in case of a lunatic attack calls VerifyCommitLightTrusting with e.ConflictingBlock.Commit. Subsequently, VerifyCommitLightTrusting calls verifyCommitBatch or verifyCommitSingle with the countAllSignatures argument set to false. This means that both verifyCommitBatch and verifyCommitSingle do not go through all the signatures contained in e.ConflictingBlock.Commit.Signatures if the signatures that have been verified so far exceed 1/3 (i.e., the default trust level) of the voting power we stop checking when the following condition evaluates to true:

if !countAllSignatures && talliedVotingPower > votingPowerNeeded {

As a result, a malicious validator (or set of validators) that has more than 1/3 of the voting power could generate LightClientAttackEvidence that has all the verifiable signatures at the beginning of the conflictingBlock.Commit.Signatures slice and afterwards it has bogus signatures that are not verifiable.
Nevertheless, in such a scenario, the LightClientAttackEvidence with the bogus signatures would still be added in the evidence pool.

When we slash based on this LightClientAttackEvidence we extract the byzantine validators that would go through all the signatures:

for _, commitSig := range l.ConflictingBlock.Commit.Signatures {
    ...
    _, val := commonVals.GetByAddress(commitSig.ValidatorAddress)

And hence we could slash validators that have their ValidatorAddress in some of the signatures but those validators have not performed a light client attack. This way, a malicious validator would get slashed, but can also succeed in slashing innocent validators.

CometBFT version: Note that the above provided links stem from CometBFT v0.38.2 but I would assume the issue exists since the introduction of LightClientAttackEvidence.

Thanks to @jmalicevic and @sergio-mena for looking into this.

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions