GHSA-893m-9g4r-4992: Out-of-bounds Read via a Zero-length TLS 1.3 Certificate Message in NetX Secure
GHSA ID |
|
|---|---|
CVE ID |
CVE‑2026‑92853 |
Severity |
High |
CVSS score |
7.5 ( |
CWE |
|
Published |
2026‑10‑02 |
Last updated |
2026‑10‑02 |
Description
Summary
The TLS 1.3 Certificate-message parser in NetX Secure decrements the message length to skip a context byte without first establishing that the message has a byte to skip. A zero-length Certificate message therefore wraps the unsigned length to 0xFFFFFFFF, which makes the bounds check that follows vacuous and sends the parser reading past the session packet buffer.
The trigger is a four-byte handshake header and requires no cryptographic validity. It is reachable pre-authentication.
Details
In _nx_secure_tls_process_remote_certificate, the TLS 1.3 branch advances past the certificate-request context:
#if (NX_SECURE_TLS_TLS_1_3_ENABLED)
if(tls_session->nx_secure_tls_1_3)
{
packet_buffer++;
message_length--; /* no check that message_length > 0 */
}
#endif
total_length = (UINT)((packet_buffer[0] << 16) + (packet_buffer[1] << 8) + packet_buffer[2]);
length = length + 3;
/* Make sure what we extracted makes sense. */
if (total_length > message_length) /* vacuous once message_length == 0xFFFFFFFF */
{
return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
}
The TLS 1.3 client handshake forwards a Certificate message with message_length of zero, so the decrement underflows before any certificate content is examined. Every subsequent length test compares against 0xFFFFFFFF and passes.
There is a second, conformance defect on the same statement. RFC 8446 §4.4.2 makes the context 1 + packet_buffer[0] bytes, but the parser advances a single byte regardless of the length actually declared, so it is misaligned whenever a context is supplied.
A zero-length server Certificate is itself non-conformant: RFC 8446 §4.4.2 requires the server’s certificate_list to be non-empty, and §4.4.2.4 requires a client receiving an empty Certificate message to abort with a decode_error alert. The defect is precisely that NetX Secure parses it rather than aborting.
Impact
An unauthenticated malicious TLS 1.3 server, or an on-path attacker before the handshake completes, crashes any connecting NetX Duo TLS 1.3 client. The same function is reached by a TLS 1.3 server with client-certificate verification enabled when attacked by a malicious client, and by DTLS 1.3 clients.
On embedded targets the out-of-bounds read from the session packet buffer typically crosses an MPU or RAM boundary and produces a hard fault or reset, denying service to the whole firmware image. The bytes read never leave the DER parser, so there is no direct disclosure path.
Affected configurations
NetX Secure builds with TLS 1.3 enabled, on clients, on servers performing client-certificate verification, and on DTLS 1.3 clients.
Every NetX Duo release up to and including 6.5.1.202602.
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H — 7.5, High.
AV:N reflects that the attacker is any endpoint the client connects to, before that endpoint has been authenticated. AC:L reflects a single fixed malformed message, with no cipher-suite or configuration condition beyond TLS 1.3 itself. C:N and I:N reflect that the bytes read are consumed only by DER parsing.
Patches
Fixed in NetX Duo 6.5.2.202603. The one-byte context length must be present before it is read, which is what stops the decrement wrapping a zero-length message, and the context it declares must be present as well. The parser then advances by the length byte plus the context, rather than by a single byte regardless of what was declared, which closes the conformance defect that left it misaligned whenever a context was actually supplied. A regression test drives a zero-length Certificate message, a one-byte message, a message whose declared context runs past its end, and well-formed messages that must still be accepted. It must be built with TLS 1.3 enabled; in a configuration without it the test compiles out and reports N/A rather than failing.
The three length checks overlap deliberately, and that limits what the test can prove about each one. All three return NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH, so removing any single check leaves the next one to refuse the same input with the same status, and the test still passes. What the test does prove on its own is the correction that matters: restoring the original single-byte advance reproduces the unsigned wrap and the test fails. Separating the three checks would need a memory sanitizer, since the over-read they prevent lands inside a valid buffer in a test harness.