## https://sploitus.com/exploit?id=03E19148-CFD3-58E7-8BBD-8AFF564305D4
# DNS SEC upgrade repo
## Summary
This repo contains the solution to address two issues.
- [feat: Replace EllipticCurve with EIP-7951 P-256 precompile for Algorithm 13](https://github.com/ensdomains/ens-contracts/pull/509)
- [RSA Signature Forgery via Missing PKCS#1 v1.5 Padding Validation in ENS DNSSEC Oracle](./reports/REPORT.md)
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](https://etherscan.io/address/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.