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

Test behavior of SignatureChecker against the identity precompile (0x4) #5501

Conversation

Amxx
Copy link
Collaborator

@Amxx Amxx commented Feb 12, 2025

The identity precompiles, at address 0x4, is potentially dangerous when targeted by ERC1271 checks. The returned bytes contains starts with the function selector, which is exaclty the 4 bytes that are expected.

The current implementation (as of 5.2) checks the that the first 32 bytes of the returned value contain the selector followed by 28 bytes of zeros. This is what a valid ERC-1271 wallet would return when the call is successfull.

In the case of the identity precompile, the first 32 bytes of the returned value contain the selector followed by the first 28 bytes of the hash being verified. That means that unless the first 28 bytes of the hash are all zero, the precompile issue will not affect this library.

I real-life applications, the hash is actually the return of a hashing function. As a consequence, having 28 bytes of zeros is basically impossible, and the implmentation is not vulnerable.

However we cannot rule the case where some application decides the use a hash that is not an ERC-191 or ERC-712 hash, and is not produced by a hashing function. For this extermelly unlikelly case, we add an additional check that signer is not address(0x4).

PR Checklist

  • Tests
  • Documentation
  • Changeset entry (run npx changeset add)

signer when hash starts with 28 zero bytes.
@Amxx Amxx added this to the 5.3 milestone Feb 12, 2025
@Amxx Amxx requested review from arr00 and ernestognw February 12, 2025 14:08
Copy link

changeset-bot bot commented Feb 12, 2025

⚠️ No Changeset found

Latest commit: f92d6d1

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

arr00
arr00 previously approved these changes Feb 12, 2025
@arr00
Copy link
Contributor

arr00 commented Feb 12, 2025

Need to update the commit message

@Amxx Amxx changed the title SignatureChecker: improve handling of the identity precompile as a signer when hash starts with 28 zero bytes. SignatureChecker: test behavior against the identity precompile (0x4) Feb 12, 2025
@Amxx Amxx changed the title SignatureChecker: test behavior against the identity precompile (0x4) Test behavior of SignatureChecker against the identity precompile (0x4) Feb 13, 2025
@Amxx Amxx enabled auto-merge (squash) February 13, 2025 10:29
@Amxx Amxx merged commit dbd9805 into OpenZeppelin:master Feb 13, 2025
20 of 21 checks passed
@Amxx Amxx deleted the feature/isValidERC1271SignatureNow-identity-precompile branch February 13, 2025 15:36
@pcaversaccio
Copy link
Contributor

I have a question @Amxx; you write here:

However we cannot rule the case where some application decides the use a hash that is not an ERC-191 or ERC-712 hash, and is not produced by a hashing function. For this extermelly unlikelly case, we add an additional check that signer is not address(0x4).

But I can't see any added checks in the Solidity implementation of this PR?

@Amxx
Copy link
Collaborator Author

Amxx commented Feb 13, 2025

It's was decided against it for a few reasons:

  • we expect almost all usage will be on the isValidSignature now function, which is not affected
  • we expect the hash to always be produced by a hashing function
  • even if both are not true, we feel like having a valid signature for address 0x4 should not cause security issues. Address 0x4 should not have any permissions or hold any assets.

Overall, 99.99% of the usage are already safe and should not bear any extra cost. The remaining 0.01% are a combination of many things, one of which is bad application design.

Amxx added a commit to Amxx/openzeppelin-contracts that referenced this pull request Feb 14, 2025
@pcaversaccio
Copy link
Contributor

we expect almost all usage will be on the isValidSignature now function, which is not affected

Well, the identity precompile will become a predeploy with code probably soon in the future: https://eips.ethereum.org/EIPS/eip-7666. Thus the following line in isValidSignatureNow, will become false:

and isValidERC1271SignatureNow is called.

we expect the hash to always be produced by a hashing function

Fair.

@Amxx
Copy link
Collaborator Author

Amxx commented Feb 14, 2025

Wow, thanks for sharing eip-7666. That is one less "safeguard", but I'd say we likelly are still safe.

I'd really like to see a vulnerable application to better understand in what case 0x4 being a valid signer of something is an issue.

@pcaversaccio
Copy link
Contributor

pcaversaccio commented Feb 14, 2025

I'd really like to see a vulnerable application to better understand in what case 0x4 being a valid signer of something is an issue.

My issue here links to a recent hack due to inheriting the ERC-6492 reference implementation. That was the original trigger around this discussion.

@Amxx
Copy link
Collaborator Author

Amxx commented Feb 14, 2025

My issue here links to a recent hack due to inheriting the ERC-6492 reference implementation.

Thank you again for that !

