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!

XSS and cache poisoning via upload.twitter.com on ton.twitter.com- 1133

filedescriptor - HackerOne    Reference →Posted 2 Years Ago
  • This bug report is a doozy! It combines various vulnerability classes to create a horrifying exploit in Twitter.
  • Twitter allows users to upload files. If a known file type is sent, then the response for the file will contain the proper Content-Type. If it's a malicious file extension, such as HTML, it's rejected though. So, what happens if the file type is not known? No Content-Type is sent!
  • The web browser does not trust file extensions; it only likes the Content-Type. If this header is not included, it attempts to deduce the type of the file based upon the content! This is called MIME Sniffing. By sending a file with a random file type, the browser will sniff the type of it based upon the content. This allows for malicious content, such as HTML, to be included in the file that will be executed!
  • Sadly, this was a self-attack though; we need another bug to make this hit other users. The author found out that an HTML5 AppCache manifest file can be uploaded to website. This allows a malicious user to control the caching behaviors over ton.twitter.com in the browser. What can an attacker do with this?
  • The appcache manifest file has crazy capabilities. For instance, it can change the HTML on the page! Worse yet, it will stick in your browser, giving a user permanent XSS. Overall, a combination of MIME sniffing and clever usage of the appcache manifest file lead to permanent XSS. Pretty rad!

Hacking Brightway scooters: A case study- 1132

Von - robocoffee    Reference →Posted 2 Years Ago
  • Electric scooter hacking!? Sign me up! In this article, the author takes a look into the Brightway Scooters made for NAVEE and Xiaomi. The scooter has a Controller in the bottom that communicates with a motor and a battery. In the top of the scooter is a dashboard that communicates with the Controller uses UART. The Dashboard communicates with cell phones using BLE.
  • To pair a scooter, the app must be downloaded and a QR code is scanned. To activate the scooter, a home video must be watched. The 'Mi Home' API is integrated with the vendors app. By looking into this internal application, we find the locations of important registers (such as put the scooter into drive mode) and more.
  • The format for an packet for the scooter is as follows:
    • TYPE: The command type. Write, read, MCU (controller) read/write and a few others.
    • ADDRESS: The register address mentioned above.
    • REST: The package being used.
    • LEN: The length of the payload.
    • PAYLOAD: The hex values to transmit.
  • They decided to take apart the scooter and map out all of the hardware. While doing this, they noticed that Single Wire Debug (SWD) pins were left on! All they had to do to access JTAG was connect via OpenOCD. With this, they have complete access to the system memory, control flow and anything else they want.
  • Another oversight they noticed was that the firmware updates (OTA) for BLE are unencrypted. This allowed for reverse engineering of the system as a whole.
  • Recently, Xiaomi introduced firmware signing to secure the BLE firmware from tampering. However, the MCU firmware is still not signed. This allows for some tampering of the device still. They tried uploading their own firmware to various components for fun using this issue.
  • The device has BLE encryption and a secure chip. However, using these does not mean security by default. Protections still need to be put in place for other things. Overall, fun post on reverse engineering!

Carbon - Source Code Imager- 1131

Carbon    Reference →Posted 2 Years Ago
  • Carbon is a source imaging tool that supports a variety of languages. Just wanted to document it here to use in the future. bytes032 uses this all the time and things look great using it.

ERC4626 Inflation Attack Protection- 1130

