Skip to content

paco0x/kyber-exploit-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Here's the reproduction of the Kyber elastic exploit. For more details on the underlying issue, please see this link.

This might be one of the most intricate DeFi protocol exploits to date, requiring highly accurate and specific parameters for successful attack transactions. A discrepancy as small as 1 wei could lead to different outcomes.

I was intrigued by how the hacker managed to determine the exact parameters needed for various Kyber pools.

At first, I tried using some random numbers to reproduce this attack. But it was unsuccessful and it turned out that obtaining the the correct parameters is difficult with a very low likelihood of success.

Eventually, I found that Foundry could be used to perform brute force testing to pinpoint vulnerable parameters. (Kudos to Foundry for executing Solidity code at blazing fast speeds!)

As of now, this repository only includes methods using brute force—is there a better approach?

Reproduce the exploit in local test pool

This test setup a 1:1 pool and brute forcing to get a value to exploit the pool.

❯ forge test -vvv --mt testBruteForceExploit

It will take a while to run this test, since it's brute forcing.

A particle attack may leverage a forked network to pre-calculate necessary values, which are then utilized in the attack transaction.

Fuzz test

Run fuzz to test if it can get an exploitable value (only 1 fuzz variable).

By default, foundry fuzzer only generate 256 cases, which is not enough to get a exploitable value. I've changed the config to 65535 so that the fuzz test can take effect on this simple case.

❯ forge test -vvv --mt testFuzz [⠊] Compiling... No files changed, compilation skipped Running 1 test for test/Kyber.t.sol:KyberAttack [FAIL. Reason: Assertion failed. Counterexample: calldata=0x0x6590d6450000000000000000000000000000000030303030303030303030363636390000, args=[64053151420411946063694050374803062784 [6.405e37]]] testFuzz(uint128) (runs: 8493, μ: 9713, ~: 9800) Logs: Bound Result 67288735232761868185 liquidity 67288735232761868185 targetSqrtP 20693058119558072255662180724088 nextSqrtP 20693058119558072255665665854997 Error: a == b not satisfied [bool] Expected: true Actual: false ...

This test is expected to fail because the invariant cannot consistently be met in Kyber. I've simplified and focused on specific mathematical operations that impact the invariant for demonstration. In real production environment, we typically run fuzz tests on a higher-level swap functions, making the failure identification more challenging.

Probability analysis

By utilizing the exceptionally fast foundry execution, we can evaluate the chances of getting a liquidity amount within a specified LP range that can be used for exploiting the protocol.

❯ forge test -vvv -mt testProbability

This runs a simple for loop to get the valid values(liquidity amount) found in a given LP range.

Some of the found numbers when setting liquidity to [80e18, 80e18+1e8]:

❯ forge test -vvv -mt testProbability ... liquidity 80000000000009325512 liquidity 80000000000009325561 liquidity 80000000000009325610 liquidity 80000000000009325660 liquidity 80000000000009325709 liquidity 80000000000009325759 liquidity 80000000000009325808 liquidity 80000000000009325857 liquidity 80000000000009325907 liquidity 80000000000009325956 liquidity 80000000000009326055 liquidity 80000000000009326104 liquidity 80000000000009326154 liquidity 80000000000009326203 liquidity 80000000000009326252 liquidity 80000000000009326302 liquidity 80000000000009326351 liquidity 80000000000009326401 liquidity 80000000000009326450 liquidity 80000000000009326499 liquidity 80000000000009326549 liquidity 80000000000009326598 liquidity 80000000000009326648 liquidity 80000000000009326697 liquidity 80000000000009326746 liquidity 80000000000009326796 liquidity 80000000000009326845 liquidity 80000000000009326895 liquidity 80000000000009326944 liquidity 80000000000009326993 liquidity 80000000000009327043 liquidity 80000000000009327092 liquidity 80000000000009327141 liquidity 80000000000009327191 liquidity 80000000000009327240 liquidity 80000000000009327290 liquidity 80000000000009327339 found 1983 in 10000000 Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 84.69s Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)

When configuring the liquidity range to [20282409603651670423947251286016, 20693058119558072255662180724088] and initiating with a liquidity amount of 80e18, it identified 1983 valid values out of 10,000,000 attempts. Adjusting the range and initial liquidity can yield varying outcomes for further analysis.

About

reproduce kyber-elastic exploit

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published