Lucene search

K
code423n4Code4renaCODE423N4:2022-10-HOLOGRAPH-FINDINGS-ISSUES-297
HistoryOct 25, 2022 - 12:00 a.m.

Optimistic bridging pattern, can lead to bridge exploitation

2022-10-2500:00:00
Code4rena
github.com
2

Lines of code
<https://github.com/holographxyz/holograph-protocol/blob/c4_audit/contracts/HolographBridge.sol#L270&gt;

Vulnerability details

Impact

Zero deposit Bridging. Wherease users can fake the depositing process but can mint multiple tokens in the destination chain.

The bridging is optimistic, whereas the validation restricts to just checking the function selector and a no-error pattern, this can be exploited in many possible ways.

The returns variable is also not validated. Possible re-entrancy can also happen in the bridgeOut() function.

Proof of Concept

Step 1

Reproducing the issue is pretty straight forward, you can deploy the entire suite of contracts and start of with deploying a new holograph contract using deployHolographContract() function. This function accepts a byte code.

function deployHolographableContract(
    DeploymentConfig memory config,
    Verification memory signature,
    address signer
  ) external {
    address registry;
    address holograph;
    assembly {
      holograph := sload(_holographSlot)
      registry := sload(_registrySlot)
    }
    bytes32 hash = keccak256(
      abi.encodePacked(
        config.contractType,
        config.chainType,
        config.salt,
        keccak256(config.byteCode),
        keccak256(config.initCode),
        signer
      )
    );
    require(_verifySigner(signature.r, signature.s, signature.v, hash, signer), "HOLOGRAPH: invalid signature");
    bytes memory holographerBytecode = type(Holographer).creationCode;
    address holographerAddress = address(
      uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), hash, keccak256(holographerBytecode)))))
    );
    require(!_isContract(holographerAddress), "HOLOGRAPH: already deployed");
    uint256 saltInt = uint256(hash);
    address sourceContractAddress;
    bytes memory sourceByteCode = config.byteCode;
    assembly {
      sourceContractAddress := create2(0, add(sourceByteCode, 0x20), mload(sourceByteCode), saltInt)
    }
    assembly {
      holographerAddress := create2(0, add(holographerBytecode, 0x20), mload(holographerBytecode), saltInt)
    }
    require(
      InitializableInterface(holographerAddress).init(
        abi.encode(abi.encode(config.chainType, holograph, config.contractType, sourceContractAddress), config.initCode)
      ) == InitializableInterface.init.selector,
      "initialization failed"
    );
    HolographRegistryInterface(registry).setHolographedHashAddress(hash, holographerAddress);
    emit BridgeableContractDeployed(holographerAddress, hash);
  }

The above function basically allows anyone to deploy their holograph contract as it is just with identifier external. Hence any valid EVM account holder can deploy a holograph contract with a function selector similar to the Holographable.bridgeOut.selector and return true in all cases (or) with custom logic to re-enter the bridge.

src: <https://github.com/holographxyz/holograph-protocol/blob/c4_audit/contracts/HolographFactory.sol#L192&gt;

Step-2

In the bridge contract, call the bridgeOutRequest() function with a random payload. Now the function will execute successfully irrespect that, the bridgeOut() logic basically moves no tokens from the user’s wallet inside the holograph contract logic.

(bytes4 selector, bytes memory returnedPayload) = Holographable(holographableContract).bridgeOut(
      toChain,
      msg.sender,
      bridgeOutPayload
    );


    require(selector == Holographable.bridgeOut.selector, "HOLOGRAPH: bridge out failed");

After calling this function, which will optimistically consider all the true values as logic executed, we can then be able to call stuff we would like, which includes re-entrancy and feeding in a different holographContract()

Hence we would be able to either re-enter the contract (or) mint infinite tokens at this point without really bridging them.

src: <https://github.com/holographxyz/holograph-protocol/blob/c4_audit/contracts/HolographBridge.sol#L262&gt;
<https://github.com/holographxyz/holograph-protocol/blob/c4_audit/contracts/HolographBridge.sol#L270&gt;

Visual Representation

Flowchart

Note: would auto-delete in 6-days

Damages

The exploit clearly allows anyone to misuse the protocol for their own good. For eg, the exploiter can deploy a ERC20 token and list them to uniswap.

Later he can use the tokens to bridge them across chains without really moving them and rugging the users. I’ve added one possible example, but there are clearly many more of them.

Tools Used

Hardhat
Chai
Draw io
Dillinger

Recommended Mitigation Steps

Multiple ways are there to mitigate the possible risk of the problem. Some of them are,

  1. Allow approved entites to deploy a new holograph contract.
  2. Prevent optimistic flow and add balance validation inside bridge, re-architect the token flow pattern.
  3. Make sure the bytecode is what you expected for the user to deploy and standardize a byte code pattern.

The text was updated successfully, but these errors were encountered:

All reactions