bytes032 and others    Reference →Posted 2 Years Ago
  • ERC4626 is a specification for a vault. This vault gives out shares in return for assets. The shares determine the underlying assets that can be redeemed (in terms of assets) from the protocol.
  • The number of shares that are gained is dependent on the vaults exchange rate. This rate is dependent on the vaults liquidity. For instance, if 100 tokens give 200 shares, then the share is worth 0.5 of a token.
  • When depositing tokens, the user receives a slightly rounded down number of shares. This often doesn't matter... but, in the case where small amounts of assets and shares are being used, this can cause major havoc. For instance, if the exchange rate for is 1 share for 100 tokens. Then depositing 99 tokens would result in a drastic loss with the user getting zero shares.
  • When the vault is empty, an attacker can abuse this rounding to steal money from other users. For instance, take the following scenario:
    1. The attacker buys a single share for virtually no money.
    2. A regular user decides to add in a large amount of the asset. They send the transaction.
    3. The transaction is frontran by an attacker who donates the same amount of funds as the user is about to add in.
  • Why does this matter? The contract currently has 1 share for a large amount of assets. So, the cost of 1 share is the amount of assets added in (assets worth/1 share). The user deposits in the token. If it's less than the worth of the one share, then they will get 0 shares even though they liquidity is added. The attacker can then withdraw their share for a massive profit.
  • This is a known limitation of the specification that was first realized by a Trail of Bits audit of Yearn. How do we prevent this? Two obvious ways are forcing a large deposit at the beginning of the contract and forcing a minimum amount of shares.
  • The new concept being used to prevent this by Amxx and Open Zeppelin is a virtual offset. The issue occurs because of an inflation attack on the contract and rounding errors with a small amount of shares. The goal of the virtual offset is to artificially increase the number of shares by adding more decimals to the shares. This mitigates the attack since the rounding error is what made the attack possible
  • The second remediation strategy is including the virtual shares and virtual assets in the exchange rate computation. By doing this artificial increase, the donation is somewhat put into the virtual components, making it not profitable.
  • Overall, an interesting attack that is possible because of frontrunning and the EVM not supporting floating point numbers. The solution to the problem is clever and does cost very much money for the users of the vault.

Voting Vulnerability of SUSHI Token - 1129

Phuwanai Thummavet    Reference →Posted 2 Years Ago
  • The SUSHI token is a governance token with voting power. The SUSHI holders can delegate their votes to other users to gang vote on proposals as well. This entity is known as the representative.
  • The protocol had some design flaws in it. The function _moveDelegates is executed during the voting delegation process to give the votes to a representative. Although the voting power is moved to the representative, the delegator's tokens are NOT. So, they can transfer the tokens to another user who can now vote or delegate further these further. This is known as a sybil or double spend attack.
  • The second vulnerability is a logic flaw in changing representatives. During the redelegation process, the previous delegates voting tokens are subtracted from and the new delegates tokens are added to. However, the previous delegate token amount subtracts with the current token amount instead of the previous. This means that we can subtract votes from a representative by simply delegating, buying SUSHI and changing representatives.
  • The previous vulnerability can also cause a denial of service (DoS). A user may want to redelegate their funds to another. However, since the current SUSHI token count is used instead of the previous one, the arithmetic can underflow.
  • Interestingly, these are known bugs by the SUSHI team. In the contract code, there is a comment saying to NOT use this token for security reasons. I'm sure when people assumed the code worked fine though. Why wouldn't they just patch the bugs then? So weird. Overall, impactful and simple logic bugs.

RouteProcessor2 has been exploited on Sushi Swap- 1128

Slowmist    Reference →Posted 2 Years Ago
  • Sushi Swap is a popular trading platform with the ability to take out loans, perform leverage trading and more.
  • When a user wants to allow an address to spend money on their behalf, they use the approve ERC20 function. Since we trust Sushiswap and they need the approval to spend our money in the smart contract call, this is a pretty standard thing to do.
  • A router contract allows for a high level call to be made and the smart contract will do the rest for you. For instance, if you wanted to trade USDC for wETH, you would need to find the pool to perform the trade. The router can be used as a lookup in order to find this pool. Additionally, it may be able to perform multiple operations in one transaction.
  • The Sushiswap router was a little too generous with user provided data. The function processRoute took in a variable called route, which was generated off chain. This route is used for the path of tokens to be traded, with the first token being the sold and the final being the bought token.
  • The route variable had no verification performed on it though. When using the swap command code with a UniswapV3 pool, the user can provide an arbitrary address.
  • The attackers contract calls back to the uniswapV3SwapCallback function. There is validation that the sender is the pool, which is true since an attacker controls the contract address! Now, the smart contract thinks that the caller is a UniswapV3 pool.
  • In the code, there is a safeTransferFrom call, where the attacker controls the from parameter. Since the router has approvals from other users to spend their money, an attacker can use this to send the money to themselves! Additionally, all of the funds of a token can be drained from the router itself, since it has a call to safeTransfer on itself.
  • This is why large approvals are horrible... you must be careful, since a protocol may have a vulnerability that will allow them to drain the funds of its users. Overall, a super interesting and impactful bug in a popular trading platform. In practice, be careful on the external contract calls and privileges you allow.

Beyond the market risk: a logic bug identified in SushiSwap’s KashiPairMediumRiskV1 contract- 1127

BlockSec    Reference →Posted 2 Years Ago
  • In November of 2022, BlockSec sounded the alarms: funds had been successfully drained from SushiSwap. They contacted the Sushi security team to try to remediate the situation.
  • There are functional bugs within smart contracts, like reentrancy and integer overflows. A large amount of the vulnerabilities are accounting bugs that come from messing up the math.
  • The borrow() function has the modifier solvent to check to see if it's above water. If it's not, then the transaction will revert. This is compared against the exchangeRate. Of particular importance is that this variable is mistakenly NOT upgraded in this function call.
  • In liquidate, the updating for the exchangeRate is done in the beginning of the function. If two prices are different between withdrawal and deposit, this can be a major case for exploitation.
  • The exploit steps are pretty straight forward for this. The attacker used a flash loan to amplify the calculation difference. In particular, the exchange rate in the borrow function was 250 * 10^27. On the liquidate function the exchange rate was 328 * 10^27. By borrowing at one rate then liquidating at another, they were able to make a huge profit off of this. I'm guessing that the hacker was sitting on a large price difference for a while in order to exploit this bug.
  • Overall, an interesting yet simple bug. Gotta do better than this!

Reentrancy Vulnerability in Sentiment.xyz- 1126

0xmikko_eth    Reference →Posted 2 Years Ago
  • Balancer had a read only reentrancy vulnerability. This happens when a read only function, outside of the protocol, calling back into the function within a weird state. The reentrancy checks don't work, since it's normally not put onto view functions.
  • The vulnerability comes from the function _joinOrExit. It invokes the function _callPoolBalanceChange before calling _setMinimalSwapInfoPoolBalances. This is important because _setMinimalSwapInfoPoolBalances updates the token balances for balancer. The interesting part is that the protocol will always send back unused Ether to the user part way through execution via sendValue.
  • The transferring of the ETH is in the middle of the execution of _callPoolBalanceChange but before _setMinimalSwapInfoPoolBalances. This means that the Balancer pool tokens have been minted but the vault has NOT been updated at this stage. This puts the contract into a funky state.
  • So, reentrancy to steal all of the money with consecutive calls, right? Well, not so fast. These functions have reentrancy modifiers on them in order to prevent this. The modifiers are only placed on external functions that modify the state typically. This still means a read only reentrancy is possible though. If an attacker sets up a fallback function where the extra ETH gets sent back to, they could make read only calls to the contract using this exploit. Further analysis of this vulnerability can be found on the Balancer Forums.
  • What even uses these read only calls though? Pricing oracles! In the case of Sentiment.xyz, they were using Balancer as an oracle for how much each token costs. The attacker performed the following steps to exploit this:
    1. Take out a flash loan and put assets into Sentiment.xyz as collateral.
    2. Manipulate the Balancer pool.
    3. Setup a reentrant contract to call the exitPool function.
    4. Call Sentiment.xyz with the manipulated pool prices to obtain collateral back at an extremely high cost.
    5. Profit.
  • I'm a little confused on how Sentiment.xyz got exploited on this, since this is an issue with Balancer and Balancer patched the problems. My hypothesis is that Sentiment.xyz was using an older version of the pool that was vulnerable or was not using the information from the contract properly. Overall, super interesting vulnerability!

Escaping the Dark Forest- 1125

