Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protocol does not check inside GuardianProver::approve() if all the guardians are approving the same proof #248

Closed
c4-bot-6 opened this issue Mar 27, 2024 · 12 comments
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-205 edited-by-warden satisfactory satisfies C4 submission criteria; eligible for awards sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity") sufficient quality report This report is of sufficient quality

Comments

@c4-bot-6
Copy link
Contributor

c4-bot-6 commented Mar 27, 2024

Lines of code

https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/provers/GuardianProver.sol#L33

Vulnerability details

Summary

The natspec for GuardianProver::approve() says the following on L33 but the "sent the same proof" clause is never really checked inside the function:

  File: contracts/L1/provers/GuardianProver.sol

  29:               /// @dev Called by guardians to approve a guardian proof
  30:               /// @param _meta The block's metadata.
  31:               /// @param _tran The valid transition.
  32:               /// @param _proof The tier proof.
  33:  @--->        /// @return approved_ If the minimum number of participants sent the same proof, and proving
  34:               /// transaction is fired away returns true, false otherwise.
  35:               function approve(
  36:                   TaikoData.BlockMetadata calldata _meta,
  37:                   TaikoData.Transition calldata _tran,
  38:                   TaikoData.TierProof calldata _proof
  39:               )
  40:                   external
  41:                   whenNotPaused
  42:                   nonReentrant
  43:                   returns (bool approved_)
  44:               {
  45:                   if (_proof.tier != LibTiers.TIER_GUARDIAN) revert INVALID_PROOF();
  46:                   bytes32 hash = keccak256(abi.encode(_meta, _tran));
  47:                   approved_ = approve(_meta.id, hash);
  48:           
  49:                   if (approved_) {
  50:                       deleteApproval(hash);
  51:  @--->                ITaikoL1(resolve("taiko", false)).proveBlock(_meta.id, abi.encode(_meta, _tran, _proof));
  52:                   }
  53:           
  54:                   emit GuardianApproval(msg.sender, _meta.id, _tran.blockHash, approved_);
  55:               }

Description & Impact

  • Assume there are a total of 9 guardians. Hence approvals needed for approved_ = true is (9 + 1) / 2 = 5.
  • Guardian1 to Guardian3 pass proofX while calling approve().
  • Guardian4 passes proofY.
  • Guardian5 passes proofX. Since the hash on L46 is calculated without involving the proof, L47 will return true at the 5th guardian's call even though Guardian4 had used proofY.
  • proveBlock() is called with _proof equalling proofX.
  • Note that whatever _proof Guradian5 uses while calling approve() will be used to call proveBlock() on L51, irrespective of whatever the previous guardians passed.

Thus the guardian proof is approved even when in reality the required votes have not been achieved.

Tools Used

Manual review

Recommended Mitigation Steps

Compare the _proof.data to make sure approval for the same proof is being provided by all the guardians.

Assessed type

Invalid Validation

@c4-bot-6 c4-bot-6 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Mar 27, 2024
c4-bot-9 added a commit that referenced this issue Mar 27, 2024
@c4-pre-sort
Copy link

minhquanym marked the issue as primary issue

@c4-pre-sort
Copy link

minhquanym marked the issue as sufficient quality report

@dantaik
Copy link

dantaik commented Apr 2, 2024

I think this is a valid report, although the severity is not high. Fixed in this PR: https://github.com/taikoxyz/taiko-mono/pull/16606/files

@c4-sponsor c4-sponsor added the sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity") label Apr 2, 2024
@c4-sponsor
Copy link

dantaik (sponsor) confirmed

@0xean
Copy link

0xean commented Apr 9, 2024

@dantaik - can you clarify why you don't believe this to be impactful? It does seem M is warranted as the function of the protocol is affected, no?

2 — Med: Assets not at direct risk, but the function of the protocol or its availability could be impacted, or leak value with a hypothetical attack path with stated assumptions, but external requirements.

@c4-judge
Copy link
Contributor

c4-judge commented Apr 9, 2024

0xean marked the issue as satisfactory

@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Apr 9, 2024
@0xean
Copy link

0xean commented Apr 9, 2024

@dantaik - see #205 for perhaps a better impact statement

@c4-judge
Copy link
Contributor

0xean marked the issue as selected for report

@c4-judge c4-judge added the selected for report This submission will be included/highlighted in the audit report label Apr 10, 2024
@0jovi0 0jovi0 mentioned this issue Apr 11, 2024
@mcgrathcoutinho
Copy link

Hi @0xean, I think this issue should be of QA-severity, here's why:

If there is no check present, the guardians sending another proof could be considered as incorrect input supplied by a trusted role. This falls under QA since trusted roles are providing incorrect parameters. Also to note, the guardians are selected by the DAO and Security council as Dan mentioned in his BCR video linked in the README.

Overall, I think the check is more of a sanity check than a major issue to the protocol's functionality.

Would like to hear your opinion on this in case I'm misjudging.

Thank you!

@0xean
Copy link

0xean commented Apr 11, 2024

Hi @0xean, I think this issue should be of QA-severity, here's why:

If there is no check present, the guardians sending another proof could be considered as incorrect input supplied by a trusted role. This falls under QA since trusted roles are providing incorrect parameters. Also to note, the guardians are selected by the DAO and Security council as Dan mentioned in his BCR video linked in the README.

Overall, I think the check is more of a sanity check than a major issue to the protocol's functionality.

Would like to hear your opinion on this in case I'm misjudging.

Thank you!

See #205 -

The issue arises from the fact that the approved message doesn't include the _proof. It means that the last approving guardian can provide any desired value in the _proof. The data from the _proof is used to determine whether it is necessary to return the liveness bond to the assigned prover or not:

To me the above represents a privilege escalation or if nothing malicious an issue that could affect the functioning of the protocol. Based on that I think M is correct.

@c4-judge
Copy link
Contributor

0xean marked issue #205 as primary and marked this issue as a duplicate of 205

@c4-judge c4-judge added duplicate-205 and removed primary issue Highest quality submission among a set of duplicates selected for report This submission will be included/highlighted in the audit report labels Apr 11, 2024
@c4-judge
Copy link
Contributor

0xean marked the issue as not selected for report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-205 edited-by-warden satisfactory satisfies C4 submission criteria; eligible for awards sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity") sufficient quality report This report is of sufficient quality
Projects
None yet
Development

No branches or pull requests

8 participants