People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!
write_to_contract() to write error messages to the WASM address space.write_to_contract() calls allocate. This function allocates a large block of memory in the address space. Normally, this is a standard library from CosmWasm but can be overwritten by a developer. addr_validate() within our custom allocate() function, an infinite recursion call can be created.getenforce were removed as well.init_module was restricted but finit_module was not! They are the same exact call except one takes in a file and the other takes in a file descriptor. finit_module allows the author to get into the kernel and disable SELinux. They had to write a custom loader for this though, which is interesting. Overall, an interesting bypass for SELinux.try with 3 options for the catch. First, catch Error(...) catches a revert from the external contract with a particular reason string. Second, Panic catches a serious error like division by zero, an integer underflow or assert. catch (bytes memory) that will catch all other unhandled errors. So, what if we could cause a denial of service by triggering one of these outcomes? Or, if we could bypass the checks implemented in a specific catch but not another? Let's hack things!uint256, it will use the address or any other data that is provided. catch case. mint to create an asset or burn to remove it from existence. Then, using a proof, the other chain would know whether we owned an asset on it or not.increment should occur before the call to _safeMint. This worked as follows:
function mint(address to) public returns (uint256) {
uint256 newWarriorId = tokenIds.current();
_safeMint(to, newWarriorId);
tokenIds.increment();
return newWarriorId;
}
_safeMint() function has an external function call for onERC721Received inside of it. Since the CEI pattern is not followed and the contract is not using the standard library for preventing reentrancy, there is a major problem. _mint function again, it will fail because the token id wasn't incremented and already exists. However, there are other functions within the contract that could be interesting to us.crossChainTransfer() is used to send the assets from one chain to another. Calling this with a particular token ID will send the token from one chain to another.mint() with the attacker contract as the recipient. NOTE: The ID hasn't been incremented.crossChainTransfer to transfer the new id to chain B.mint() again from the recipient contract to mint the same NFT once again.claimAsset(), but it always goes to the proper user.claimAsset() was built to be gasless (free). This is because a new user will not have any assets on the L2, since they are currently transferring them over. Because of this, a malicious actor could send lots of invalid free claim tx's to cause a DoS. Well, not exactly.
isFreeTx := poolTx.GasPrice().Cmp(big.NewInt(0)) <= 0
// if the tx is free and it was reverted in the pre execution, reject the transaction
if isFreeTx && preExecutionResponse.isReverted {
return fmt.Errorf("free claim reverted")
} else { // otherwise
...name. Why did this occur?name field. In particular, it had split into 125 different networks! This was at the fault of CosmWasm and led to them not reaching consensus. This vulnerability is known as indeterminatism; this is when the operations being performed do not have a deterministic path, leading to rapid forking.AuthZ module. It was found by multiple parties at once independently from the Cosmos team. The Cosmos SDK uses ValidateBasic() to validate that a message is valid. However, the module was missing this check, leading to invalid state transitions being possible. This would have allowed an attacker to manipulate a market in strange ways.