ssl: fix SSLv2 CLIENT_HELLO underflow

SSLv2Decode() consumed six fixed CLIENT_HELLO body bytes (version +
cipher_spec_length + session_id_length) guarded only by input_len >= 6,
which checks the buffer remainder but not the record itself.  When an
attacker sends a record whose declared record_length is < 7 (e.g. 1),
bytes_processed advances past record_lengths_length + record_length,
leading an integer underflow.

Address by adding a record_length >= 7 check to the CLIENT_HELLO case.

Also add another check: bail if bytes_processed > record_length +
record_lengths_length.

Ticket: #8853.
pull/16192/head
Victor Julien 1 month ago
parent 201ecd5618
commit 928ac01215

@ -2258,7 +2258,12 @@ static struct SSLDecoderResult SSLv2Decode(uint8_t direction, SSLState *ssl_stat
break; break;
case SSLV2_MT_CLIENT_HELLO: case SSLV2_MT_CLIENT_HELLO:
if (input_len < 6) { /* record_length does not count the msg_type byte. CLIENT_HELLO
* body starts with 3 fixed fields: client_version (2) +
* cipher_spec_length (2) + session_id_length (2). We need at
* least those 6 bytes after the msg_type, so record_length
* must be >= 7. */
if (input_len < 6 || ssl_state->curr_connp->record_length < 7) {
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD); SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
return SSL_DECODER_ERROR(-1); return SSL_DECODER_ERROR(-1);
} }
@ -2354,6 +2359,16 @@ static struct SSLDecoderResult SSLv2Decode(uint8_t direction, SSLState *ssl_stat
ssl_state->flags |= ssl_state->current_flags; ssl_state->flags |= ssl_state->current_flags;
if (ssl_state->curr_connp->bytes_processed >
ssl_state->curr_connp->record_length + ssl_state->curr_connp->record_lengths_length) {
SCLogDebug("SSLv2 bytes_processed (%u) exceeds record+hdr "
"len (record_length=%u, lengths_length=%u)",
ssl_state->curr_connp->bytes_processed, ssl_state->curr_connp->record_length,
ssl_state->curr_connp->record_lengths_length);
SSLSetEvent(ssl_state, TLS_DECODER_EVENT_INVALID_SSL_RECORD);
return SSL_DECODER_ERROR(-1);
}
if (input_len + ssl_state->curr_connp->bytes_processed >= if (input_len + ssl_state->curr_connp->bytes_processed >=
(ssl_state->curr_connp->record_length + (ssl_state->curr_connp->record_length +
ssl_state->curr_connp->record_lengths_length)) { ssl_state->curr_connp->record_lengths_length)) {

Loading…
Cancel
Save