-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Context
User "Sytten" on Discord brought to our attention the following presentation from this year's DEFCON: https://media.defcon.org/DEF%20CON%2032/DEF%20CON%2032%20presentations/DEF%20CON%2032%20-%20Paul%20Gerste%20-%20SQL%20Injection%20Isn't%20Dead%20Smuggling%20Queries%20at%20the%20Protocol%20Level.pdf
(Note: if there's a public page or blog post for this, or one is posted in the future, please let me know so I can include it for posterity.)
Essentially, encoding a value larger than 4GiB can cause the length prefix in the protocol to overflow, causing the server to interpret the rest of the string as binary protocol commands (or other data? it's not clear):
It appears SQLx does perform truncating casts in a way that could be problematic, for example:
sqlx/sqlx-postgres/src/arguments.rs
Line 163 in 6f29056
(self.len() - offset - 4) as i32 |
This code has existed essentially since the beginning, so it is reasonable to assume that all published versions are affected.
It's hard to glean just from the slides exactly how this may be exploited, and in any case it requires a malicious input at least 4 GiB long.
Mitigation
As always, you should make sure your application is validating untrustworthy user input. Reject any input over 4 GiB, or any input that could encode to a string longer than 4 GiB. Dynamically built queries are also potentially problematic if it pushes the message size over this 4 GiB bound.
Encode::size_hint()
can be used for sanity checks, but do not assume that the size returned is accurate. For example, the Json<T>
and Text<T>
adapters have no reasonable way to predict or estimate the final encoded size, so they just return size_of::<T>()
instead.
For web application backends, consider adding some middleware that limits the size of request bodies by default.
Resolution
I have started work on a branch that adds #[deny]
directives for the following Clippy lints:
and I'm auditing the code that they flag. This is the same approach being used by Diesel: diesel-rs/diesel#4170
In the process I realized that our CI wasn't running a lot of our unit tests, so I'm fixing that as well.
After the fix, attempting to encode a value larger than is allowed in a given binary protocol will return an error instead of silently truncating it.
I will also be filing a RUSTSEC advisory.