Platform: Code4rena
Start Date: 01/08/2022
Pot Size: $50,000 USDC
Total HM: 26
Participants: 133
Period: 5 days
Judge: Jack the Pug
Total Solo HM: 6
Id: 151
League: ETH
Rank: 32/133
Findings: 2
Award: $246.32
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: berndartmueller
Also found by: 0xA5DF, arcoun, rotcivegaf, wastewa
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Community.sol#L887 https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Project.sol#L513-L532
The address returned by SignatureDecoder.recoverKey()
is never compared with the zero address (address(0)
) before comparing it with the expected address. If the expected address is also the zero address (address(0)
), the signature verification will pass although the signature is invalid.
There is at least two cases where this can be used to achieve an unauthorized operation:
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Community.sol#L169-L203
In Community.addMember()
, this can be used to add a member to an uninitialized community as there is no verification that the community is not created and _community.owner
will be equal to address(0)
. When the target community will later be created, the address will still be in the _community.isMember
dictionary and be able to publish a project.
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Project.sol#L493-L536
In Project.raiseDispute()
, this can be used to raise a dispute while there is no contractor assigned (contractor == address(0)
) on a project.
Regarding Community.addMember()
:
addMember
with:
data.communityID
: ID to a community which is not yet created (communityID > communityCount
)data.newMemberAddr
: address to add to the communitysignature
: 2 signatures, the first one can be junk data, the second one is a signature of the message by data.newMemberAddr
checkSignatureValidity()
at line 187 will pass because _community.owner == address(0)
so any invalid signature will be acceptedcheckSignatureValidity()
at line 188 will pass because the second signature is valid_community.isMember[_newMemberAddr] = true
will add the address to the isMember
dictionary_community.isMember[_newMemberAddr]
will not be removed and the address will have the ability to bypass the require(_community.isMember[_builder], "Community::!Member")
at line 248 and publish a new project.Regarding Project.raiseDispute()
:
raiseDispute
on a project where contractor
is currently unasigneddata.project
to the project address and data.task = 0
, signature
can be junk datarecoverKey()
, signer
will be equal to address(0)
as the signature is invalidcontractor
is also equal to address(0)
IDisputes(disputes).raiseDispute()
will be called to add the dispute. The signature will also be checked there to fill _dispute.raisedBy
but still not checked against address(0)
The recommended fix is to check the return address of SignatureDecoder.recoverKey()
:
SignatureDecoder.recoverKeyorThrow()
function can be added and used most of the time. This function raises an error if the return address is address(0)
.Community.checkSignatureValidity()
and Project.checkSignatureValidity()
, raise an error if _address
is address(0)
.#0 - 0xA5DF
2022-08-11T13:59:54Z
Part of this bug (Project.raiseDispute()
) is duplicate of #327
#1 - parv3213
2022-08-18T09:38:15Z
Duplicate of #298 and https://github.com/code-423n4/2022-08-rigor-findings/issues/327
🌟 Selected for report: Lambda
Also found by: 0x1f8b, 0x52, 0xA5DF, 0xNazgul, 0xNineDec, 0xSmartContract, 0xSolus, 0xf15ers, 0xkatana, 0xsolstars, 8olidity, Aymen0909, Bahurum, Bnke0x0, CertoraInc, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, Extropy, Funen, GalloDaSballo, Guardian, IllIllI, JC, Jujic, MEP, Noah3o6, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, SooYa, Soosh, Throne6g, TomJ, Tomio, TrungOre, Waze, Yiko, _Adam, __141345__, a12jmx, ajtra, ak1, arcoun, asutorufos, ayeslick, benbaessler, berndartmueller, bin2chen, bobirichman, brgltd, bulej93, byndooa, c3phas, codexploder, cryptonue, cryptphi, defsec, delfin454000, dipp, djxploit, erictee, exd0tpy, fatherOfBlocks, gogo, hake, hansfriese, horsefacts, hyh, ignacio, indijanc, joestakey, kaden, mics, minhquanym, neumo, obront, oyc_109, p_crypt0, pfapostol, poirots, rbserver, robee, rokinot, rotcivegaf, sach1r0, saian, samruna, saneryee, scaraven, sikorico, simon135, sseefried, supernova
40.621 USDC - $40.62
signatureSplit
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/libraries/SignatureDecoder.sol#L58
The NatSpec documentation of signatureSplit
indicates that the pos
parameter should be checked to avoid out of bounds access but this is not done by any direct or indirect caller.
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/libraries/SignatureDecoder.sol#L25
Recommended mitigation is to update the test at line 25 and add || messageSignatures.length / 65 <= pos
.