mirror of https://github.com/sysown/proxysql
fix(mysqlx): four minor security findings from issue #5676
Addresses the four Minor / Nit findings deferred when the Important
re-auth bug was fixed in commit 09c15d6d5.
## (1) Reject TLS upgrade post-auth or on encrypted channel
`handler_capabilities_set` previously honored `tls=true` regardless
of session state, so a logged-in client could ship CapabilitiesSet
with tls=true and the server would dutifully start an SSL handshake
on an already-authenticated session — or, worse, a second handshake
on an already-encrypted channel that left the state machine in
"expecting fresh handshake" while the client kept its existing TLS
session. Both cases are spec violations (the X Protocol forbids TLS
negotiation post-AuthenticateOk) and produce a confused-client kill.
Fix: reject with code 5052 (FATAL) when client_ds_.is_encrypted() is
true OR status_ has progressed past the pre-auth states. The TLS
branch only runs from CONNECTING_CLIENT / X_CAPABILITIES_GET /
X_CAPABILITIES_SET now.
## (2) Cap leading-NOTICE drain in backend auth
`read_auth_frame` loops while the backend ships NOTICE frames, on
the assumption that any legitimate backend emits at most a couple
during auth. A compromised or malicious backend could pin the worker
thread by streaming NOTICEs continuously. Add a cap of 64 leading
notices (MAX_LEADING_NOTICES); on the 65th, treat as auth failure
(BACKEND_AUTH_ERROR) and let the chassis tear the session down.
## (3) Per-session pre-auth CapabilitiesGet/Set replay cap
A client can reset back to CONNECTING_CLIENT after each
CapabilitiesGet/Set without ever authenticating, and each iteration
allocates a fresh protobuf and runs the full handler. Without a cap
this is a free CPU/memory amplifier (bounded only by the OS recv
buffer). Add a per-session counter (pre_auth_cap_msgs_) bumped on
every CapabilitiesGet/Set seen while status_ != WAITING_CLIENT_XMSG.
Threshold MAX_PRE_AUTH_CAP_MSGS = 64 (legitimate clients send 1-3);
on overflow, send 5008 + healthy=false. Counter resets on session
reset() and is bypassed once auth completes (post-auth introspection
of capabilities is legitimate and unbounded).
## (4) MysqlxDataStream::enqueue_frame: surface oversize as parse error
`if (body_len + 1 > X_MAX_PAYLOAD_SIZE) return;` previously dropped
oversize bodies silently, leaving the client expecting a frame that
never arrives. Set parse_error_=true so the session loop tears the
connection down cleanly. Reaching this branch is an internal bug
(server-side senders are responsible for never producing a >16MiB
body), but a clean teardown is materially better than a half-working
session.
## Verified
After this commit (PROXYSQLGENAI=1 NOJEMALLOC=1 WITHASAN=1):
- mysqlx_session_unit-t 60 / 0 (was 60 / 0)
- mysqlx_robustness_unit-t 74 / 0 (was 74 / 0)
- mysqlx_compression_unit-t 64 / 0 (was 64 / 0)
- mysqlx_protocol_unit-t 42 / 0 (was 42 / 0)
- mysqlx_data_stream_unit-t 18 / 0 (was 18 / 0)
- ASAN: 0 errors
These are defense-in-depth changes; none addresses an exploitable
crash. All five tests pass with no regressions.
fix/test-mysqlx-plugin-load-phase-b
parent
99a745f6ed
commit
2b0c2fdcc4
Loading…
Reference in new issue