-
Notifications
You must be signed in to change notification settings - Fork 725
[Script] Fix "split P2CS" vulnerability #2258
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
[Script] Fix "split P2CS" vulnerability #2258
Conversation
eb6d44b to
14d3956
Compare
|
Rebased on top of #2269 , and added a contextual flag to guard the new rules before v6 activation. |
06ac6e2 to
01d4cd5
Compare
|
Rebased on master. Ready for review. |
01d4cd5 to
8298ed5
Compare
The validation for P2CS scriptPubKey is incomplete and doesn't check all the opcodes. This opens a vulnerability. A script could be crafted so that: * it is identified as P2CS (passing IsPayToColdStaking), and recognized by the wallet as ISMINE_SPENDABLE_DELEGATED. * the assumed owner is not actually the owner (or not the only one) of the coins. In this Proof of concept, we craft a script that is recognized as own P2CS by the owner wallet, but can actually be spent with **any** key. This is achieved by including OP_DROP in a strategic position, so that, during the script evaluation, part of the locking condition (included only to fake IsPayToColdStaking) is removed, and replaced by a new condition embedded in the spending scriptSig.
Ensure stack consistency (size, signature and pubkey encoding) during evaluation
check the whole script template (leave only the 20 bytes for the staker keyID and 20 for the owner keyID).
8298ed5 to
c8502bf
Compare
furszy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK c8502bf
Fuzzbawls
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK c8502bf
4a5baf3 [Doc] Add cold-staking changes to release notes (random-zebra) c19416f [GUI] Use new opcode for P2CS after v6 enforcement (random-zebra) 45ebfee [RPC] Use new opcode for P2CS after v6 enforcement (random-zebra) 8eefab5 [Tests] Add script test for new opcode (random-zebra) df11631 [Script] Introduce new OP_CHECKCOLDSTAKEVERIFY opcode (random-zebra) b194386 [Refactor] Rename CCSV opcode to OP_CHECKCOLDSTAKEVERIFY_LOF (random-zebra) Pull request description: Extracted from #2267, and rebased on top of #2258. Given the consensus change, introduced in #2274, we can define a more secure `OP_CHECKCOLDSTAKEVERIFY` opcode, which doesn't leave the last output of the coinstake "free" (as we no longer pay masternode/budgets in the coinstake tx). Built on top of: - [x] #2258 - [x] #2274 ACKs for top commit: Fuzzbawls: re-Code ACK 4a5baf3 after rebase, no code changes. furszy: ACK 4a5baf3. Tree-SHA512: ee78b76137e40df05b854f8959755f1b99e7c7328fb13708ba7e3e6dae6357450210ce19ed7a99dc54aa0d6051d0dbd745af70f4b6e9927de5d3cbb2e04fffb6
>>> Backports dced6c0 (PIVX-Project#2258) The validation for P2CS scriptPubKey is incomplete and doesn't check all the opcodes. This opens a vulnerability. A script could be crafted so that: * it is identified as P2CS (passing IsPayToColdStaking), and recognized by the wallet as ISMINE_SPENDABLE_DELEGATED. * the assumed owner is not actually the owner (or not the only one) of the coins. In this Proof of concept, we craft a script that is recognized as own P2CS by the owner wallet, but can actually be spent with **any** key. This is achieved by including OP_DROP in a strategic position, so that, during the script evaluation, part of the locking condition (included only to fake IsPayToColdStaking) is removed, and replaced by a new condition embedded in the spending scriptSig.
>>> Backports 889a9e7 (PIVX-Project#2258) Ensure stack consistency (size, signature and pubkey encoding) during evaluation
>>> Backports 74bc415 (PIVX-Project#2258) check the whole script template (leave only the 20 bytes for the staker keyID and 20 for the owner keyID).
62bf095 [Consensus] use v5.2 params to guard new cold-staking rules (random-zebra) 5358c50 [Refactor] Move stack check inside CheckColdStake (random-zebra) 7bec531 [Consensus] Introduce V5.2 network-upgrade params (random-zebra) fecbb4a [Script] Strict test for IsPayToColdStaking (random-zebra) 84ed2d4 [Script] Strict checks for OP_CHECKCOLDSTAKEVERIFY (random-zebra) 9531fb8 [Tests] Proof of concept for P2CS vulnerability (random-zebra) Pull request description: Backports #2258 and #2428 ACKs for top commit: furszy: re code-ACK 62bf095 Fuzzbawls: utACK 62bf095 Tree-SHA512: 97e155f9fd84e8362f1a07ab1dd91216378f451dc3a0e756e543dfa31e37a8d53e3ffd90e2e8d67ee5e4d3a7f0fbcbd6118eaaaea7677c9682cea4c8f5e941bf
This PR is the result of a responsible disclosure for a vulnerability, related to the cold-staking code, made by Flowzzz (of https://keyboardwarrior.be/), on March 15th. After the initial discussion and analysis, along with @furszy and Flowzzz, a critical exploit has been identified and unit-tested.
For this report and collaboration, PIVX has granted the biggest bounty reward of its history (https://twitter.com/_PIVX/status/1372032360636502019).
This PR contains the PoC unit-test, used to reproduce the exploit, and the successive fix.
Problem
The validation for P2CS scriptPubKey is incomplete and doesn't check all the opcodes.
This opens up a possible exploit. A script could be crafted so that:
IsPayToColdStaking), and recognized by the wallet asSPENDABLE_DELEGATEDismine-type.In this Proof of concept, we craft a script that is recognized as own P2CS by the owner wallet, but can actually be spent with any key.
This is achieved by including
OP_DROPin a strategic position, so that, during the script evaluation, part of the locking condition (included only to fake IsPayToColdStaking) is removed, and replaced by a new condition embedded in the spending scriptSig.Fix
IsPayToColdStakingcheck that the script matches exactly the expected template (51 bytes, with 11 fixed bytes, and the remaining 40 for the two keyIDs). This patches the discovered exploit.OP_CHECKCOLDSTAKEVERIFYinEvalScript(at this point of evaluation, the stack must contain only the pubkeyID, the pubkey, and the signature, properly encoded).