smtp: recover from invalid BDAT command syntax

A BDAT command that failed to parse, such as "BDAT 5 X", returned -1,
disabling SMTP parsing for the rest of the flow. A server may reject the
command and continue the session, leaving following messages
uninspected.

Instead raise a decoder event and queue the command as an ordinary
command.

Ticket: #8741
pull/16014/head
Jason Ish 2 months ago committed by Victor Julien
parent ec0fec1a37
commit 60e0df6530

@ -31,4 +31,6 @@ alert smtp any any -> any any (msg:"SURICATA SMTP duplicate fields"; flow:establ
alert smtp any any -> any any (msg:"SURICATA SMTP unparsable content"; flow:established,to_server; app-layer-event:smtp.unparsable_content; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220019; rev:1;)
alert smtp any any -> any any (msg:"SURICATA SMTP filename truncated"; flow:established,to_server; app-layer-event:smtp.mime_long_filename; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220020; rev:1;)
alert smtp any any -> any any (msg:"SURICATA SMTP failed protocol change"; flow:established,to_client; app-layer-event:smtp.failed_protocol_change; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220021; rev:2;)
# next sid 2220022
alert smtp any any -> any any (msg:"SURICATA SMTP invalid BDAT command"; flow:established,to_server; app-layer-event:smtp.invalid_bdat; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220022; rev:1;)
# next sid 2220023

@ -132,6 +132,7 @@ SCEnumCharMap smtp_decoder_event_table[] = {
{ "MAX_REPLY_LINE_LEN_EXCEEDED", SMTP_DECODER_EVENT_MAX_REPLY_LINE_LEN_EXCEEDED },
{ "INVALID_PIPELINED_SEQUENCE", SMTP_DECODER_EVENT_INVALID_PIPELINED_SEQUENCE },
{ "BDAT_CHUNK_LEN_EXCEEDED", SMTP_DECODER_EVENT_BDAT_CHUNK_LEN_EXCEEDED },
{ "INVALID_BDAT", SMTP_DECODER_EVENT_INVALID_BDAT },
{ "NO_SERVER_WELCOME_MESSAGE", SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE },
{ "TLS_REJECTED", SMTP_DECODER_EVENT_TLS_REJECTED },
{ "DATA_COMMAND_REJECTED", SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED },
@ -1393,14 +1394,19 @@ static int SMTPProcessRequest(
bool last = false;
r = SMTPParseCommandBDAT(state, line, &last);
if (r == -1) {
SCReturnInt(-1);
}
state->current_command = last ? SMTP_COMMAND_BDAT_LAST : SMTP_COMMAND_BDAT;
SMTPSetProgressTS(tx, SMTP_REQUEST_DATA);
if (state->bdat_chunk_len > 0) {
state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
} else if (last) {
SMTPTransactionCompleteTS(tx);
/* Invalid BDAT syntax is recoverable: the server rejects the
* command and the session continues. */
SMTPSetEvent(state, SMTP_DECODER_EVENT_INVALID_BDAT);
state->current_command = SMTP_COMMAND_OTHER_CMD;
r = 0;
} else {
state->current_command = last ? SMTP_COMMAND_BDAT_LAST : SMTP_COMMAND_BDAT;
SMTPSetProgressTS(tx, SMTP_REQUEST_DATA);
if (state->bdat_chunk_len > 0) {
state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
} else if (last) {
SMTPTransactionCompleteTS(tx);
}
}
} else if (line->len >= 4 && ((SCMemcmpLowercase("helo", line->buf, 4) == 0) ||
SCMemcmpLowercase("ehlo", line->buf, 4) == 0)) {

@ -39,6 +39,7 @@ enum {
SMTP_DECODER_EVENT_MAX_REPLY_LINE_LEN_EXCEEDED,
SMTP_DECODER_EVENT_INVALID_PIPELINED_SEQUENCE,
SMTP_DECODER_EVENT_BDAT_CHUNK_LEN_EXCEEDED,
SMTP_DECODER_EVENT_INVALID_BDAT,
SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE,
SMTP_DECODER_EVENT_TLS_REJECTED,
SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED,

Loading…
Cancel
Save