Achieved 5th place in @mellowprotocol contest on @sherlockdefi. Joined late, missed some high/medium issues, but found one high and one solo medium. Let's see what's next.
- make a model
- market it as "extremely powerful at cybersecurity"
- everyone is now hyped and waiting for your new model to be released, more than happy to pay you 200$ when it comes out
- model released, big sales
- users complain that any security related question is blocked due to "safety measures"
- turns out the model was never as good at cybersecurity as claimed
- but it does not matter, because the weakness is hidden behind the "safety measures"
https://t.co/Ev5Xf9sFVA
This is how @THORChain hack happened:
1- for EVM/ERC20 tokens, Thorchain keeeps assets in a router (https://t.co/cA2dtcGdw6) and gives allowance to asgard vault addresses to transfer those tokens out. (an internal allowance mapping, not a ERC20 allowance/approval)
2- For example, https://t.co/SfbZo28AEu is an asgard vault (an EOA account), which had allowance to spend tokens from the thorchain router and transfer tokens out of that contract.
3- once attacker controlled/reconstructed the vault private key to 0x82a5cf67f3e6970c0529122178075c0a94878bda it could spend all that allowance and transfer tokens out of the router.
4- If you look at the 0x82a5cf67f3e6970c0529122178075c0a94878bda on etherscan, its simply an EOA address. but who controls this address and its private key? did attacker steal the private key of this wallet? yes, but its not as simple as that. this wallet is controlled by a GG20 threshold ECDSA key, i.e, not a single person can simply sign a transaction and execute it. the private key is split into shares between the nodes which are eligible to participate in the signing set. enough nodes need to participate in the GG20 signing protocol using their own private key shares to jointly produce the final ECDSA signature and hence execute a transaction from 0x82a5cf67f3e6970c0529122178075c0a94878bda on chain.
5- so private key of this asgard vault, was not simply stored somewhere, like on a paper, or in a notes app etc which attacker could steal. the private key could only be reconstructed if you knew the secret share of other nodes participating in the signing set. the private key should never be reconstructed during normal operation.
6- so attacker had to first join the signing set then find a way to extract information about the secret shares of the other nodes in the same signing set, as a result attacker could reconstruct the full vault private key and sign any arbitrary transaction from it (i.e transferring tokens out of router).
8- attacker reportedly joined the signing set by bonding around 635,000 RUNE
9- This is where the problem arises, THORChain was using an older GG20 TSS implementation. In GG20, participants use paillier encryption during the offchain signing protocol to do encrypted math without revealing their private key shares. the vulnerable implementation did not properly reject malicious paillier key material, so the attacker could provide malformed paillier parameters. when honest nodes interacted with that malicious participant during signing rounds, their protocol responses leaked small pieces of information about their secret key shares.
10- this leak was not from the final on-chain signature itself, but from the off-chain signing messages exchanged between TSS participants.each signing session gave the attacker more constraints about other nodes secret shares. think of it like a huge equation with many unknown variables => one result is useless, but enough different results can reveal the hidden variables.
11- attacker finally reconstructed the private key of the 0x82a5cf67f3e6970c0529122178075c0a94878bda using those secret parts (conceptually: secret_share1 + secret_share2 + secret_share3 + ... = final_private_key). now attacker has full control of this asgard vault (which is bascially an EOA account), and a ton of allowance on thorchain router.
12- attacker simply used that private key to transfer the funds out of the thorchain router (https://t.co/SfbZo28AEu look at the "TransferOut" transactions)
13- for other chains like BTC, LTC, DOGE, etc, the attacker used the reconstructed chain-specific vault private key to sign native L1 transactions and drain funds directly from those vault addresses.
https://t.co/clP0FUpSa0
How this @KelpDAO hack happened (290M gone) :
1- rsETH had a unichain <=> ethereum layerzero path, meaning that rsETH could move between these two chains through kelp layerZero OFT setup
2- this path relied on only one required DVN, one single verification from this DVN was enough to execute a message on the ethereum side of this bridge
3- the DVN was shown a fake unichain event and signed a packet that did not happen on unichain (RPC poisoning attack)
4- the layerzero on ethereum side executed that signed packet, and kelp OFT adapter released 116,500 rsETH to attacker
kelp must have used > 1 DVNs to verify a message (like 2 of 3, or 3 of 5)
https://t.co/ZgW8MIbYwg
this is how this attack happened in simple terms (rekted around $4.3M in USDC, 274 WETH, $434K in USDT, and 14.16 PAXG (gold)):
1- the attacker first created fake tokens on osmosis chain, the osmosis chain has a token factory which allows users to create their own tokens. the attacker created fake versions of USDT, USDT, PAXG (gold) and WETH.
2- osmosis chain can communicate with gravity chain through cosmos IBC (inter-blockchain communication), so attacker bridged their fake tokens to gravity chain using IBC. as soon as the tokens arrived on gravity chain, they got assigned a unique IBC denom on gravity chain (https://t.co/oLR7jsACz6 this link explain IBC denoms, the IBC denom is something like this [ibc_denom = 'ibc/' + hash('path' + 'base_denom')])
3- the gravity bridge has a registry which maps an IBC denom to an ETH token address. so for example, the registry maps ibc_denom X to pepe coin on ethereum chain. that means when you withdraw a pepe wrapper coin that has the ibc_denom X from gravity chain, you will receive real pepe coins on ethereum chain.
4- now the attacker only needs to map the ibc_denom of the fake tokens they have to the address of a real coins on ethereum (USDC, USDT, PAXG, WETH) and then by withdrawing the fake coins they just bridged into gravity, they can receive real assets on ethereum chain
5- to do this attacker used the gravity's ethereum bridge contract (https://t.co/631Tfqogz0), they called the deployERC20 function with a malformed ibc denom which included both the ibc_denom of the fake tokens they have on the gravity chain as well as the real coin addresses (USDC, USDT, PAXG, WERH) on the ethereum chain (ibc/C92D312D79D9C44B6C6F94AF40FFCB30A334D87F08952D6ED9904E3E83A9F50C/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/transfer/channel-10/factory/osmo1m9athjzah02f2mnrgtcke7e5ya3zpvw8lccuss) (and tx = https://t.co/PJkrZku1oe)
6- this ibc denom was crafted in such a way that when picked up by gravity validators and orchestrators they mapped the ibc_denom of the fake hacker tokens to the real coin addresses on ethereum
7- now the ibc denoms of the fake attacker coins were pointing to the real ethereum addresses (e.g. fake_usdt_denom => real_usdt_address).
8- attacker simply withdrewed those coins and received real assets on ethereum chain.
easy peasy lemon squeezy.
Lesson learnt for future protocols/bridges integrated with IBC to make defi great again?
never ever freely trust user-controlled cross-chain metadata to change some critical states, check every edge case, validate every bit, and more importantly dont forget good audits.
#MAKE_DEFI_GREAT_AGAIN
When auditing a protocol, ask AI to write test scenarios starting from contract deployment all the way through day-to-day protocol lifecycle and user interactions.
Then follow those tests as you read the code.
It gives you a much clearer understanding of how the whole protocol works, and how each piece fits together.
https://t.co/u6UECpMC4u
How this rekt happend:
1. The old DxSale v1 locker used an Ownable admin model. whoever held the owner key could call privileged functions and bypass what users thought were immutable LP locks.
2. the original owner called transferOwnership, giving the attacker full admin control of the primary locker contract and two other locker contracts.
3. Because the attacker was now owner, the “locked” LP tokens were no longer protected by time-lock logic in practice so admin authority could trigger token transfers out directly.
4. The attacker used EIP-7702-style batch delegation / atomic transaction tooling to efficiently hit 1,400+ liquidity pools on BNB Chain in a coordinated flow.
5. They pulled LP tokens from the locker, redeemed/removed liquidity from pools, and converted the locked positions into movable assets.
6. Proceeds were routed through aggregation/relay wallets and then dispersed to Binance deposit addresses.