Looking very quickly at https://pbs.twimg.com/media/GiByHVbacAAJQEX?format=jpg&name=4096x4096, I'm not sure I understand how 0x4 is involved here. If I was to deploy the ERC-7666 bytecode at any address that is NOT in the precompile range, using CREATE or CREATE2, and use that address instead of 0x4, wouldn't the vulnerability work just the same ? If 7666 goes through, I feel address 0x4 would be exactly the same as any such address (that has the same code deployed) ... so filterting address 0x4 (or even the range of precompile addresses) would not change anything, whould it?

EDIT: I'm partially wrong, with any other address, contractCodeLength would either not be 0, or it would have to be created by the arbitrary call. Why only "partially" wrong ? Well the arbitrary call could be malicious AND deploy the code as expected. For example, it could be an ERC-721, 1155, or 1363 "transfer with hook" and the hook would be able to deploy the fake signer. It would limit the range of calls that can be executed, but there would still be a vulnerability.

@pcaversaccio
Copy link
Contributor

Re the 0x4 involvement, you can see this here:

image

I mean, the vulnerability - as you correctly state - could also be exploited by any arbitrary contract returning 0x1626ba7e (generally speaking); he just chose to use the identity precompile here. So having the arbitrary call possibility in combination with ERC-6492 introduces this vulnerability. Since ERC-6492 uses ERC-1271 our natural reaction was to look into this as well. If you delegate verification to another contract (which is done by ERC-1271) this can't be arbitrary, otherwise you're rekt of course. The overall question is if there are protocols using ERC-1271 with the wrong assumptions, i.e. if you directly call a ERC-1271 wallet (i.e. without ECDSA verification) will a EOA address always return 0x only?

@Amxx
Copy link
Collaborator Author

Amxx commented Feb 14, 2025

IMO the actual good fix for that is to use a SenderCreator similar the one used in ERC-4337 EntryPoint

@pcaversaccio
Copy link
Contributor

Do you think it's worth linking this conversation or as a general code comment in the SignatureChecker contract?

@Amxx
Copy link
Collaborator Author

Amxx commented Feb 14, 2025

Do you think it's worth linking this conversation or as a general code comment in the SignatureChecker contract?

Maybe

