Commit Graph

29 Commits (fe939e8da7203bab461114e2258ad386e9346284)

Author SHA1 Message Date
Juliana Fajardini fe939e8da7 pgsql: better boundaries to row_description/data_row
parse_row_description and parse_consolidated_data_row read a field_count
from the message body and use that to iterate a slice, without checking
whether the count actually fits the body.

A backend-controlled attack could lead to fewer fields logged, or
stalling of the parser to-client direction for the duration of the flow.

A malformed_response event is set for pgsql, if either of those
message's inner parsers has a field_count that can't be reconciled with
the body slice.

A new pgsql.response log field is added to indicate this, too:
pgsql.response.row_description_malformed, a boolean. This wasn't added
to the consolidated data row message, per its summarization nature.

The row_description unit test buffer declared a length one byte longer
than its three fields occupy. The old code silently discarded that
surplus byte; the new one reports it, so the buffer was corrected.

Ticket: #8885
2 months ago
Juliana Fajardini 8b5fb9b044 pgsql: bound Copy responses to their length field
CopyIn and CopyOut message parsers read the length field, but did not
use that information to parse the rest of the message, instead, parsing
as many columns as indicated in the columns field, without ever
checking against the informed length. This opened the door for
attackers to fabricate messages that were never sent by the server,
as well as to obfuscate following valid backend messages, in case the
columns value was bigger than the actual message (up to ~128KiB).

Those parsers also had a message length parsing check off-by-one, fixed
in this patch.

When a malformed CopyIn or CopyOut response is seen, it is logged as
previously, with a new field added to indicate whether it is malformed
or not.

Ticket: #8863
2 months ago
Juliana Fajardini 88fdfb9d5a pgsql: debug validation on duplicated request msgs
There shouldn't be duplicated messages in the requests Vec. And thus
the parser shouldn't log duplicated keys nor messages. Add debug
validations to ensure this.

With PGSQL's current state machine, most frontend/ client messages will
lead to the creation of a new transaction - which would prevent
duplicated messages being pushed to the requests array and reaching the
logger.

The current exceptions for that are:

- CopyDataIn
- CopyDone
- CopyFail

Thus, debug statements were added for those cases.

CopyDone and CopyFail, per the documentation, shouldn't be seen
duplicated on the wire for the same transaction. CopyDataIn -- yes, but
we consolidate those, so the expectation is that they won't be
duplicated in the requests array or when reaching the logger either.

Related to
Task #7645
1 year ago
Juliana Fajardini f3aa0085a0 pgsql: rename copy in/out response field
We used `copy_column_count`, while just `columns` is more accurate with
what PostgreSQL describes, and what Wireshark shows.

Related to
Task #7644
Task #7645
1 year ago
Juliana Fajardini 2086f99d6b pgsql: add initial support to CopyIn mode/subproto
This sub-protocol inspects messages sent mainly from the frontend to
the backend after a 'COPY FROM STDIN' has been processed by the
backend.

Parses new messages:
- CopyInResponse -- initiates copy-in mode/sub-protocol
- CopyData (In) -- data transfer message, from frontend to backend
- CopyDone -- signals that no more CopyData messages will be seen from
  the frontend, for the current transaction
- CopyFail -- used by the frontend to signal some failure to proceed
  with sending CopyData messages

Task #7645
1 year ago
Juliana Fajardini decbb0ba5f pgsql: allow multi-request transactions
Important for CopyIn mode/ subprotocol, where the frontend is the one
sending 0 or more messages to the backend as part of a transaction.

Related to
Task #7645
1 year ago
Juliana Fajardini b3b0bbd1c3 pgsql: make CopyData struct generic
We have a data structure that can be used both for backend and frontend
messages, but was named as backend only.

Related to
Task #7645
1 year ago
Juliana Fajardini 62949b3815 pgsql: remove unused "password_message" code
``Password message`` is actually logged just as ``Password``.
Remove related dead code.
1 year ago
Juliana Fajardini 6f81caf8d4 pgsql: clearly indicate redacted password message
If a password message was seen while logging passwords was disabled
for pgsql, this would lead to an empty request being logged.
Instead of simply not logging anything when there is a password message
and this is disabled, however, log instead that said password is
redacted.

Bug #7647
1 year ago
Juliana Fajardini ef8b13c1ef pgsql: use generic name for TerminationMessage msg
Since this structure can be used for different messages with other
meanings.

Related to
Task #4854
2 years ago
Juliana Fajardini e75fcffa29 pgsql: add initial support to copy-out subproto
This sub-protocol inspects messages exchanged between postgresql backend
and frontend after a 'COPY TO STDOUT' has been processed.

