Resources

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!

Popsicle Finance Post Mortem- After Fragola Hack- 899

Mudit Gupta    Reference →Posted 3 Years Ago
  • A big part of DeFi is rewarding those who put up their assets to be used. This is rewards distribution, yield... it has many words.
  • A user should be paid based upon their entry date rather than the first day money is put down. This rewards people staying around and keeping their funds in play.
  • Popsicle Finance doesn't transfer the debt when users transfer their shares to a different account. This allows for the claiming of share rewards for multiple shares over and over again.
  • Apparently, this bug has occurred several other times as well. The author points out WildCredit as an example of this as well.
  • Overall, interesting bug! Will confirm that all variables are updated when moving assets from account to account.

Explained: The Crema Finance Hack- 898

Rob Behnke    Reference →Posted 3 Years Ago
  • Crema is an Automated Market Maker (AMM) that allows users to concentrate their funds into a specific zones for trading. This allows users to use of their resources, instead of a small fraction of them. With this model, liquidity providers can specify price ranges for when their liquidity should be traded.
  • The issue was susceptibility to flash loan attacks. First, the attacker created a tick account. This is an account dedicated to storing the price data of the AMM.
  • Next, they took out a large flash loan to add the liquidity to Crema. The calculation of the fees relies on the data from the tick account. Since the tick could be controlled by the attacker, this was sending out malicious data. Particularly, it sent that the fee for a transaction was gigantic, stealing a large amount of capital in the process.
  • Since the attacker took out the flash loan, the impact was quite dramatic. They owned a large amount of the transaction fees (with their large capital) and the tick account with the large transaction fee being provided. This resulted in a large amount of money from the protocol being stolen.
  • My question is how does somebody get to set the price of the transaction fee? That seems really strange that an account can be created and simply do that. The protocol has some verification steps, but this was trivial bypassed.

Explained: The Poly Network Hack- 897

Tommaso Gagliardoni    Reference →Posted 3 Years Ago
  • Poly is a cross chain protocol. It is essentially a bridge between two contracts.
  • In order to do this, a special contract gets called from an EOA to update the state from blockchain to blockchain. In the case of Ethereum, there are two very privileged contracts: EthCrossChainData and EthCrossChainManager. EthCrossChainData can only be invoked by contract owners. It is used to manage the keys for nodes and many other sensitive operations.
  • EthCrossChainManager can trigger messages from another chain to the Polychain. To do this, the function verifyHeaderAndExecuteTx within this contract is called with a poly contract to execute. This is intended to ONLY call functions with a specific solidity function ID though.
  • The calculation of the function is done with bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))). A user controls the parameter _method. Since functions are literally just the code above, if an attacker could specify a DIFFERENT method ID, they could call arbitrary functions in the contract. This requires brute forcing the hash because of the function signature though.
  • Remember how the EthCrossChainData contract can only be updated by owners? Well, we can proxy the request with the previous bug, since EthCrossChainManager is an owner of it! By proxying a call to this with the previous bug, we can call sensitive functions! In particular, putCurEpochConPubKeyBytes adds a public key to the contract for verification.
  • By adding a public key, we can sign our own transactions now! This is how the attacker stole all of the money; a crazy 610 million in USD. Damn.
  • Function calls used to proxy requests should be carefully audited in applications. This one bug lost a fortune for the platform.

Revest Finance Vulnerabilities: More than Re-entrancy- 896

BlockSec    Reference →Posted 3 Years Ago
  • The Financial Non-Fungible Token (FNFT) of Revest has vaults that allow the transferring of access to these vaults. This works by a user sending some asset, such as wETH to the contract. Then, using the funds from that asset, FNFTs are generated with an identifier. A user can divide up the FNFTs as they like. Once the vault is unlocked, then the FNFTs can be burned to receive funds from the underlying asset, such as wETH.
  • The entry contract has three interfaces to mint FNFTs by locking previous assets. mintTimeLock locks the asset for a set period of time, mintValueLock will unlock only when the asset goes above or below a certain value and mintAddressLock will unlock assets when a specific account opens it. All of these paths call the same set of additional contracts for unlocking and locking contracts.
  • An additional piece of functionality called depositAdditionalToFNFT is used to lock more underlying assets to an existing lock. When this happens, it assumes that the amount can be evenly distributing among the existing NFT owner. If it is not, then a new lock is placed on the ID and burns some quantity of the old FNFT tokens and mints the new quantity. This is done by adding up the old quantity with the new quantity to get a total quantity.
  • So, what's the vulnerability then? Well, there is two. The simpler bug (and one discovered by the authors of the post) is a logic issue. When handling multiple deposits on the same call, the depositAmount for a given FNFT is put BOTH into the old lock and the new lock! This means we can use our funds twice, which is a recipe for disaster. Instead, it should destroy the original lock and put the funds into the new one only.
  • The original vulnerability comes from a re-entrancy attack. When creating or updating the FNFT, the id gets updated. By creating an FNFT, the id should be increased. However, prior to incrementing the counter the variable fnftId, ERC-1155 standard's callback mechanism can be triggered.
  • Since the id has not been incremented in the state yet, shenanigans can be pulled. Remember how the update will either add the funds to a new FNFT (and increment the ID) or use the current one? By reentering the contract with the fnftId in the wrong state, we can create a update the previous FNFT (increment by 1) to update the depositAmount of a token. Why is this bad?
  • This state update is catastrophic because it will update the funds in the contract but not the amount of tokens minted. As a result, an attacker can create a large amount of tokens with zero value (token 2) and update the value of token 1 to really update the value of token 2! By doing this, the cost of token 2 is not zero but there are a ton of tokens we can withdraw for a high value.
  • That last re-entrancy vulnerability is insanely complex and I cannot believe somebody truly figured that out. The diagrams in the blog post are amazing for explaining this, as there are many steps to make this work.