Dargon789 added a commit to Dargon789/openzeppelin-contracts that referenced this pull request Feb 15, 2025
* Update ReentrancyGuardTransient documentation (OpenZeppelin#5417)

* Optimize `MerkleTree` for loops by using `uint256` iterators (OpenZeppelin#5415)

Co-authored-by: Ernesto García <[email protected]>

* Update `_revokeRole` documentation in AccessControl (OpenZeppelin#5321)

Co-authored-by: Ernesto García <[email protected]>

* Merge release-v5.2 branch (OpenZeppelin#5424)

Signed-off-by: Hadrien Croubois <[email protected]>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Hadrien Croubois <[email protected]>
Co-authored-by: Sam Bugs <[email protected]>
Co-authored-by: Ernesto García <[email protected]>
Co-authored-by: Arr00 <[email protected]>
Co-authored-by: wizard <[email protected]>
Co-authored-by: leopardracer <[email protected]>
Co-authored-by: cairo <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Francisco Giordano <[email protected]>
Co-authored-by: Simka <[email protected]>
Co-authored-by: Voronor <[email protected]>

* Add a Calldata library with `emptyBytes` and `emptyString` functions (OpenZeppelin#5422)

Co-authored-by: Ernesto García <[email protected]>

* Update governor docs (OpenZeppelin#5420)

* Add missing `Calldata`, `Bytes`, `CAIP2` and `CAIP10` API references (OpenZeppelin#5428)

* Expose `_isTrustedByTarget` internally in ERC2771Forwarder (OpenZeppelin#5416)

* Update LICENSE (OpenZeppelin#5434)

* Refactor EnumerableSet.behavior.js for reuse in the community repo (OpenZeppelin#5441)

* Replace `overriden` with `overridden` in GovernorCountingOverridable.sol (OpenZeppelin#5446)

Co-authored-by: Arr00 <[email protected]>
Co-authored-by: ernestognw <[email protected]>

* Remove Unnecessary Initialisation of `_paused` (OpenZeppelin#5448)

Co-authored-by: Ernesto García <[email protected]>

* Fix Broken Docs References (OpenZeppelin#5436)

* Update actions/upload-artifact action to v4 (OpenZeppelin#4826)

* Remove unused `setBaseURI` tests (OpenZeppelin#5456)

Co-authored-by: Hadrien Croubois <[email protected]>

* Group typographical errors (OpenZeppelin#5443)

Co-authored-by: futreall <[email protected]>
Co-authored-by: Marco <[email protected]>
Co-authored-by: Dmitry <[email protected]>
Co-authored-by: Dmytrol <[email protected]>
Co-authored-by: Noisy <[email protected]>
Co-authored-by: Danil <[email protected]>
Co-authored-by: CrazyFrog <[email protected]>
Co-authored-by: Bryer <[email protected]>
Co-authored-by: Viktor Pavlik <[email protected]>
Co-authored-by: Skylar Ray <[email protected]>
Co-authored-by: Brawn <[email protected]>
Co-authored-by: fuder.eth <[email protected]>
Co-authored-by: FT <[email protected]>
Co-authored-by: Ann Wagner <[email protected]>
Co-authored-by: Hopium <[email protected]>
Co-authored-by: Arr00 <[email protected]>
Co-authored-by: Hadrien Croubois <[email protected]>

* Fix interface docs ordering and add missing interface (OpenZeppelin#5460)

* Add a governor extension that implements a proposal guardian (OpenZeppelin#5303)

Co-authored-by: Arr00 <[email protected]>
Co-authored-by: Ernesto García <[email protected]>

* Fix the CLI output of formal verification runs (OpenZeppelin#5445)

* Update dependency halmos to v0.2.4 (OpenZeppelin#5461)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Use stable foundry version in CI (OpenZeppelin#5465)

* Add stake management function to ERC4337Utils (OpenZeppelin#5471)

* Add forum badge correct link (OpenZeppelin#5481)

* SafeERC20.trySafeTransfer{,from} (OpenZeppelin#5483)

* Improve promise rejections handling in hardhat/async-test-sanity.js (OpenZeppelin#5429)

Co-authored-by: Arr00 <[email protected]>

* Use slither v0.10.4 (OpenZeppelin#5488)

* Add ERC6909 Implementation along with extensions (OpenZeppelin#5394)

Co-authored-by: Hadrien Croubois <[email protected]>
Co-authored-by: Ernesto García <[email protected]>

* Rename ERC4337Utils ENTRYPOINT to ENTRYPOINT_V07 (OpenZeppelin#5472)

Co-authored-by: Hadrien Croubois <[email protected]>

* Add Bytes32x2Set (OpenZeppelin#5442)

Co-authored-by: Ernesto García <[email protected]>

* Add clear function to Enumerable{Set,Map} (OpenZeppelin#5486)

Co-authored-by: Hadrien Croubois <[email protected]>

* Make set-max-old-space-size.sh compatible with sh (OpenZeppelin#5493)

Co-authored-by: Hadrien Croubois <[email protected]>

* Update FUNDING.json (OpenZeppelin#5496)

Co-authored-by: Hadrien Croubois <[email protected]>

* Update FUNDING.json hierarchy (OpenZeppelin#5500)

Co-authored-by: Hadrien Croubois <[email protected]>

* Test behavior of SignatureChecker against the identity precompile (0x4) (OpenZeppelin#5501)

* Treat code-size warnings as errors (OpenZeppelin#5101)

Co-authored-by: Hadrien Croubois <[email protected]>

* Make `TimelockController` receive function virtual (OpenZeppelin#5506)

Co-authored-by: Arr00 <[email protected]>
Co-authored-by: Hadrien Croubois <[email protected]>

---------

Signed-off-by: Hadrien Croubois <[email protected]>
Co-authored-by: Ernesto García <[email protected]>
Co-authored-by: Michael <[email protected]>
Co-authored-by: Maks <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Hadrien Croubois <[email protected]>
Co-authored-by: Sam Bugs <[email protected]>
Co-authored-by: Arr00 <[email protected]>
Co-authored-by: wizard <[email protected]>
Co-authored-by: leopardracer <[email protected]>
Co-authored-by: cairo <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Francisco Giordano <[email protected]>
Co-authored-by: Simka <[email protected]>
Co-authored-by: Voronor <[email protected]>
Co-authored-by: Eric Lau <[email protected]>
Co-authored-by: planetBoy <[email protected]>
Co-authored-by: sudo rm -rf --no-preserve-root / <[email protected]>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Renan Souza <[email protected]>
Co-authored-by: futreall <[email protected]>
Co-authored-by: Marco <[email protected]>
Co-authored-by: Dmitry <[email protected]>
Co-authored-by: Dmytrol <[email protected]>
Co-authored-by: Noisy <[email protected]>
Co-authored-by: Danil <[email protected]>
Co-authored-by: CrazyFrog <[email protected]>
Co-authored-by: Bryer <[email protected]>
Co-authored-by: Viktor Pavlik <[email protected]>
Co-authored-by: Skylar Ray <[email protected]>
Co-authored-by: Brawn <[email protected]>
Co-authored-by: fuder.eth <[email protected]>
Co-authored-by: FT <[email protected]>
Co-authored-by: Ann Wagner <[email protected]>
Co-authored-by: Hopium <[email protected]>
Co-authored-by: Yan Victor SN <[email protected]>
Co-authored-by: Ursula <[email protected]>
Co-authored-by: Michalis Kargakis <[email protected]>
Co-authored-by: luca <[email protected]>
Co-authored-by: Jonas <[email protected]>
Co-authored-by: Joseph Delong <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants