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!
callAfterTransfer in their token. This surprised many protocols, leading to security issues down the road.sweepToken was implemented. This is for rescuing funds that were accidentally sent to a contract managing a specific underlying token. This function can called by anyone but the tokens are sent to the admin so it shouldn't matter.sweepToken has a sanity check to ensure that the address of the token we are trying to recover does NOT equal the underlying token of the cToken contract. This is because being able to send out arbitrary tokens that back the cToken contract would destroy the protocol.sweepToken call, we can bypass this sanity check with the legacy version address. This means that the entirety of the balance of the underlying token can be sent to the Admin. Why is this bad? Finance calculations!(totalCash + totalBorrows - totalReserves) / totalSupplyThe variables above are:
totalCash:T otal amount of TUSD in the contract.totalBorrows: Amount of TUSD currently borrowed from the contract.totalReserves: Amount of TUSD that belongs to the protocol.totalSupply: Amount of TUSD that has been minted.totalCash to become 0 for TUSD in the contract. Since we are drastically changing the price of the token by doing this, an attacker can profit from it! The author gives a few ideas on how to do this:
sweepToken function. Additionally, TrueUSD removed the second entry point. According to the authors of the post, the better solution would have been a sanity check on the underlying balance of the contract before and after the transfer though. Overall, a very novel vulnerability that is something to look out in the future when interacting with a contract with multiple entry points.claimTokens() function of the AirdropGraphsToken contract to claim their free ApeCoin. In order to verify if you deserved a token from the airdrop, the contract would validate the balanceOf() a particular user. Down the road, when the tokens were distributed, it was marked in a list who owned which ID.balanceOf calls.flashLoan allows a user to borrow an arbitrary amount of vToken, which is backed by the NFTs.burn these vTokens to get a specified NFT. Additionally, the burning has a fee of 1.04 as well. xar files. A xar file contains three parts:
0x1 0000 0000 would resolve to 0x1 0000 0000 for 64 bit but 0x0 for 32 bit.hostname field has a command injection vulnerability. execve instead of system. They did a good job fixing this issue. curl library to make these requests, two crucial settings are turned off: CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER. AddSessionToCache, which is called when a client receives a new session ticket from the server. Whenever a new session ticket arrives, the client will reuse a previously stored cache entry. The ticket is 700 bytes, meaning it is given its own heap allocation with XMALLOC. cacheTicBuff again. But, as ticBuff is already initialized, cacheSession->ticketLenAlloc is 0. Practically, we have a confused state where a value doesn't get properly initialized. This improper initialization leads to a crash down the road because of an invalid free.balanceOf on the EulerStrategy.sol is used to determine the current value held by the EulerStrategy. This result is then used to calculate the price per share of the user's withdrawing position.balanceOf calls EUSDC.balanceOfUnderlying() underneath it. The problem with this is that the actual value being returned may be manipulated. Although the contract believes this will be an atomic call (no other paths ran), this is NOT the case.totalAssets is updated prior to the call but the totalBalances is NOT updated yet. This results in computeExchangeRate() being higher than the actual value. An attacker could use this to change the price and obtain more money than anticipated. computeExchangeRate. Since the price per share is higher, an attacker can redeem more USDC than they should be able to.path is parsed as well. However, this parsing is done slightly differently from a byte array.abi.encodePacked(WBTC, poolFee, WETH, DAI)
abi.encodePacked(WBTC, poolFee, fake, poolFee, WETH). path variable is a commonly used pattern for swaps. So, this is something to watch out for and something I've looked for in the past.