Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Signature Replay attack on re-created smart accounts #472

Open
code423n4 opened this issue Jan 9, 2023 · 8 comments
Open

Signature Replay attack on re-created smart accounts #472

code423n4 opened this issue Jan 9, 2023 · 8 comments
Labels
bug Something isn't working disagree with severity Sponsor confirms validity, but disagrees with warden’s risk assessment (sponsor explain in comments) downgraded by judge Judge downgraded the risk level of this issue duplicate-127 grade-b Q-06 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue

Comments

@code423n4
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2023-01-biconomy/blob/main/scw-contracts/contracts/smart-contract-wallet/BaseSmartAccount.sol#L12-L18

Vulnerability details

Signature Replay attack on re-created smart accounts

Impact

User's can loose funds or any unexpected behaviour can occur that transaction replay attacks usually lead to.

Proof of Concept

Consider the case when someone decides they want to destroy their smart account for some reason. Since the smart contract (account) is created from the factory using the create2 opcode from, users are able to re-deploy their smart contract account again after a self-destruct. The problem comes from that after a selfdestruct operation, all the smart contract`s storage is gone. That means if user re-creates their smart contract account, the nonces mapping will be deleted. This will give the opportunity for any external malicious account to replay already passed transaction as the contract owner is the same and the nonces counting restart from 0.

Consider the following example:

  1. Alice creates a SmartAccount proxy using the SmartAccountFactory.deployCounterFactualWallet with the following args:
    _owner: address(0xabababababababababababababababababababab)
    _entryPoint: address(0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd)
    _handler: address(0xefefefefefefefefefefefefefefefefefefefef)
    _index: 0
  2. Alice deposit 10 ETH to her smart contract account
  3. Alice transfers the deposited 10 ETH to Bob (this is her first transaction, so the nonce=0)
  4. At some point Alice decides she want to temporaly delete her account
  5. After a few days Alice wants to create a smart contract account with the same address as the previous one
  6. She calls SmartAccountFactory.deployCounterFactualWallet with the same args from 1.
  7. Alice assumes that she is starting to use this account from scratch as it is absolutely clear
  8. Alice deposits 10 ETH again and hodls
  9. Bob notices what Alice has done and decides to replay the first transaction Alice has executed (and signed) for her previous account
  10. Her first transaction was exactly sending 10 ETH to Bob
  11. As the nonce of the previous first transaction was 0 and the current nonce in the re-created account is also 0, Bob can execute this transaction and steal Alice's 10 ETH

NOTE: Although the domainSeparator is used to calculate the account transaction hash, this doesn't prevent the signature replay as the verifyingContract (address(this)) is the same in both the old smart contract account (the selfdestructed one) and the new one.

Tools Used

Manual review

Recommended Mitigation Steps

Add expirationTime propery in the Transaction struct and check against block.timestamp in SmartAccount.execTransaction.

struct Transaction {
        address to;
        uint256 value;
        bytes data;
        Enum.Operation operation;
        uint256 targetTxGas;
	uint256 expirationTime // @audit add expiration time to prevent replay attack on re-created smart contract
    }
@code423n4 code423n4 added 3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working labels Jan 9, 2023
code423n4 added a commit that referenced this issue Jan 9, 2023
@c4-judge
Copy link
Contributor

gzeon-c4 marked the issue as duplicate of #127

@c4-sponsor
Copy link

livingrockrises marked the issue as disagree with severity

@c4-sponsor c4-sponsor added the disagree with severity Sponsor confirms validity, but disagrees with warden’s risk assessment (sponsor explain in comments) label Jan 26, 2023
@c4-sponsor
Copy link

livingrockrises marked the issue as sponsor disputed

@c4-sponsor c4-sponsor added the sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue label Jan 26, 2023
@livingrockrises
Copy link

explain delete account and recreated smart account

@c4-judge c4-judge added downgraded by judge Judge downgraded the risk level of this issue QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax and removed 3 (High Risk) Assets can be stolen/lost/compromised directly labels Feb 10, 2023
@c4-judge
Copy link
Contributor

gzeon-c4 changed the severity to QA (Quality Assurance)

@c4-judge
Copy link
Contributor

gzeon-c4 marked the issue as grade-b

@GeorgeHNTR
Copy link

GeorgeHNTR commented Feb 12, 2023

explain delete account and recreated smart account

Sorry for not describing it better and providing a PoC in code, I was running out of time:

delete account = call selfdestruct via delegatecall for the SmartAccount contract proxy
recreated smart account = re-deployed SmartAccount contract proxy on the same address (using create2) after selfdestruct()

I think this is a valid finding of medium severity according to C4's severity criteria leak value with a hypothetical attack path with stated assumptions

@gzeon-c4
Copy link

The risk is low because the smart account being self-destructed and later funded with value is very unlikely to happen.

@C4-Staff C4-Staff reopened this Feb 15, 2023
@C4-Staff C4-Staff added the Q-06 label Feb 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working disagree with severity Sponsor confirms validity, but disagrees with warden’s risk assessment (sponsor explain in comments) downgraded by judge Judge downgraded the risk level of this issue duplicate-127 grade-b Q-06 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue
Projects
None yet
Development

No branches or pull requests

7 participants