Defending web3 against domain hijacking

TL;DR: Wallets query a domain, let’s say carpetde.fi (shameless shilling) on an on-chain registry. The carpetde.fi owner marks what smart contracts can be interacted with by this website. If the frontend interacts with something else, the wallet will give a BIG BOLD WARNING!

May 14th, 2022. GoDaddy gets attacked and many DeFi protocols’ domains get domain hijacked. QuickSwap’s frontend is quickly replaced with a phishing frontend, with many users losing funds to a malicious smart contract.

Let’s say you’re a DeFi power user, you know the ins and outs of every protocol you use. You’re pretty tech savvy and you always double-check the domain names.

One day you’re just conducting what seems to be a normal swap on your AMM of choice. Wait, where did all your USDC go? Uh oh. You check the approval transaction, and you see that you approved an attacker to take your funds. The domain just got hijacked. You feel like an idiot now, and you lost your money. :(

Domain contracts registry

Let me explain what I mean.

There’s a common security practice called the principle of least privilege where an application should only get access to what it needs and nothing more. We can apply this here, having the trusted wallet interface warn the user with big BOLD TEXT when the frontend tries to send a transaction to an address that isn’t registered as allowed for this domain and falling back to allowing all contracts if there is no registry entry.

There would be an on chain registry where domain owners can register their domain and add/remove allowed smart contracts. A domain owner would be able to prove their ownership with a TXT record on the domain pointing to their address (maybe _dcr.carpetde.fi shameless shill), signed with the registry’s DNSSEC key.

Each blockchain would get its own registry deployed as a Singleton at the same address using EIP 2470.

To protect against the attacker gaining control of the domain, sending a new proof of domain ownership would require a timelock of 1 month, more than enough time for the domain owner/registrar to get their shit together.

This is fully backwards compatible with all smart contracts however it requires wallets to implement it, falling back to the current insecure behavior if unimplemented.

The registry should be flexible

The registry should give enough tools for the developer to secure their dapp with fine grained policies if necessary. By default, a registered domain will use a basic implementation of a Checkpoint, which is a smart contract that has the following function selector and satisfies the implementation criteria:

function checkInteractionAllowed(address callTarget, bytes calldata) external view returns (bool allowed)

A checkpoint implementation MUST:

  • Either revert or return false in allowed if a condition is not satisfied

  • Return true in allowed if the conditions are met

A client implementation MUST:

  • Look up the domain in the registry and find the Checkpoint address

  • Run the function checkInteractionAllowed on the Checkpoint with the target of the transaction and the transaction’s calldata

  • Alert the user if the function either reverts or returns false in allowed

A basic example of a Checkpoint would be something like this:

contract BasicCheckpoint is Ownable {
  mapping(address => bool) public isAllowed;
  
  function setAllowed(address contract, bool value) external onlyOwner {
    isAllowed[contract] = value;
  }

  function checkInteractionAllowed(address callTarget, bytes calldata) external view returns (bool allowed) {
    require(isAllowed[callTarget], "Not allowed");
    return true;
  }
}

More complex Checkpoints are possible, such as Checkpoints that check contracts to see if they are ERC-20s, Checkpoints that make sure the frontend only approves certain parties, etc etc. MIght turn this into an EIP.

I really hope that one day, DeFi becomes much much safer for the average user without sacrificing decentralization.

Image attribution

"Computer Data Hacker" by Visual Content is licensed under CC BY 2.0.

Subscribe to Operator
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.