Skip to content

ensdomains/ens-contracts-bug-62248-pr-509

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DNS SEC upgrade repo

Summary

This repo contains the solution to address two issues.

To address these issues, this repo contains the set of instructions to deploy new contracts, make configuration changes, then test that if the vulnabilities are fixed.

File structure

├── mainnet.env
├── README.md
├── reports
    ├── PoV.sh # Original exploit test script
    ├── PoVNew.sh # Modified exploit test script that takes variables
    └── REPORT.md # Original report
└── sepolia.env

Steps overview

  1. DAO vote to transfer the ownership of DNSSECImpl (0x0fc3152971714E5ed7723FAFa650F86A4BaF30C5) to security council multisig (0xb8fa0ce3f91f41c5292d07475b445c35ddf63ee0)
  2. Run PoV.sh to check the test passes (exploit exist)
  3. Security Councitl to Deploy contracts
  4. Security Councitl to set Algorithem
  5. Run PoV.sh with new contract addresses to check the test fails (exploit closed)
  6. Security Councitl to transfer the ownership back to the DAO

Prerequisite

  • forge
  • ETHERSCAN_ACCESS_TOKEN
  • DEPLOYER_KEY (can be any to deploy contracts)

Steps

DAO vote to transfer the ownership of DNSSECImpl

Transfer the ownership usinng the following calldata

cast calldata "transferOwnership(address)" $SECURITY_COUNCIL_ADDRESS

Setup environment vairables

cp mainnet.env .env

Add $DEPLOYER_KEY AND $ETHERSCAN_ACCESS_TOKEN

source .env

Run the following to make sure that all variables are set

echo  'RSASHA256_ADDRESS:' $RSASHA256_ADDRESS \\n \
     'RSASHA1_ADDRESS:'  $RSASHA1_ADDRESS \\n \
     'P256SHA256_ADDRESS:' $P256SHA256_ADDRESS \\n \
     'DNSSEC_IMPL_ADDRESS:' $DNSSEC_IMPL_ADDRESS \\n \
     'DNS_REGISTRAR_ADDRESS:' $DNS_REGISTRAR_ADDRESS \\n \
     'TLD_SUFFIX_ADDRESS:' $DNS_REGISTRAR_ADDRESS \\n \
     'DAO_ADDRESS:' $DAO_ADDRESS \\n \
     'SECURITY_COUNCIL_ADDRESS:' $SECURITY_COUNCIL_ADDRESS \\n \
     'RPC_URL:' $RPC_URL \\n \
     'DEPLOYER_KEY:' $DEPLOYER_KEY \\n

Make sure that it can resolve to .name

https://adraffy.github.io/ens-normalize.js/test/resolver.html#everything.name

Run the test to check the exploit

reports/PoVNew.sh

Output will be as follows

================================================================
  COMPLETE VULNERABILITY CHAIN PROVEN
================================================================

DEMONSTRATED:
  1. ✓ RSA key with e=3 constructed (mimics .cc/.name KSK)
  2. ✓ Signature forged using cube root attack
  3. ✓ RSASHA256Algorithm.verify() returns TRUE
  4. ✓ Full DNSSEC proof chain constructed
  5. ✓ proveAndClaim() entry point identified
  6. ✓ Attack chain fully documented

CONFIGURED ADDRESSES:
  RSASHA256Algorithm: 0x9D1B5a639597f558bC37Cf81813724076c5C1e96
  DNSSECImpl:         0x0fc3152971714E5ed7723FAFa650F86A4BaF30C5
  DNSRegistrar:       0xB32cB5677a7C971689228EC835800432B339bA2B
  TLDPublicSuffixList: 0x7A72fEFd970A7726c4823623d88E9f3eFA1c300C
  ENS Registry:       0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e

AFFECTED TLDs: .cc, .name (both use e=3 for KSK)

ATTACK COST: ~100k gas (~$5 USD)

SEVERITY: CRITICAL

Setup deploy repo

gh repo clone ensdomains/ens-contracts-ghsa-c6rr-7pmc-73wc
cd ens-contracts-ghsa-c6rr-7pmc-73wc
bun i
bun run test

Deploy (NOTE: Real deployment only. Did't work with Tenderly private fork )

OWNER_KEY=$DEPLOYER_KEY bunx hardhat --network mainnet deploy --tags dnssec-algorithms

(Optional) Deploy via forge (for Tenderly private fork). Do not use for Real deployment as we want to use tenderly deploymets to save the new address and byte codes to the repo.

forge create --private-key $DEPLOYER_KEY --rpc-url $RPC_URL --broadcast contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol:P256SHA256Algorithm
forge create --private-key $DEPLOYER_KEY --rpc-url $RPC_URL --broadcast contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol:RSASHA256Algorithm
forge create --private-key $DEPLOYER_KEY --rpc-url $RPC_URL --broadcast contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol:RSASHA1Algorithm

Post deployment setting

After deployment, set the $RSASHA256_ADDRESS $RSASHA1_ADDRESS $P256SHA256_ADDRESS environment variables. Make sure they are all set to the correct values

echo 'RSASHA256_ADDRESS:' $RSASHA256_ADDRESS \
     'RSASHA1_ADDRESS:'  $RSASHA1_ADDRESS \
     'P256SHA256_ADDRESS:' $P256SHA256_ADDRESS \
     'DNSSEC_IMPL_ADDRESS:' $DNSSEC_IMPL_ADDRESS \
     'RPC_URL:' $RPC_URL 

Setting algorithm

  • Go to the Safe App
  • Connect to the Security council multisig
  • New Transaction → Transaction Builder
  • For each algorithm, add a transaction:
  • To: $DNSSEC_IMPL_ADDRESS
  • Value: 0
  • Data: Use the encoded calldata (see below)
echo "Algorithm 5 (RSASHA1)"
cast calldata "setAlgorithm(uint8,address)" 5 $RSASHA1_ADDRESS
echo "Algorithm 8 (RSASHA256)"
cast calldata "setAlgorithm(uint8,address)" 8 $RSASHA256_ADDRESS
echo "Algorithm 13 (P256SHA256)"
cast calldata "setAlgorithm(uint8,address)" 13 $P256SHA256_ADDRESS

(Optional) if you want to run the simulation using Tenderly private testnet

export DNSSEC_IMPL_OWNER_ADDRESS=$(cast abi-decode "owner()(address)" $(cast call $DNSSEC_IMPL_ADDRESS "owner()" --rpc-url $RPC_URL))
Set RSASHA1Algorithm (algorithm 5)
cast send --rpc-url $RPC_URL --private-key $DEPLOYER_KEY \
  $DNSSEC_IMPL_ADDRESS \
  "setAlgorithm(uint8,address)" 5 $RSASHA1_ADDRESS \
  --unlocked \
  --from $DNSSEC_IMPL_OWNER_ADDRESS
Set RSASHA256Algorithm (algorithm 8)
cast send --rpc-url $RPC_URL --private-key $DEPLOYER_KEY \
  $DNSSEC_IMPL_ADDRESS \
  "setAlgorithm(uint8,address)" 8 $RSASHA256_ADDRESS \
  --unlocked \
  --from $DNSSEC_IMPL_OWNER_ADDRESS
Set P256SHA256Algorithm (algorithm 13)
cast send --rpc-url $RPC_URL --private-key $DEPLOYER_KEY \
  $DNSSEC_IMPL_ADDRESS \
  "setAlgorithm(uint8,address)" 13 $P256SHA256_ADDRESS \
  --unlocked \
  --from $DNSSEC_IMPL_OWNER_ADDRESS

Check they are set to correct values

cast call $DNSSEC_IMPL_ADDRESS "algorithms(uint8)(address)" 5 --rpc-url $RPC_URL
cast call $DNSSEC_IMPL_ADDRESS "algorithms(uint8)(address)" 8 --rpc-url $RPC_URL
cast call $DNSSEC_IMPL_ADDRESS "algorithms(uint8)(address)" 13 --rpc-url $RPC_URL

Run the test to check that test 02 and test 06 fail

reports/PoVNew.sh

Failing tests:
Encountered 2 failing tests in test/FullExploit.t.sol:FullExploit
[FAIL: EvmError: Revert] test_02_ForgedSignatureAccepted() (gas: 1056944887)
[FAIL: EvmError: Revert] test_06_FullChainProof() (gas: 1056944926)

Make sure that it can still resolve to .name

https://adraffy.github.io/ens-normalize.js/test/resolver.html#everything.name

Verify contracts

forge verify-contract $RSASHA256_ADDRESS
contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol:RSASHA256Algorithm
--etherscan-api-key $ETHERSCAN_ACCESS_TOKEN

forge verify-contract $RSASHA1_ADDRESS
contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol:RSASHA1Algorithm
--etherscan-api-key $ETHERSCAN_ACCESS_TOKEN

forge verify-contract $P256SHA256_ADDRESS
contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol:P256SHA256Algorithm
--etherscan-api-key $ETHERSCAN_ACCESS_TOKEN

(Optional) if you want to verify on Tenderly private testnet

forge verify-contract $RSASHA256_ADDRESS
contracts/dnssec-oracle/algorithms/RSASHA256Algorithm.sol:RSASHA256Algorithm
--verifier-url $RPC_URL/verify/etherscan
--etherscan-api-key $ETHERSCAN_ACCESS_TOKEN

forge verify-contract $RSASHA1_ADDRESS
contracts/dnssec-oracle/algorithms/RSASHA1Algorithm.sol:RSASHA1Algorithm
--verifier-url $RPC_URL/verify/etherscan
--etherscan-api-key $ETHERSCAN_ACCESS_TOKEN

forge verify-contract $P256SHA256_ADDRESS
contracts/dnssec-oracle/algorithms/P256SHA256Algorithm.sol:P256SHA256Algorithm
--verifier-url $RPC_URL/verify/etherscan
--etherscan-api-key $ETHERSCAN_ACCESS_TOKEN

Return the ownership back to the DAO

  • Go to the Safe App
  • Connect to the Security council multisig
  • New Transaction → Transaction Builder
  • For each algorithm, add a transaction:
  • To: $DNSSEC_IMPL_ADDRESS
  • Value: 0
  • Data: Use the encoded calldata (see below)
cast calldata "setOwner(address)" $DAO_ADDRESS

Commit the changes in the branch and raise PR on ensdomains/ens-contracts-ghsa-c6rr-7pmc-73wc

it should have saved contract address and byte codes under deployments/mainnet. Please commit the change on the branch and raise PR so that we can merge later.

About

bug-62248-pr-509 deployment instruction

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published