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!

Hundred Finance Hack- 1143

Rekt    Reference →Posted 2 Years Ago
  • Automated Market Makers are great! Well, until you manipulate the algorithmic part of it. It was audited by WhitehatDAO who cleared missed some things.
  • In Hundred Finance, hTokens are liquidity provider tokens. These are interest bearing tokenized representations of user deposits. This is denoted with an h in front of the token name, such as hBTC.
  • The exchange rate formula for the contract was based upon the amount wrapped Bitcoin (WBTC) that the hBTC the contract has inside of it. Using this knowledge and the lack of protection, this can be abused. First, the attacker donated 200 hWBTC from 200 WBTC.
  • By donating a large amount of hWBTC to the contract, the exchange rate went up dramatically. Using the inflated exchange rate, they took out large loans from other platforms. Why is this bad?
  • If we borrow 1M of assets at but provide something worth 1.5M, that's fine. However, the liquidation point is where the collateral becomes worth less than the borrowed funds. The attacker used the high exchange rate to trick protocols in accepting way less collateral than they should. Once they put the exchange rate back by redeeming the hWBTC, they kept the loan and left the useless collateral.
  • Algorithms are hard when using have access to infinite money with flash loans. Overall, another DeFi hack on Hundred Finance. It should be mentioned that this a fork of Compound... the flaw is partially in the design of Compound.

VM2 Sandbox Escape - 1142

SeungHyun Lee    Reference →Posted 2 Years Ago
  • VM2 is a sandbox for NodeJs. The idea is that untrusted code can be executed within this context without anything sensitive being stolen or important items altered. Being able to escape the sandbox would be terrible for the system.
  • Host exceptions may leak host objects in the sandbox. In order to prevent this from happening, code is preprocessed to instrument sanitizer for function calls. The identifier of the name catch clause has post processing in order to replace $tmpname with the actual value in a catch clause.
  • This post processing allows a user to bypass the handleException() processing as a result of this. Now, an attacker can use any method to raise a host exception. Then, using the context of the host, access objects higher in the hierarchy to get code execution outside the sandbox.
  • Overall, a straight forward sandbox escape by getting access to higher level objects. It's interesting how similar this is to Oxides sandbox escape 3 months ago.

Osmosis Zone Draining of Liquidity Pool Vuln- 1141

TheJunonaut    Reference →Posted 2 Years Ago
  • Osmosis Zone is a decentralized exchange built in the Cosmos ecosystem.
  • A reddit user made a comment that a bug in the liquidity pool allowed a gain of 50% for simply adding and removing liquidity from the pool. Naturally, people did not take the person seriously... until they tried it. This was taken advantage of to still money instantly.
  • Eventually, this led to a stoppage of the blockchain to allow for a fix before it was too late. How easy was this exploit? Put money in, take it out... do it again. Eventually, the various hackers stole 5M from the dex, prior to the stoppage. It's pretty clear looking at transactions that money is simply being duplicated.
  • Overall, a really simple vulnerability that is unreal it wasn't found during testing. To me, taking out when you put in seems like a pretty sane thing to test.

Synthetics Recorder: Code injection when recording website with malicious content- 1140

dee-see - HackerOne    Reference →Posted 2 Years Ago
  • Escaping input is very important when trying to prevent XSS, code injection and many other classes of vulnerabilities. However, the escaping is context dependent. In some situations, a single quote would break the system while, for other times, it may be another character. Knowing when to escape what really matters.
  • In this report, a user is providing a URL that will be navigated to. For some reason, there is a multiline comment that is necessary for escape some input. /*{ url: 'https://example.com' }*/ is used within the parameters. In order to prevent code injection, they call quote to escape single and double quotes.
  • The quote is not the only thing to worry about though. What about the comment? By ending the comment, an attacker can add their own code. For instance, the input https://example.com?q=*/.../* would escape the comment to add arbitrary content to the JavaScript. In particular, this appears to be a NodeJs environment.
  • The final payload to escape the function call and execute JavaScript is as follows:
    Injection point: 
    page.waitForNavigation(/*{ url: '
    https://example.com'}*/),
    
    Payload: 
    https://example.com?q=*/require(child_process)
    .exec(touch$IFS/tmp/haxx)/*
    
    Executed code: 
    page.waitForNavigation(/*{ url: '
    https://example.com?q=*/require(`child_process`)
    .exec(`touch$IFS/tmp/dee-see`)/*' }*/),
    
    
    
  • A pretty interesting case of not escaping inputs properly. True code injection doesn't happen very often but it's sure interesting when it does. Good report!

CAN Injection: keyless car theft- 1139

Ken Tindell    Reference →Posted 2 Years Ago
  • The author of this post noted a weird issue on Twitter: thieves were wrecking a mans cars to eventually steal it. Why and how? They wanted direct access to the Controller Area Network (CAN) bus. The Toyota has telemetry on it which is conveniently logs all errors on the CAN bus. On the RAV4, the headlights connect to the CAN bus directly, which is why the attackers removed the headlights.
  • The telemetry showed that the headlights had a communication failure. Not just for the lights though... many other things as well. Ian, the car owner, went on the dark web to find devices used to steal all sorts of cars. Eventually, he decided to buy one of these devices in order to reverse engineer it. This is where the author of the post comes into the situation: he's an expert on CAN buses.
  • When most people think about stealing cars, they think about issues with the smart key or key fob, from relay attacks to replay attacks. Since these issues are getting fixed, the attackers discussed a new technique: CAN bus injection. By sending data directly on the CAN bus, we can force it to perform actions. This is possible because the CAN bus is considered a trusted environment; there is no validation on who sends it.
  • The device is a JBL music speaker with CAN transceiver attached to it. The device gets connected to the CAN bus (commonly through the headlight) to impersonate a smart key Electronic Control Unit (ECU). In particular, it connects and sends back the "Smart Key is valid" signal to the car 20 times per second. This isn't enough though! Since the bus already has other devices on it, it disables other devices from writing to the bus with the dominant-override wire. By doing this over and over again, we can trick the car to turn on.
  • The author dives into the anatomy of the CAN bus protocol more throughout the article. From this, we can really understand how the injector works. To fix this problem, the author suggests using cryptographic primitives to prevent random devices from jumping onto the bus. Additionally, a more brittle fix would be to program the smart key CAN frame to only be accepted if no bit errors were found on the bus recently.
  • Overall, interesting article into the dark web and how people are actually stealing cars.

Precision Loss Errors- 1138

Dacian    Reference →Posted 2 Years Ago
  • Solidity only has integers and there is a lot of money going around. So, precision is very important when dealing with money. Sometimes, this benefits the protocol. Other times, funds disappear entirely. But worst of all, funds may be stolen. What are all the ways this can go wrong? This article dives into it.
  • Division Before Multiplication. All division in Solidity will round down by default. So, if we do division then multiplication, there is a chance of lost value along the way. The example shows a multiplication, division and two multiplications afterwards that result in precision loss.
  • Rounding Down To Zero. Since division rounds down to zero, small values may cause problems. In a loan application, an attacker could repay their funds. However, they could subtract a small amount. The result was that the loanCollateral was being subtracted when it was zero and the loanAmount could still be subtracted from.
  • The solution to the precision problem is to have a check to ensure that values do not round down to zero.
  • No Precision Scaling. Tokens have different decimal places, such as USDC with 6 and ETH with 18. In the example, two tokens are used to calculate the value of an LP token. A loss in precision can occur if computation is done by combining the amounts of two tokens with different precision without scaling the the secondary token to the primary tokens precision.
  • When combining amounts of tokens with different precision, convert the amounts to the primary token's precision before any computation. Otherwise, value could be added or removed from the contract.
  • Excessive Precision Scaling. Scaling too many times. If you scale ETH twice, then you will receive too many funds. An example can be found at here.
  • Mismatched Precision Scaling. One location may have the precision hard-coded while another is dynamic. If this mismatch can be abused, then the values could get messed up. If the values get messed up, it likely leads to loss of funds. In the example, a dynamic decimal and a hardcoded 1e18 token causes problems.
  • Downcast Overflow. When explicitly casting from one integer type to another, an unchecked overflow can occur. In the example on Balancer, a require was ran on a non-truncated value and the actual usage was done on the truncated value.
  • Overall, an amazing article on precision issues in Solidity. In particular, I enjoy the multiple examples per vulnerability.

QuestFactory is suspicious of the reorg attack- 1137

V_B    Reference →Posted 2 Years Ago
  • In Solidity smart contract, there are two ways opcodes that can deploy contracts: CREATE and CREATE2. CREATE uses the addresses incrementing nonce in order to determine the address. CREATE2 takes in a user controlled value in order to determine where to place the contract.
  • A network reorganization is when the blockchain ordering has changed somehow. This happens in a few cases:
    • Network lag
    • A fork of the chain
    • Malicious actor messing with the system
  • The smart contract being tested had functionality that would deploy a smart contract called a Quest when called. This contract used the CREATE in order to send this transaction.
  • The author of this finding (solo medium severity finding) brings up a scenario with reordering and deterministic creation of a smart contract. A user may have a local script to create the quest that waits for the success to occur. After this succeeds, this would send funds to the contract.
  • What if a reorganization occurred at this moment? A malicious actor could create the quest first! Then, the quest they created would be at a different location and their reassurance of the address would be gone. This means that the user would send their funds to the wrong contract.
  • The author mentions that a user may try to predict the contract address and send the funds there. If this is true, then a simple frontrunning attack would work on them as well.
  • The solution to this issue is to use the CREATE2 opcode instead. Overall, a weird finding that I'm sure could be reported more.

Loss of Funds Bug in Aptos and Sui from Move Compiler Bug- 1136

Jasper    Reference →Posted 2 Years Ago
  • Aptos and Sui are protocols built in the Move programming language. Both of these projects use type constraint checker to improve the safety of programs before they are executed. The verifier is a very important for the security of the platform.
  • Move needs to build a Control Flow Graph (CFG) in order to verify the reference and locals safety checker. The CFG divides code into basic blocks then adds successor edges to where the code could potentially go, with at most two. This CFG is used by the verifier code in order to confirm everything is safe.
  • The vulnerability appears to be an edge case to prevent integer overflows. If the index of the code was the maximum 16 bit integer, then an empty sets of edges were returned. This can be seen in the code snippet at here. Without the edge, the verifier will never check this edge but the code will still be executed! The difference between the use and the check is the problem.
  • In Move, there is the concept of a Hot Potato. This is when a program gives some code that an address must invoke. With a flash loan, this requires the user to run code in order to pay back the flash loan. If we could get rid of the flash loan amount or the callback itself, it would be horrible for the program.
  • Using the vulnerability in the verifier above, we can bypass this check! We force the unverified block to be code that would overwrite the value of the flash loan that we need to provide. Normally, the verifier would catch this not allowing us to write to this section. This is just an example of how this can be exploited though.
  • Overall, a super interesting bug in how the Move programming language must operate. Aptos labs has a 1M bounty on vulnerabilities that lead to lost of funds and is very concerned with the security of the platform.

C3 Linearization in Solidity- 1135

bytes032    Reference →Posted 2 Years Ago
  • Inheritance is straight forward until its not. What do you do when a diamond is created from inheritance. For instance, if we have contract A, contract B & C which inherit from contract A and contract D which inherits from B & C. Weird problem to have. The solution to this in Solidity is C3, which is also used by Python.
  • The algorithm guarantees that the method of resolution is uniform throughout the inheritance hierarchy. Additionally, it's expected that method calls and attribute lookups work in this scenario as well.
  • The goal of the Linearization is to make this a linear hierarchy. As a result, the inheritance flow will turn into [D,C,B,A]. Crazy enough, C is now a direct descendant of B! Although this is not the EXACT interruption that you would expect, it's better than the program not compiling.
  • Constructors for the parent contracts are always executed in the C3 order. Changing the order of constructor execution within the child constructor doesn't effect this at all. Additionally, a parent with a constructor and no arguments is automatically invoked, even if it's not explicitly invoked by the child. There is an example in the code of this for the Ownable contract.
  • Overall, a pretty interesting article on how inheritance works in Solidity. Probably been a few bugs in the past as a result of this.

Digging into Compound- 1134

Bytes032    Reference →Posted 2 Years Ago
  • Compound is a borrowing and lending protocol built on Ethereum. Naturally, Compound needs funds to lend out. This is done via liquidity providers (LP). When an LP deposits funds, they are put into a huge pool and receive the ERC-20 token cToken. This cToken represents a portion of the total pool. As the pool earns interest, the amount of funds a user can claim grows.
  • cTokens represent ownership of a loan to be taken out. The value of the cTokens increases over time as borrowers make payments. The cTokens allow a user to take loans by using them as collateral. This means that the funds a user deposits as an LP to get cToken can directly be used to get another asset.
  • cTokens are generic. For instance, cDAI is the DAI token cToken. How does it know how much a token is worth or what the exchange rate is? They use a Chainlink pricefeed in order to do this. This oracle is used to determine collateral requirements and all of the other fund work.
  • The Controller manages risk within the protocol. This is done by setting collateral requirements and liquidation thresholds based on risk weights, user balances and prices from the oracle. Naturally, loans need to be overcollaterized in DeFi in order to work. This logic ensures that the protocol never loses funds on a loan when the market goes down.
  • How does the protocol remain solvent - or have enough funds? Either too many people are borrowing or there are not enough funds being lent. To solve this problem, Compound has a formula known as the utilization rate for a pool. The higher the current utilization rate, the higher the interest on the loan is. Naturally, if the utilization rate is high, less loans will be taken out. Additionally, it will have high interest rates, leading to more LPs to provide value.
  • The interest rate is calculated using the utilization rate, the profits to the protocol and the general borrowing interesting rate. This final value is calculated using an interest rate model to determine the cost of it. In particular, it has a flat fee and a yearly multiplier. This makes the interest linear. The graphs in the article use the purple line as what the borrower pays and the green line as what the LP receives.
  • Most borrowed assets use the Jump Rate model. It's exactly like the previous model with two additional parameters: kink and jump multiplier. The kink is the point on the graph that the jump multiplier is used. The jump multiplier is the rate of increase once the kink has been hit. This makes a very steep climb once a particular threshold of utilization has been hit.
  • The goal is that a high APY will incentivize users to deposit more to ensure there is always liquidity for withdrawal. With these values in mind, it is possible to calculate the amount of interest that would be paid for a loan over a given time period.
  • Overall, good explanation on Compound! I had a lot of misconceptions cleared up.