Connext contest - cmichel's results

The interoperability protocol of L2 Ethereum.

General Information

Platform: Code4rena

Start Date: 09/07/2021

Pot Size: $25,000 USDC

Total HM: 7

Participants: 10

Period: 3 days

Judge: ghoulsol

Total Solo HM: 2

Id: 19

League: ETH

Connext

Findings Distribution

Researcher Performance

Rank: 2/10

Findings: 7

Award: $5,166.54

🌟 Selected for report: 4

🚀 Solo Findings: 1

Findings Information

🌟 Selected for report: 0xRajeev

Also found by: cmichel, pauliax

Labels

bug
duplicate
3 (High Risk)

Awards

1103.2637 USDC - $1,103.26

External Links

Handle

cmichel

Vulnerability details

Vulnerability Details

The addLiquidity function can be called by anyone to transfer funds from the router address specified as a function argument. These funds must be approved first by the router prior to calling this function. There are different griefing attacks depending on the allowance that the router set to the contract:

  • allowance > amount: For example, the allowance could be set to the maximum value of type(uint256).max which allows anyone to deposit more of the router's balance to the contract, even if they only intended to deposit amount. The additional funds must then first be removed again by the router. Usually, it's best practice to only set an allowance equal to the amount to transfer. (option 2)
  • allowance = amount: Upon observing an addLiquidity(amount, assetId, router) transaction, the attacker can call addLiquidity(1, assetId, router) to transfer and decrease the allowance by a single wei. As the updated allowance for the original call with then be allowance - 1 < amount, the original addLiquidity call will revert.

Impact

A griefer can deny anyone from depositing their desired amount of liquidity.

Remove the router argument and always transfer from msg.sender, essentially setting router = msg.sender.

#0 - LayneHaber

2021-07-12T20:01:05Z

#48

Findings Information

🌟 Selected for report: 0xRajeev

Also found by: cmichel, gpersoon, pauliax, s1m0, shw

Labels

bug
duplicate
3 (High Risk)
sponsor confirmed

Awards

402.1396 USDC - $402.14

External Links

Handle

cmichel

Vulnerability details

Vulnerability Details

The fulfill transaction on the receiving chain tries to call the addFunds and execute actions on txData.callTo. When any of the calls reverts, the funds are sent to the txData.receivingAddress.

The txData.callTo is user-controlled and an attacker can deploy a contract to this address and revert on both calls, receiving the amount twice.

Impact

The receiver can get twice the amounts of funds that the router agreed to (and locked up). This allows stealing all added liquidity in the contract by an attacker engaging in cross-chain transfers with themselves.

Only transfer them once, not in both catch blocks.

#0 - LayneHaber

2021-07-12T19:44:15Z

#46

Findings Information

🌟 Selected for report: pauliax

Also found by: 0xsanson, cmichel, shw

Labels

bug
duplicate
3 (High Risk)
sponsor confirmed

Awards

744.703 USDC - $744.70

External Links

Handle

cmichel

Vulnerability details

Vulnerability Details

The fulfill transaction on the receiving chain first approves the txData.callTo contract with the toSend amount.

It then tries to call the addFunds and execute actions on txData.callTo. When any of the calls reverts, the funds are sent to the txData.receivingAddress.

Note this is a different attack from "Funds are sent twice on callTo errors". Assume that issue was already fixed and it would only send out the transfer once.

The txData.callTo is user-controlled and an attacker can deploy a contract to this address and revert on all calls. They then receive the funds once (or twice if other issue was not fixed) through the direct LibAsset.transferAsset(txData.receivingAssetId, payable(txData.receivingAddress), toSend) call. Afterwards, as the approval was given to callTo, the attacker can send a transaction to their callTo contract to transferFrom(TransactionManager, toSend) again.

Impact

The receiver can get twice the amounts of funds that the router agreed to (and locked up). This allows stealing all added liquidity in the contract by an attacker engaging in cross-chain transfers with themselves.

Giving approvals to arbitrary contracts is very dangerous. It should probably be removed completely. If it's really desired, at least reset the approval to 0 again at the end of the fulfill function such that callTo must have used transferFrom within the same transaction in the execute call.

#0 - LayneHaber

2021-07-12T19:37:15Z

#31

Findings Information

🌟 Selected for report: cmichel

Labels

bug
2 (Med Risk)
sponsor acknowledged

Awards

1225.8485 USDC - $1,225.85

External Links

Handle

cmichel

Vulnerability details

Vulnerability Details

The agreement between the user and the router seems to already happen off-chain because all the fields are required for the initial InvariantTransactionData call already. A router could pretend to take on a user's cross-chain transfer, the user sends their prepare transaction locking up funds on the sending chain. But then the router simply doesn't respond or responds with a prepare transaction of amount=0.

Impact

The user's funds are then locked for the entire expiry time whereas the router does not have to lock up anything as the amount is 0, even no gas if they simply don't respond. This way a router can bid on everything off-chain without a penalty and take down everyone that accepts the bid.

Maybe there must be a penalty mechanism for non-responsive routers that agreed off-chain, slashing part of their added liquidity. Could also be that the bid signature already helps with this, but I'm not sure how it works as the off-chain part is not part of the repo.

#0 - LayneHaber

2021-07-12T20:58:15Z

This is true, and we are building penalty mechanisms outside of these contracts. For now we are considering adding in a permissioned launch, see #49

Findings Information

🌟 Selected for report: 0xRajeev

Also found by: cmichel, shw

Labels

bug
duplicate
2 (Med Risk)

Awards

330.9791 USDC - $330.98

External Links

Handle

cmichel

Vulnerability details

Vulnerability Details

The fulfill signature is only on (txData.transactionId, relayerFee) which allows the router to steal user funds for cross-chain transfers that go to the same router and use the same transaction ID as an earlier transfer.

Example:

  • a successful cross-chain transfer is done. The user at some points leaks fulfill.signature which acts as a ticket for the router to claim their amount on the sending chain.
  • The user prepares another cross-chain transfer using the same transaction ID and router.
  • The router does not need to lock up funds using prepare at all now, they can just use the previous signature to steal the funds

Note that the signature is also not bound to a chain, the user could create the second cross-chain transfer on a different chain using different assets.

The transaction ID must be unique per user among all chains. Therefore, it's hard to enforce this on a chain-specific contract. A way to mitigate this would be to let the signature be on the entire txData + relayerFee instead of just the txData.transactionId + relayerFee.

#0 - LayneHaber

2021-07-12T20:23:29Z

#54

#1 - ghoul-sol

2021-08-02T00:05:22Z

Medium risk Ref #54

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter