Three valid signatures for the same message #13
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
H-06
primary issue
Highest quality submission among a set of duplicates
🤖_primary
AI based primary recommendation
🤖_67_group
AI based duplicate group recommendation
selected for report
This submission will be included/highlighted in the audit report
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/precompiles/ec_recover.cairo#L40
Vulnerability details
Impact
On Ethereum, it's possible to create two different valid signatures for the same message (known as ECDSA Signature Malleability). However, on Kakarot, you can create three different valid signatures for the same message. This happens because, on Ethereum, if the value of
s
is higher than the maximum valid range, it returnsaddress(0)
. On Kakarot, in this case, it returns a valid address.Proof of Concept
If
r
andv
are in the valid range, ands
is between1
andsecp256k1n
, theecrecover
function behaves the same on both Ethereum and Kakarot.s
is higher thansecp256k1n
, it returnsaddress(0)
.s
is higher thansecp256k1n
, it returns an address equivalent tos + secp256k1n
.Here's an example for better clarity. The
ecrecover
function for the following inputs will return the same result0x992FEaf0E360bffaeAcf57c28D2a3F5059Fe0982
:On Ethereum:
r = 1, v = 27, s = 2
r = 1, v = 28, s = secp256k1n - 2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F
On Kakarot:
r = 1, v = 27, s = 2
r = 1, v = 28, s = secp256k1n - 2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F
r = 1, v = 27, s = secp256k1n + 2 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364143
While inputs 1 and 2 behave as expected, input 3 highlights the problem. With input 3, Ethereum's
ecrecover
returnsaddress(0)
, but Kakarot returns the same result as input1 and input2.This shows that a malleability attack on Kakarot can be done in two ways, whereas on Ethereum, it can only be done in one.
In simple terms, on Ethereum, a malleability attack can be done by changing the
v
from27
to28
(or vice versa) and swappings
withsecp256k1n - s
:r, s, v
r, secp256k1n - s, v = {27 -> 28, 28 -> 27}
On Kakarot, the malleability attack can be done in two ways: either by changing
s
tosecp256k1n + s
(as long as it's not larger than2**256 - 1
) or using the same method as Ethereum by changing thev
and swappings
withsecp256k1n - s
:r, s, v
r, secp256k1n - s, v = {27 -> 28, 28 -> 27}
OR:
r, s, v
r, secp256k1n + s, v
The value of
s
needs to be limited in theec_recover::run
function to make sure it's within the valid range.https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/precompiles/ec_recover.cairo#L40
PoC
In the following test, three different combinations of
(r, s, v)
are provided as parameters to theecrecover
function, and the result for all of them is the same.To run the end-to-end tests correctly, the
make test-end-to-end14
command should be used, as defined in theMakefile
.The output log is:
Tools Used
Recommended Mitigation Steps
The following modifications are needed to constraint the valid range of
s
:https://github.com/kkrt-labs/kakarot/blob/7411a5520e8a00be6f5243a50c160e66ad285563/src/kakarot/precompiles/ec_recover.cairo#L40
Assessed type
Context
The text was updated successfully, but these errors were encountered: