-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
[sdk] Add a length restriction on poseidon hash input #33363
[sdk] Add a length restriction on poseidon hash input #33363
Conversation
Codecov Report
@@ Coverage Diff @@
## master #33363 +/- ##
=======================================
Coverage 81.9% 81.9%
=======================================
Files 798 798
Lines 216579 216581 +2
=======================================
+ Hits 177481 177513 +32
+ Misses 39098 39068 -30 |
@vadorovsky, can you double check if my reasoning is correct here? Thanks! |
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.
I think it's an unnecessary change? Do you have an actual reproducer which hijacks the syscall (some input which is too large and is considered as valid)?
light-poseidon already has a necessary check for each input, which also instead of hard coding a specific value (like 32
), it counts the byte limit for the modulus of the prime field, so it is able to handle other elliptic curves or prime fields without having to hard code any new values:
We even have tests with too large inputs:
In case you have any reproducer, then I think we should rather fix light-poseidon - the library itself should be secure and handle all the checks, instead offloading them to the callers.
The only reason why I did an explicit check on the number of slice inputs in Solana is to be able to calculate the compute cost.
This is not an issue about whether the bytes are correctly parsed as valid field elements or not, but whether the assigned compute units correctly capture the compute costs to evaluate the hash function. Correct me if I am misunderstanding the flow of the code, but if we evaluate the hash function with So imagine a really long input like in your test. The computation could be correct in that it returns The bench code that was used to assign CU's fixes the inputs at 32 bytes. We should make sure that the CU's are still accurate for inputs that are much larger than 32 bytes. Let me know what you think. It could be that I am missing something, but we really want to be sure for these type of things that could potentially lead to ddos. |
Submitting too large inputs might be a potential DDoS attack vector. Before this change, `hash_bytes_be` was reversing all input byte slices before validating them (to convert them from big-endian to little-endian), so it was prone to an attack, where a malicious user could submit arrays just to DDoS the software using light-poseidon with heavy reversal operations. Fix that by performing validation as the first operation on byte inputs. Kudos to @samkim-crypto for finding the issue. Ref: solana-labs/solana#33363
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.
@samkim-crypto OK, I understand now. Thanks for clear explanation!
This PR looks good to me, thanks for spotting the issue! I think it makes sense to merge this PR.
At the same time, I submitted a fix: Lightprotocol/light-poseidon#32, which performs the validation before the big-endian array is inverted. In the long-term, we might also want to bump light-poseidon once the fix lands there too and we make a new release.
Submitting too large inputs might be a potential DDoS attack vector. Before this change, `hash_bytes_be` was reversing all input byte slices before validating them (to convert them from big-endian to little-endian), so it was prone to an attack, where a malicious user could submit arrays just to DDoS the software using light-poseidon with heavy reversal operations. Also, remove the `fuzz-tests` flag and run all tests by default. After this fix, the runtime of fuzz tests is fast. Its degradation is actually an indicator of performance issues or DDoS attack vectors. Fix that by performing validation as the first operation on byte inputs. Kudos to @samkim-crypto for finding the issue. Ref: solana-labs/solana#33363
Submitting too large inputs might be a potential DDoS attack vector. Before this change, `hash_bytes_be` was reversing all input byte slices before validating them (to convert them from big-endian to little-endian), so it was prone to an attack, where a malicious user could submit arrays just to DDoS the software using light-poseidon with heavy reversal operations. Also, remove the `fuzz-tests` flag and run all tests by default. After this fix, the runtime of fuzz tests is fast. Its degradation is actually an indicator of performance issues or DDoS attack vectors. Fix that by performing validation as the first operation on byte inputs. Kudos to @samkim-crypto for finding the issue. Ref: solana-labs/solana#33363
Submitting too large inputs might be a potential DDoS attack vector. Before this change, `hash_bytes_be` was reversing all input byte slices before validating them (to convert them from big-endian to little-endian), so it was prone to an attack, where a malicious user could submit arrays just to DDoS the software using light-poseidon with heavy reversal operations. Also, remove the `fuzz-tests` flag and run all tests by default. After this fix, the runtime of fuzz tests is fast. Its degradation is actually an indicator of performance issues or DDoS attack vectors. Fix that by performing validation as the first operation on byte inputs. Kudos to @samkim-crypto for finding the issue. Ref: solana-labs/solana#33363
That new release contains an important change which prevents a potential DDoS. * Lightprotocol/light-poseidon#32 Invoking `from_bytes_be` function light-poseidon 0.1.1 inverts all the inputs before performing a check whether their length exceeds the modulus of the prime field. Therefore, it was prone to an attack, where a mailicious user could submit long byte slices just to DDoS the validator, being stuck on inverting large byte sequences. The update and mentioned change fixes the same issue as #33363 aims to address. The new release contains also few other less important changes like: * Lightprotocol/light-poseidon#37 * Lightprotocol/light-poseidon#38 * Lightprotocol/light-poseidon#39
@samkim-crypto #33923 is merged, should we close this PR? |
Yep, closing. Thanks! |
That new release contains an important change which prevents a potential DDoS. * Lightprotocol/light-poseidon#32 Invoking `from_bytes_be` function light-poseidon 0.1.1 inverts all the inputs before performing a check whether their length exceeds the modulus of the prime field. Therefore, it was prone to an attack, where a mailicious user could submit long byte slices just to DDoS the validator, being stuck on inverting large byte sequences. The update and mentioned change fixes the same issue as #33363 aims to address. The new release contains also few other less important changes like: * Lightprotocol/light-poseidon#37 * Lightprotocol/light-poseidon#38 * Lightprotocol/light-poseidon#39 (cherry picked from commit 67f8daf) # Conflicts: # Cargo.lock # Cargo.toml # programs/sbf/Cargo.lock
That new release contains an important change which prevents a potential DDoS. * Lightprotocol/light-poseidon#32 Invoking `from_bytes_be` function light-poseidon 0.1.1 inverts all the inputs before performing a check whether their length exceeds the modulus of the prime field. Therefore, it was prone to an attack, where a mailicious user could submit long byte slices just to DDoS the validator, being stuck on inverting large byte sequences. The update and mentioned change fixes the same issue as #33363 aims to address. The new release contains also few other less important changes like: * Lightprotocol/light-poseidon#37 * Lightprotocol/light-poseidon#38 * Lightprotocol/light-poseidon#39 (cherry picked from commit 67f8daf)
…4247) chore: Update light-poseidon to 0.2.0 (#33923) That new release contains an important change which prevents a potential DDoS. * Lightprotocol/light-poseidon#32 Invoking `from_bytes_be` function light-poseidon 0.1.1 inverts all the inputs before performing a check whether their length exceeds the modulus of the prime field. Therefore, it was prone to an attack, where a mailicious user could submit long byte slices just to DDoS the validator, being stuck on inverting large byte sequences. The update and mentioned change fixes the same issue as #33363 aims to address. The new release contains also few other less important changes like: * Lightprotocol/light-poseidon#37 * Lightprotocol/light-poseidon#38 * Lightprotocol/light-poseidon#39 (cherry picked from commit 67f8daf) Co-authored-by: vadorovsky <[email protected]>
Problem
The newly added poseidon hash syscall (#32680) performs a length check on the number of slice inputs to the function (here) but not on the length of the slice. The assigned compute units for the hash function is also independent of the length of the slice inputs.
Consider invoking the poseidon hash syscall on a very long input. If the function is invoked in the
LittleEndian
setting, then this is fine since the slices will immediately fail to be converted to a valid field element (here).However, if the function is invoked in the
BigEndian
setting, then the bytes are reversed (here) before they are converted into a field element, which takesO(n)
time. This creates a risk for potential ddos since the compute units do not account for this linear time operation.Summary of Changes
Added a length check on the input slices before the hash function is invoked.
Fixes #