samczsun    Reference →Posted 2 Years Ago
  • This post has a title that alludes to a famous MEV exploit article called Ethereum is a Dark Forest. In that story, the author of a post found some funds laying around that anybody could capture. They tried getting the funds for the poor victim but a bot swooped in and stole it.
  • samczsun was auditing a large amount of yield farming clones with the same pitch: stake your tokens to become the next crypto millionaire. While looking at some code late at night, they were looking where Ether was transferred and found two hits. The second one was a burn function that sent Ether to the sender.
  • The auditor found an issue. This was a contract to redistribute Ether to the bond holders upon maturity. The vulnerability was that a BondGroup could be made at no cost by providing an empty array. By setting the maturity to be the same as BondGroup 10 (with 25K Eth), it would be a valid.
  • Then, an attacker could exchange the empty BondGroup with a non-empty BondGroup by calling exchangeEquivalientBonds. At this point, they had essentially create a worth bond and turned it into a valid one. Wild!
  • The author had an exploit in hand. What to do now? If they get users to withdraw their funds, then some funds might get stolen. If they exploit it themselves, they could get hit by the Dark Forest. These whitehats wanted a rematch against the bots.
  • They built a trusted war room for people to try to perform this attack. To defeat the Dark Forest, they wanted to tap into a private mining pool. This way, since it wasn't in the mempool, it couldn't get frontrun. SparkPool has a special beta way of sending private transactions. So, this was the way to go.
  • They sent up 4 signed transactions to exploit this vulnerability. They tested them locally and really verified this would work. The plan was to transfer a large amount of 30K of SBT+LBT tokens to the Lien team. Then, the Lien team could run the final transaction to swap this for ETH.
  • They sent the transactions on the private setup and the team got the ETH back. It had worked. They had escaped the Dark Forest with $9.6M. The heros!

Ethereum is a Dark Forest- 1124

Paradigm - Dan Robinson & Georgios Konstantopoulos    Reference →Posted 2 Years Ago
  • This is a classic horror story on MEV bots in Ethereum. Read at your own discretion (and craziness).
  • While on Discord, the author of this post received a question on Uniswap: "is it possible to recover the LP tokens that are sent to the pair contract itself?" Initially, they thought no but it's recoverable - by anyone!
  • When somebody calls the burn function on the Uniswap core contract, the contract measures its own LP balance and burns it. Then, the withdrawn tokens are outputted to the caller of the function. Within the contract was 12K worth of liquidity tokens just waiting for somebody to take it. This is a ticking time bomb, since anybody could burn their LP tokens and accidentally receive the funds.
  • There is a pros and a cons to the decentralized nature of blockchain. One of these cons is that if there is a contract that can be exploited for a profit, then it will be; this is a battlefield. However, this isn't even close to how bad the mempool is, where unconfirmed/pending transactions lay. If the chain is a battle ground, the mempool is the much worse dark forest.
  • The mempool is filled with bots that exploit the ordering of transactions currently in the mempool in order to turn a profit. This is why recovering the funds is a complicated task! If a bot sees what we're trying to do, they frontrun the swap and use their own address to receive the money instead.
  • The name of the game here is obfuscation. We need to make the call to the contract without the bots being able to detect the pattern. Their obfuscation plan was to use two separate calls: a getter and a setter contract that will make these calls instead of a call from an EOA. This way, a simple modification to the transaction wouldn't be possible to perform.
  • Their hope was to deploy these contracts in the same block but separate transactions. If an attacker only executed the get, then the contract would revert. The thought was that by the time the set and get had both been executed, the bot wouldn't know what hit them.
  • When trying the recovery, the get call was rejected by Infura even with manual gas overrides. Oh gosh... this means that the set had been done and the get was getting ready to go. The transaction slipped into the next block... they got a INSUFFICIENT_LIQUIDITY_BURNED error from Uniswap, meaning that somebody had performed the call and stolen the funds.
  • What can we take away from this?
    • The monsters are real. Their are real generalized frontrunning bots out in the world who will steal funds.
    • Don't get sloppy. Have a plan and execute it.
    • Don't rely on normal infrastructure. The reason the getfailed was because it should have failed for the current blockchain state but not what they were updating it with. Or, know a private miner.
  • Overall, an extremely scary situation that's only going to get worse over time. The mempool is the reason for this unique bug class being possible. A product called VeeDo from Starkware has created a Verifiable Deploy Function to make Ethereum applications immune to these types of attacks.