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!

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.

Explained: The XCarnival Hack- 889

Rob Behnke    Reference →Posted 3 Years Ago
  • XCarnival is an NFT lending platform in which a user can deposit an NFT as collateral against loans. By depositing NFTs are collateral, tokens and other assets can be purchased.
  • When a user deposits an NFT into the platform, they are assigned an orderID. This should have been valid as long as the collateral (NFT) was still in the system.
  • However, there was a mistake in this logic. The orderID was still valid, even if the collateral had been taken out of the contract. This allows for the using of the receipt to take out loans, while the contract not longer possessed the collateral necessary to force the payback of the loan.
  • To launch the attack, they created several contracts and put NFT as collateral. The reason they used multiple contracts was that there was a limit on the size of loans that could be taken out. As a result, they did this attack multiple times to steal 3.8 million ETH.
  • Apparently, they had passed an audit from Certik. Interesting how this either got missed by the audit or the functionality was changed after. From my perspective, this feels like something I would check quickly. Overall, good bug!

Exploiting Spartan Protocol’s LP-Share Calculation Flaws- 888

Amber Group    Reference →Posted 3 Years Ago
  • Spartan is a DeFi protcol for assets running on BSC/BNB. This is mostly the same as the UniswapV2 protocol with some small differences. This is an AMM.
  • When putting funds into a pool, a user is able to remove (liquidate) these funds. When a user removes these funds, the amount of the funds they are entitled to must be calculated. When taking funds out of the pool, the user must send back LP tokens, which are essentially receipts for putting funds into the pool.
  • The simple way to do this is returning LP tokens/total LP tokens. This allows them to obtain a total for the underlying assets proportional to what they put in. At this point, the tokens will be burned (destroyed). This math is where the vulnerability occurs at because of bad state handling.
  • The vulnerability occurs when syncing costs between the reserves and the pools contributions. Since these values are not being updated properly, they were able to exploit the slippage between the two prices. This desync between the amount of total funds and the assets put into the pool makes it possible to take out more funds than expected.
  • To perform this attack, the following steps have to be done:
    1. Add liquidity to the pool and get LP tokens back.
    2. Transfer assets into the pool. This amplifies the amount of assets in the LP token, which allows the attack be possible.
    3. Remove the liquidity. Since there are more assets (from step 2), we get more liquid returned than what we put in.
    4. Put the assets into the contract as liquidity then remove it.
    5. Perform this operation multiple times.
  • This took me a while to understand. The important nuance here is that asset and liquid are slightly different concepts. Adding assets to the pool would amplify the price of the liquidity in an unfair way. Eventually, when the liquidity was removed, we get some assets back than we put in. Neat!

Astroport Audit by Halborn & Oak- 887

Halborn    Reference →Posted 3 Years Ago
  • Astroport is a decentralized trading platform. Prior to being released fully, it went under two security audits on multiple features. A few of these bugs are interesting and worth calling out!
  • In the AMM (Automated Market Maker), there is a function to set configuration parameters, such as other deployed contracts to use. However, these functions are not backed by access control! This means that anybody cab trivially change these parameters and potentially steal funds. This same issue was found by both Oak and Halborn.
  • When creating a pool, there is no check that the same assets are being used to create this. As a result, we have a classic double spending problem. A user could take out more money from the pool than there fair share. This can be triggered again because of a case sensitive check for an address.
  • In the Oak audit, there are a few more severe issues. The first issue is a rounding problem when taking out assets with division. When taking out funds in the pool compared to one another, the division gets rounded up instead of rounded down. This resulted in money being easy to siphon from the contract.
  • The second major vulnerability is a gas exhaustion attack. There is an iteration through a map with an attacker controlled size. By putting in many small amounts into this, it would make the funds forever locked.
  • A lot of the other findings are simply "X doesn't work and user could lose funds". It is shocking how some things do not work as expected with this much money on the line. Overall, fairly good audits with good bugs!

Port Finance Logic Error Bugfix Review- 886

Immunefi    Reference →Posted 3 Years Ago
  • Lending in the real world is a complicated subject. If you are attempting to start up a business, then you need capital backing or to take out a loan yourself. When you take out a loan, you must provide some collateral to guarantee you will pay it back. While something is up for collateral, it cannot be used for anything else.
  • The value of the asset you want to borrow is called the Loan To Value (LTV). For instance, if you borrow $60 worth of some cryptocurrency and you provide $100 as collateral, your LTV is $60/$100 = 0.6.
  • Liquidation is a way to protect lenders from a negative price fluctuation. If the value of your collateral is insufficient, the liquidators may purchase your collateral at a discount. Lending protocols usually set target LTVs for their lending pools, and as a borrower, your main risks involve losing your collateral through mismanagement of your position’s LTV.
  • Port Finance is a non-custodial money market protocol on Solana. The purpose of this app was to create a large listing of interest rate and lending protects for Solana. Port Finance has a number of lending pools, which are called Reserves in their context.
  • Todo...

Sense Finance Access Control Issue Bugfix Review- 885

Immunifi    Reference →Posted 3 Years Ago
  • Sense is a framework that allows the building of new yield primitives. This would include bonds, yield tokens and tranch-like (pools of assets) instruments.
  • The first app (made by Sense) was a yield stripping app called Sense Space. This means that users can lend at a fixed rate and make gains on this. Additionally, they make short/long bets on the future yields of existing yield-bearing assets.
  • Sense Space is an Automated Market Maker (AMM). This is built upon the Balancer contract, which implements yieldspace invariants and a market for principal and yield token trading. Balancer is automated portfolio, liquidity provider and price sensor.
  • When the Balancer vault handles a swap between tokens, it does this by making a callback to the onSwap() function of the Space AMM pool.
  • The AMM pool function onSwap() would update the prices of the token depending on the actions performed on the actual swap. In particular, updating the amount of tokens available.
  • The issue is that the onSwap() method does NOT validate who makes this call. As a result, an attacker could provide arbitrary values to this to control the oracle. By controlling the oracle, the price of tokens could be set, giving an attacker an easy time stealing money.
  • The simple fix for this was to ensure that the sender of the call was the vault contract. Overall, a simple vulnerability that came from the complexity of integrating multiple pieces together.

The Inverse Finance Hack- 884

Rob Behnke    Reference →Posted 3 Years Ago
  • Price oracles are being in used to calculate how much a token costs. This is similar to exchanging currencies at the airport for USD to Euros. How is this cost set?
  • In the land of crypto, this is commonly done based upon algorithms from the amount of assets in circulation. If there are more coins in circulation, then they cost less. If there was less coins, then they cost more.
  • If the users of the token are not careful, then the cost of the token can be manipulated. For instance, an attacker could buy a ton of tokens to make the token cheap. Then, buy something using this new cheaper price. Finally, return all of the tokens to make the price stable again. This is known as oracle manipulation.
  • In the case of Inverse Finance, it was a bit more complicated. The attacker took out a flash loan then put collateral in a pool. By performing a swap with the flash loan, the price of their collateral rose drastically!
  • Because of the rise in price, they were able to take out a large loan from the pool. After performing some conversions, they were able to pay off the flash loan as well. This resulted in 150 million being stolen from the contract.
  • This token manipulation required a deep understanding of how the system worked in order to exploit. If there is any calculation going on then it must be carefully vetted.

Wormhole Uninitialized Proxy Bugfix Review- 883

Immunifi    Reference →Posted 3 Years Ago
  • Wormhole is a communication bridge between Solana and other blockchains. As such a big service, it needs to be updated. The issue, is that blockchains are immutable. So, how is this done? In some complicated and convoluted ways that have some weird negatives.
  • The goal is to change the code in use at a specific address but keep the state of the contract. To make this possible, there is one address that acts as the proxy and the other that acts as the contract code itself. The proxy holds the state of the contract. This is done via making a call to delegateCall() from the proxy to the contract. A final point is that the initialization function has to be a regular function instead of a constructor.
  • There are two common patterns for this: TPP and UUP. Transparent Proxy Pattern (TPP) ensures that all calls by a user execute the implementation logic and all calls by the admin implement the proxy contracts logic. TPP has to store information about the admin on the proxy side, making it much so efficient.
  • To combat this problem, the prevailing pattern is Universal Upgradeable Proxy Standard (UUPS). The main difference is that the upgrade logic is in the implementation contract instead of the proxy contract. This makes the cost of updating cheaper and we no longer have name collisions. For more on these patterns, read Transparent vs UUPS Proxies.
  • OpenZeppelin's (smart contract templates that are widely used) UUPS implementation had an access control problem. The init function set the caller to be the owner of the contract; this is another constructor related problem! With this, the attacker could upgrade the contract to their own malicious values, then set the new location to be their own contract. Finally, calling selfdestruct would drain the funds and make the proxy useless.
  • In the case of Wormhole, they had the same exact problem. An initialization function was never called and left open to the world. Using SELFDESTRUCT would have bricked the contract and stolen all of the money. To fix this, they simply had to call initialize themselves.
  • Overall, the proxy pattern is interesting but adds a lot of complexity. Good find for 10 million dollars.

Polygon Double-Spend Bugfix Review- 882

Immunefi    Reference →Posted 3 Years Ago
  • Polygon is a blockchain platform. They have implemented a bridge called the Plasma Bridge. A user can go from one blockchain to another with their funds using this bridge.
  • Transferring funds between blockchains is complicated. Tokens must be locked in one place then appear in another. In order to do this securely, the authors have created an implementation of a Merkle Proof. In particular, the burn transaction (exit) receipt is verified this way.
  • Within a Merkle proof, the branchMask is used to keep the system secure and must be unique. This is important, since this was the ID that was being confirmed for a exit being executed or not.
  • The branch mask is decoded by the MerklePatriciaProof.verify and once again at WithdrawManager.verifyInclusion. The decoding of the second function ignores several values while decoding it. Since the branch mask id can have many different variations from this bad decoding and this is used for an ID we have a problem.
  • The uniqueness of this ID is not 100% true then. The replay attack can be a completely valid receipt but with a separate branch mask. In particular, this lead to 224 ways to execute the same ID. This allows the stealing of money from the contract when going between chains.
  • The branch mask should always be 0x0 for the mask. Since this was not check, the particular attack mentioned above was possible. Overall, a fascinating bug from the improper validation of cryptography.