pset: check commitment lengths before FFI parsing - #295
Open
ethicnology wants to merge 1 commit into
Open
Conversation
The PSET input fields `issuance_value_comm` and `issuance_inflation_keys_comm`, and the output fields `amount_comm` and `asset_comm`, deserialize attacker-controlled byte strings via `PedersenCommitment::from_slice` and `Generator::from_slice`. Those wrap FFI functions that take no length argument and unconditionally read 33 bytes from the slice pointer. An empty or short value therefore triggers an out-of-bounds read; on an empty value the dangling pointer (address 0x1) is dereferenced and the process segfaults instead of returning an error. Found by libFuzzer/AddressSanitizer on the `deserialize_pset` target: SEGV on unknown address 0x1, read access. Reproduced on 0.25.3, 0.26.2 and master. Reject any length other than 33 bytes at the PSET deserialization boundary, before reaching FFI. Add regression tests for empty, short and invalid-content inputs, plus the minimized fuzz artifact. The same missing length check exists in the safe `secp256k1-zkp` wrappers themselves; to be reported separately upstream.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The PSET input fields
issuance_value_commandissuance_inflation_keys_comm, and the output fieldsamount_commandasset_comm, deserialize attacker-controlled byte strings viaPedersenCommitment::from_sliceandGenerator::from_slice. Those wrap FFI functions (secp256k1_pedersen_commitment_parse,secp256k1_generator_parse) that take no length argument and unconditionally read 33 bytes from the slice pointer. An empty or short value therefore triggers an out-of-bounds read; on an empty value the dangling pointer (address 0x1) is dereferenced and the process segfaults instead of returning an error.Found by libFuzzer/AddressSanitizer on the
deserialize_psettarget: SEGV on unknown address 0x1, read access, zero page. Reproduced on 0.25.3, 0.26.2 and current master (8765552). Any application parsing untrusted PSETs (wallets, signing or watch-only services) can be crashed by a malicious PSET: denial of service. The faulting access is a fixed read at 0x1; we did not assess further exploitability.Reject any length other than 33 bytes at the PSET deserialization boundary, before reaching FFI. Adds regression tests for empty, short and invalid-content inputs, plus the minimized 397-byte fuzz artifact. The full test suite passes (160 tests) and a 6.3M-execution ASan run of
deserialize_psetwith the fix found no further crash.The same missing length check exists in the safe
secp256k1-zkp::zkpwrappers themselves (PedersenCommitment::from_slice,Generator::from_slice); to be reported separately to BlockstreamResearch/rust-secp256k1-zkp.