Blur Exchange contest - Trust's results

An NFT exchange for the Blur marketplace.

General Information

Platform: Code4rena

Start Date: 05/10/2022

Pot Size: $50,000 USDC

Total HM: 2

Participants: 80

Period: 5 days

Judge: GalloDaSballo

Id: 168

League: ETH

Blur Exchange

Findings Distribution

Researcher Performance

Rank: 5/80

Findings: 3

Award: $2,969.45

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2022-10-blur/blob/2fdaa6e13b544c8c11d1c022a575f16c3a72e3bf/contracts/matchingPolicies/StandardPolicyERC1155.sol#L33 https://github.com/code-423n4/2022-10-blur/blob/2fdaa6e13b544c8c11d1c022a575f16c3a72e3bf/contracts/matchingPolicies/StandardPolicyERC1155.sol#L59

Vulnerability details

Description

ERC1155 tokens can support variable supply of each token ID. Therefore, ERC1155 NFTs can have amount more than 1. However, the StandardPolicyERC1155.sol policy always returns 1 as the matched amount, which is what will be traded. The key issue is that order.amount is never taken into consideration by the policy. So, victim may offer to buy with X ETH, Y amount of token Z, but attacker will sell them 1 for the same price.

Impact

Buyers may get much fewer NFTs than they pay for when buying ERC1155 tokens.

Proof of Concept

  1. User submits buy order for NFT X, amount Y
  2. Attacker calls execute() with a matching sell order for NFT X.
  3. User will receive a single NFT, but pay amount Y.

Tools Used

Manual audit https://betterprogramming.pub/erc1155-example-to-mint-multiple-nfts-cc716673d556

Instead of using hardcoded amount 1 for ERC1155 tokens, use order.amount. Also, the policy must make sure the buy and sell amounts are equal.

#0 - GalloDaSballo

2022-10-13T22:28:49Z

Findings Information

🌟 Selected for report: Soosh

Also found by: 0x1f8b, 0x4non, 0xc0ffEE, RaymondFam, Ruhum, RustyRabbit, Trust, arcoun, cccz, d3e4, minhtrng, rotcivegaf, saian, sakshamguruji

Labels

bug
duplicate
2 (Med Risk)

Awards

2437.8089 USDC - $2,437.81

External Links

Lines of code

https://github.com/code-423n4/2022-10-blur/blob/2fdaa6e13b544c8c11d1c022a575f16c3a72e3bf/contracts/ExecutionDelegate.sol#L18

Vulnerability details

Description

In the Blur security model, users approve their NFTs / WETH to the ExecutionDelegate (ED) contract. Only whitelisted contracts may call the ED transfer functions, which currently should only be the exchange proxy address. There are two rugging opportunities that arise from the implementation of the security model:

  1. Platform owner can upgrade the BlurExchange contract and add a function which steals all approved NFTs / WETH. Since the proxy address did not change, the ExecutionDelegate continues to trust the BlurExchange contract.
  2. Owner can add a new backdoor contract to trusted contracts list and perform the token theft from that contract.

Impact

Dishonest or hacked owner may immediately steal all WETH and NFTs trusted to the exchange.

Proof of Concept

Owner performs an implementation upgrade to BlurExchange. The new implementation has a backdoor function, which allows owner to call ExecutionDelegate's transfer functions with any parameters. Owner calls backdoor function to claim all trusted assets.

Tools Used

Manual audit

BlurExchange brands itself as a non-custodial NFT protocol. As such it should not have the capability to claim user's holdings for itself. An easy solution is an addition of time lock functionality:

  1. Contract upgrades require X time until they are executed
  2. Additions to ExecutionDelegate's contract mapping require X time This time window, for example 48 hours, will provide a sufficient opportunity for sellers and buyers to decide if they are interested in revoking their approval. If that is the case, they may call revokeApproval().

#0 - GalloDaSballo

2022-10-14T20:42:27Z

#1 - GalloDaSballo

2022-10-27T15:47:21Z

R

#2 - trust1995

2022-10-29T00:11:58Z

I believe this report introduces two significant centralization threats not discussed in referenced dup (esp. description point 2).

#3 - trust1995

2022-11-15T09:19:12Z

I will make a fact-based case of why this is a Med finding.

Firstly, it is not a dup of #713. #713 discusses a new executionDelegate which won't have revokedApproval set as previous one. That's not an actual issue because in Blur funds are approved to the executionDelegate, so a new delegate will not have users' approvals to begin with.

This report describes 2 centralization risks. Risk 1: Existing executionDelegate accepts any transferERC721 / transferERC20 / transferERC1155 calls from Exchange proxy address. Since there is no timelock (or a provable one), there is nothing stopping malicious or hacked owner from immediately upgrading the Exchange to this contract:

function _stealTokens( address token, address from, address to, uint256 tokenId, uint256 amount, AssetType assetType ) external onlyOwner { /* Call execution delegate. */ if (assetType == AssetType.ERC721) { executionDelegate.transferERC721(token, from, to, tokenId); } else if (assetType == AssetType.ERC1155) { executionDelegate.transferERC1155(token, from, to, tokenId, amount); } else if (assetType == AssetType.ERC20) { executionDelegate.transferERC20(token, from, to, amount); }

I will reiterate that this risk is not speculation on future code, it is a demonstration that existing code + dishonest owner results in rug pull of all Exchange funds. The existing code allows adding arbitrary abuse of approval, which is overly dangerous.

Risk 2: This risk shows admin can do a complete rug pull without any contract upgrade. Contracts are approved here:

function approveContract(address _contract) onlyOwner external { contracts[_contract] = true; emit ApproveContract(_contract); }

Then, they will pass the approvedContract() modifier:

modifier approvedContract() { require(contracts[msg.sender], "Contract is not approved to make transfers"); _; }

Which makes all the transfer calls accepted from a new approvedContract:

function transferERC721(address collection, address from, address to, uint256 tokenId) approvedContract external { require(revokedApproval[from] == false, "User has revoked approval"); IERC721(collection).safeTransferFrom(from, to, tokenId); }

So we've demonstrated a dead simple path where a malicious / hacked owner can abuse approvals to existing executionDelegate by adding a new evil contract to approved contract list and calling transfer functions on executionDelegate from that contract.

Again there is zero speculation on future code, only a demonstration of how existing code facilitates a rug pull. Speculation would be to state that owner will rug pull the project, we are merely pointing out that owner can rug pull the project.

I think this establishes clearly enough that owner can indeed instantly rug all user funds. Now we can take a look at previous similar findings: https://github.com/code-423n4/2022-06-illuminate-findings/issues/282 - shows admin can approve() malicious tokens and thereby steal user funds. The suggested fix is the same as mine, to put behind a timelock. It's essentially the same impact and similar call to risk 2. https://github.com/code-423n4/2022-10-thegraph-findings/issues/300 - simply stating that Governor has infinite approval on bridge funds is enough for M finding.

Also we can take a look at countless inferior centralization threats marked as M+ : https://gist.github.com/GalloDaSballo/881e7a45ac14481519fb88f34fdb8837 And only recently, a much weaker centralization threat in ArtGobblers was awarded M ( malicious admin can prevent new mints).

Hopefully this makes the case clear enough but would be happy to factually discuss any objection.

#4 - GalloDaSballo

2022-11-15T23:34:57Z

Dup of #235

Awards

416.821 USDC - $416.82

Labels

bug
QA (Quality Assurance)
sponsor acknowledged
edited-by-warden

External Links

Lines of code

https://github.com/code-423n4/2022-10-blur/blob/2fdaa6e13b544c8c11d1c022a575f16c3a72e3bf/contracts/BlurExchange.sol#L110

Vulnerability details

Description

The domain separator is supposed to guarantee the hash signed can only be applied in the context intended by the signer. However, the separator used by all order signature types in BlurExchange, does not differentiate between different implementations of the contract. The "verifyingContract" field in DOMAIN_SEPARATOR is set with address(this), which is the proxy address, not implementation.

Impact

User's submitted order is binding through logical updates of the contract. This has unforeseeable consequences for users of the platform.

Proof of Concept

  1. User submits sell order of NFT X for price Y
  2. For whatever reason, Proxy is upgraded to new implementation. For example, a 5% platform fee is taken for each order.
  3. A buyer purchases the NFT. User receives Y minus 5% platform fee. When listing the NFT, he assumed he would receive Y.

Tools Used

Manual audit

Use the implementation address as well as the proxy address in the domain separator. An easy way is to add an immutable variable impl_address which is set in the BlurExchange constructor.

#0 - minhquanym

2022-10-11T08:11:01Z

version will be changed when BlurExchange implementation is updated

#1 - trust1995

2022-10-12T20:17:08Z

Possibly, still I wouldn't count on developers bumping the version for each update, more often then not it will just lie around in the codebase. Good observation though!

#2 - blur-io-toad

2022-10-16T17:17:01Z

All upgrades will be made publicly and will give users time to adjust their listings as necessary. Won't be making changes as upgrading the version can still keep listings safe.

#3 - GalloDaSballo

2022-10-28T23:07:24Z

Will give a second look, but similarly to _gap like finding, we cannot make conjectures about code that is not in-scope.

#4 - GalloDaSballo

2022-10-29T00:40:33Z

I thin that because of the logical similarity to the Gap reports, the finding is valid.

But because we cannot determine a risk based on future code, I will downgraded to QA, Low Severity.

We can do this with recommendation that the sponsor does check the version value on new upgrades, however we cannot comment on the security of code from the future.

L

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