Bunker.finance Vulnerability Postmortem — BNft Amount Manipulation- 895

bunker.finance    Reference →Posted 3 Years Ago
  • Bunker Finance is a borrow and lend platform specifically for getting money for NFTs as collateral. Essentially, you can fund loans by using NFTs.
  • When depositing NFTs as collateral on Bunker, the users receive a bNFT or cNFT. This is a wrapper around the underlying NFT type (ERC-1155, ERC-721 or CryptoPunk). This demonstrates ownership over a specific NFT.
  • When minting a cNFT for ERC-721 or Cryptopunks, the parameter amounts is NOT checked. This means multiple ownership tokens can be minted, while the NFT itself is still in the contract. Instead of a 1 to 1 relationship there is a 1 to many relationship, which is real bad for unique objects.
  • Now, an attacker can use ONE cNFT to redeem there original NFT while still having leftover cNFT. Practically, since this is a unique token, if an attacker sold the NFT on this platform, they would simply be able to redeem it using the extra cNFT token! This steals the token from the other user.
  • Overall, neat bug with a new proof of concept included in the blog that uses hardhat and a forked network.

Polygon Consensus Bypass Bugfix Review- 894

Immunefi    Reference →Posted 3 Years Ago
  • A consensus method is how a group of entities come to a single source of truth. Bitcoin and Ethereum uses proof of work in order to do this. Newer blockchains are using proof of stake. This means that money is put into the pot to demonstrate that the environment means something to them. These stakers or validators are important to the ecosystem for ensuring everything is done properly.
  • In Polygon, a layer 2 blockchain solution, there is a list of Validators for proving that a transaction was done correctly. In order to become a validator, you must stake or give up your token to the blockchain. There is a limit of 100 validators for this ecosystem at a time though.
  • There is a struct in Solidity for keeping track of this information with two fields: validatorState.amount and validatorState.stakerCount. The amount is the amount of tokens staked, which is the staking power. The stakerCount is the total number of stakers in the contract, which is likely to be 100.
  • When a validator unstakes, the counter of the validatorState.amount updates by subtracting the amount of the user who provided the value. This allows users to stake and unstake as they would like, collecting rewards when they unstake.
  • There is an additional piece of functionality that is important for this vuln: delegation migration. A user can migrate their delegated token amounts from one validator to another. Importantly, this can be done without losing the amount of tokens by the original user; meaning, they can unstake the delegated tokens themselves.
  • The vulnerability arises from a double subtraction error. When migrating from one account to another, the validatorState.amount is updated to subtract the amount of token delegated. Additionally, when the original user wants to retrieve their unstaked token, they still can! This means we can subtract from validatorState.amount multiple times.
  • By doing this double subtraction, over time, we can shrink the validatorState.amount variable to be very small. At this point, we could override updates with the 2/3 rule to control the network.
  • The bug finder only got 75K for this bug instead of the several million they probably deserve. This was explained away by the complexity of time consuming nature of the bug, with very specific network circumstances. However, a bug at the core of the consensus network could have led to a complete take over of the network! Regardless, a fascinating bug.

Balancer DoS Bugfix Review- 893

Immunefi    Reference →Posted 3 Years Ago
  • Balancer is a specialized AMM that allows trading pools of more than 2 coins. Most of the time, these pools are 2 coins, where the price is self balancing and really simple: Balance of token A * Balance of token B = Constant product called the "constant product" equation. The adaption is to generalize this formula to work for more than 2 tokens they called weighted math.
  • The algorithm above allows for an algorithm to facilitate trades by calculating its own price. If there is less of one token, then this one goes up in price. AMMs are a fascinating concept! Balancer also has a flash loan functionality built into each pool. This is a borrow that can be performed without providing any assets in return; this has the major caveats of ONLY working if it is returned in a single transaction.
  • To perform a flash loan, a function call is performed with a list of tokens and their values to retrieve. In order to ensure that money is repaid at the end of the block, the original cost of each token is kept track of. This is checked at the end of the call to ensure that they are the same and the fee is also taken for the service.
  • An additional piece of information to understand this is proxies. Proxies allow the contract to be editable by having one base contract have the storage then send future calls to another contract, which is the current version. At this point, contract has two entrypoints: the proxy and the implementation. Several ERC20 tokens allow for this, such as sBTC and SNX.
  • The vulnerability is within the handling of double entrypoint tokens. Both the proxy and token address can be specified in the call. The first coin will appear to have all of the money, while the initial will have none of the money. When this is inserted back into the contract, (as required), the excess money will all go to the fees contract. This sends a MAJOR excess of money from the contract to the fees collector, causing a DoS on the pool.
  • This is an interesting bug for a very weird edge case of ERC20 tokens. This required a deep understanding of token implementations and the Balancer contract as a whole. This was only a partial denial of service, but was still interesting none-the-less.

The Main Cause of Vee Finance Attack- 892

Vee Finance     Reference →Posted 3 Years Ago
  • Vee Finance is a lending protocol that is mainly forked from Compound Protocol but adds a little bit more functionality.
  • Slippage is the cost between attempted buying price and the real buying price. Veefi attempts to validate the slippage but failed at this. When doing the trading, it uses the Pangolin Price Oracle. If the number of TokenB tokens that can be exchanged in the pool is greater than or equal to the expected number of TokenB that can be exchanged using the oracle, then it can be judged that the pool price is correct and not controlled.
  • The slippage check had a validation flaw in the handling of ERC20 tokens. When doing the comparisons for slippage, it did NOT take into consideration the decimals of a token. Because of this, the actual value and the slippage check are WAYYY different, allowing for oracle manipulation.
  • This directly caused the contract to obtain the wrong price from the oracle during the slippage check, which caused the slippage check to be bypassed. This allowed for transactions that should have been rejected to be accepted from oracle manipulation attacks, losing 34 million from the protocol.
  • Price Oracle manipulation is an extremely complicated attack that is becoming more and more relevant. To stop this attack, the authors removed functionality from specific classes of tokens.

Is exploiting a null pointer deref for LPE just a pipe dream? - 891

Michael DePlante - ZDI    Reference →Posted 3 Years Ago
  • The post targets BitDefender, an AntiVirus.
  • IO Ninja is used for sniffing, protocol analyzing and much more. Additionally, the author claims that it can be used to reverse engineer Inter-Process Communications (IPC) as well. They use this to open a pipe server to interact with the AntiVirus.
  • The IPC communication is simply outputted into a wireshark-looking packet. It is super neat to see on this works and looks really easy to use. While trying to reverse engineer the protocol, the AV crashed. Why is this?
  • By sending the header of the packet, just 16 bytes, over IPC, the process would crash. This is the case with almost all of the BitDefender processes. This creates a local denial of service, which is pretty interesting. From triaging, this appeared to be a null pointer dereference.
  • The AV was writing the crash information to a file. However, the permissions of the file were read/writable by all users. This is very bad because we can use a symbolic link here to overwrite the data of anything. Since the process ran as SYSTEM this really means ANYTHING.
  • To escalate privileges, we abuse the symbolic link permission writing! In particular, the DACL read/writable permissions could be placed onto a DLL (via a symbolic link) to put new permissions on the DLL. Once the permissions are there, we can modify the DLL ourselves to be loaded by a SYSTEM process to escalate privileges. Neat!
  • Another vulnerability from the AV was deleting arbitrary files on the system. If you let the prompt for deletion timeout, it would simply perform the deletion anyway.
  • Overall, a pretty good post! The reversing and testing was quite dynamic in nature, with very few static reversing done. There are many ways and places to find vulnerabilities.

Synthetix Logic Error Bugfix Review- 890

Immunefi     Reference →Posted 3 Years Ago
  • Synthetix is a liquidity pool protocol that allows trading in the DeFi space. Since this has an Automated Market Maker (AMM), there are plenty of algorithms to ensure everyone gets the money they deserve. What if one of these was down incorrectly?
  • Frontrunning is when an attacker views the upcoming transactions and sneaks in a transaction with a higher gas price to take advantage of this. For instance, if we had a game called guess the number but you didn't know what the number was. You could view the pool until you see an answer that you like. Once you see this answer, you could steal this answer and add a higher gas price to your transaction to steal the solution.
  • In a similar fashion to frontrunning, the exchange had a problem with the latency between the off-chain market for a coin and the pools price. This allows for slight gains of funds from outsiders, but can cost the people staking into the pool money. In order to combat this latency, the exchange implement a short waiting period for taking out coins.
  • On top of the waiting period, it checks to see if arbitrage has been performed. This is calculated between the exchange prices and those at the end of the waiting period. If the result is negative, then they are owed money for the latency - this is also called rebate. If the result is positive, then they owe the pool money. Once the context is understood, then the reasoning for this makes sense.
  • The algorithm for this is Amount * (1 - feeRate) * (srcRate/destRate - newSrcRate/newDestRate). When the user withdraws their money, there is a bug in the actual code to take this out. Instead of using the variable sourceAmountAfterSettlement, sourceAmount is being used.
  • This results in not enough tokens being burned. Additionally, the amountReceived is calculated from the full sourceAmount instead of the sourceAmountAfterSettlement. In other words, the sourceAmount is slightly inflated. This earned the author a 150K bounty.
  • This was a very subtle logic bug in the handling of money. This properly took hours upon hours of reading documentation and understanding the code base to find. This company has had several reviews of their code base in the past by Sigma Prime and iosiro.