Parses new messages:
- CopyOutResponse -- initiates copy-out mode/sub-protocol
- CopyData -- data transfer messages
- CopyDone -- signals that no more CopyData messages will be seen from
  the sender for the current transaction

Task #4854
2 years ago
Juliana Fajardini a4ce9cfe15 pgsql/logger: don't log empty transactions
This may happen in some situations if the app-layer parser only sees
unknown messages and sets an event: there will be an empty transaction,
but nothing to log.

Related to
Task #5566
2 years ago
Jason Ish 604e3c7422 rust/jsonbuilder: make set_uint generic over Into<u64>
Allow `set_uint` to accept any number value that can be converted to a
u64. Prevents callers from having to do `as u64`.

This required fixing up any callers that used `.into()` to just pass in
their value without the into conversion.

Most calls using `as u64` can have that cast removed, with the exception
of `usize` values which must still be cast is conversion can't be
guaranteed to be non-fallible.
2 years ago
Juliana Fajardini 2c7824a41f pgsql: use new API style for extern C functions 2 years ago
Juliana Fajardini 7aeb718dd7 pgsql: apply rust fmt changes 2 years ago
Juliana Fajardini 69e26de197 pgsql/logger: open json object from logger function
Before, the JsonBuilder object for the pgsql event was being created
from the C-side function that actually called the Rust logger.

This resulted that if another module - such as the Json Alert called the
PGSQL logger, we wouldn't have the `pgsql` key present in the log output
- only its inner fields.

Bug #6983
2 years ago
Juliana Fajardini 8d3de85edd pgsql: fix u16 overflow in query data_row
Found by oss-fuzz with quadfuzz.

Cf https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=63113

According to PostgreSQL documentation the maximum number of rows can be
the maximum of tuples that can fit onto max u32 pages - 4,294,967,295 (cf
https://www.postgresql.org/docs/current/limits.html). Some rough
calculations for that indicate that this could go over max u32, so
updating the data_row data type to u64.

Bug #6389
3 years ago
Juliana Fajardini 1afb485dfa pgsql: remove unused msg field
The `ConsolidatedDataRow` struct had a `length` field that wasn't truly
used.

Related to
Bug #6389
3 years ago
Juliana Fajardini 30ac77ce65 pgsql: add cancel request message
A CanceldRequest can occur after any query request, and is sent over a
new connection, leading to a new flow. It won't take any reply, but, if
processed by the backend, will lead to an ErrorResponse.

Task #6577
3 years ago
Juliana Fajardini bdec2d8ea8 pgsql: don't log password msg if password disabled
If the logging of the password is disabled, there isn't much point in
logging the password message itself.
3 years ago
Juliana Fajardini afd6e4dc41 pgsql: don't log unknown message type 3 years ago
Juliana Fajardini 1ac5d97259 pgsql: add unknonwn frontend message type
We had unkonwn message type for the backend, but not the frontend
messages. It's important to better identify those to improve pgsql
probing functions.

Related to
Bug #6080
3 years ago
Philippe Antoine 4c466ec5f4 rust/pgsql: remove unused/unconstructed enum variants 3 years ago
Jason Ish 33827beae5 jsonbuilder: check buffer growth
Use try_reserve before growing the internal buffer, and the internal
state vector. This allows allocation errors to be caught and an error
returned instead of just aborting the process.

Ticket: #6057
3 years ago
Jason Ish e7f5bd047d rust: fix needless borrows of references
Fixed automatically by cargo clippy --fix.
4 years ago
Juliana Fajardini c4fbd78770 pgsql: move database into opt parameters list
For StartupMessages, the database parameter is optional. This moves the
parameter into the optional_parameters list.

Bug #5579
4 years ago
Juliana Fajardini 0fc9ade7a9 pgsql: fix uint overflow and optimizations
Fuzzers found a possible integer overflow bug when parsing response
messages. To fix that, removed the case where we incremented the parsed
field length and created a new message type for situations where Suri
parsers an Unknown message. This is good because there may happen that
an unknown message to Suri is valid, and in this case, we would still be
able to log it.

Philippe Antoine found the bug while fuzzing with rust debug assertions.

Bug #5016
5 years ago
Juliana Fajardini 0bf1227f0f pgsql: fix defect found by coverity
Pgsql was using bitwise operations to assign password output config to
its context flags, but mixing that with logic negation of the default
value, resulting in the expressions having a constant value as result.

Bug: #5007
5 years ago
Juliana Fajardini 579d7dcc01 pgsql: add initial support
- add nom parsers for decoding most messages from StartupPhase and
SimpleQuery subprotocols
- add unittests
- tests/fuzz: add pgsql to confyaml

Feature: #4241
5 years ago