]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
protocol-change: sets event in case of failure
authorPhilippe Antoine <contact@catenacyber.fr>
Mon, 25 Apr 2022 06:23:53 +0000 (08:23 +0200)
committerVictor Julien <vjulien@oisf.net>
Tue, 23 Aug 2022 11:50:36 +0000 (13:50 +0200)
Protocol change can fail if one protocol change is already
occuring.

Ticket: #5509

rules/http-events.rules
rules/smtp-events.rules
rust/src/applayer.rs
src/app-layer-detect-proto.c
src/app-layer-detect-proto.h
src/app-layer-htp.c
src/app-layer-htp.h
src/app-layer-smtp.c
src/app-layer-smtp.h

index dbdf523f52c444df1c1ecea7a25ff4308d8e61ad..6376c807fcfffa85d351aab8f5d0e7e17e14ae2e 100644 (file)
@@ -87,4 +87,6 @@ alert http any any -> any any (msg:"SURICATA HTTP invalid Range header value"; f
 
 alert http any any -> any any (msg:"SURICATA HTTP file name too long"; flow:established; app-layer-event:http.file_name_too_long; flowint:http.anomaly.count,+,1; classtype:protocol-command-decode; sid:2221052; rev:1;)
 
-# next sid 2221053
+alert http any any -> any any (msg:"SURICATA HTTP failed protocol change"; flow:established; app-layer-event:http.failed_protocol_change; flowint:http.anomaly.count,+,1; classtype:protocol-command-decode; sid:2221053; rev:1;)
+
+# next sid 2221054
index cc7eedcbbf665133eb39c873266d92a9f355ce78..135b84c629e1340facfec05d82de1b0154a9a559 100644 (file)
@@ -30,4 +30,5 @@ alert smtp any any -> any any (msg:"SURICATA SMTP Mime boundary length exceeded"
 alert smtp any any -> any any (msg:"SURICATA SMTP duplicate fields"; flow:established,to_server; app-layer-event:smtp.duplicate_fields; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220018; rev:1;)
 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;)
-# next sid 2220021
+alert smtp any any -> any any (msg:"SURICATA SMTP failed protocol change"; flow:established; app-layer-event:smtp.failed_protocol_change; flowint:smtp.anomaly.count,+,1; classtype:protocol-command-decode; sid:2220021; rev:1;)
+# next sid 2220022
index 642172a51816a8bd0470a35bd926b363105b8725..a08741b02b4d0763de343daa706e5a40f30aaf9b 100644 (file)
@@ -388,7 +388,7 @@ extern {
                                                      pp_min_depth: u16, pp_max_depth: u16) -> c_int;
     pub fn AppLayerProtoDetectConfProtoDetectionEnabled(ipproto: *const c_char, proto: *const c_char) -> c_int;
     pub fn AppLayerProtoDetectConfProtoDetectionEnabledDefault(ipproto: *const c_char, proto: *const c_char, default: bool) -> c_int;
-    pub fn AppLayerRequestProtocolTLSUpgrade(flow: *const Flow);
+    pub fn AppLayerRequestProtocolTLSUpgrade(flow: *const Flow) -> bool;
 }
 
 // Defined in app-layer-parser.h
index 3971291245cda300805ddf7a8434dd47bac77ecf..638bd1b983aff16cf9316a3624a6bb33e884963e 100644 (file)
@@ -1958,13 +1958,13 @@ void AppLayerProtoDetectRegisterAlias(const char *proto_name, const char *proto_
  *  \param expect_proto expected protocol. AppLayer event will be set if
  *                      detected protocol differs from this.
  */
-void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
+bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
 {
     if (FlowChangeProto(f)) {
         // If we are already changing protocols, from SMTP to TLS for instance,
         // and that we do not get TLS but HTTP1, which is requesting whange to HTTP2,
         // we do not proceed the new protocol change
-        return;
+        return false;
     }
     FlowSetChangeProtoFlag(f);
     f->protodetect_dp = dp;
@@ -1978,6 +1978,7 @@ void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
     if (f->alproto_tc == ALPROTO_UNKNOWN) {
         f->alproto_tc = f->alproto;
     }
+    return true;
 }
 
 /** \brief request applayer to wrap up this protocol and rerun protocol
@@ -1988,9 +1989,9 @@ void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto)
  *
  *  \param f flow to act on
  */
-void AppLayerRequestProtocolTLSUpgrade(Flow *f)
+bool AppLayerRequestProtocolTLSUpgrade(Flow *f)
 {
-    AppLayerRequestProtocolChange(f, 443, ALPROTO_TLS);
+    return AppLayerRequestProtocolChange(f, 443, ALPROTO_TLS);
 }
 
 void AppLayerProtoDetectReset(Flow *f)
index cf9b5e2506a5b785a34e1336899c60a7dad46142..7d1430d541af5971b9f71647d5c97eac1fb3f970 100644 (file)
@@ -115,8 +115,8 @@ int AppLayerProtoDetectSetup(void);
  */
 void AppLayerProtoDetectReset(Flow *);
 
-void AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto);
-void AppLayerRequestProtocolTLSUpgrade(Flow *f);
+bool AppLayerRequestProtocolChange(Flow *f, uint16_t dp, AppProto expect_proto);
+bool AppLayerRequestProtocolTLSUpgrade(Flow *f);
 
 /**
  * \brief Cleans up the app layer protocol detection phase.
index cfe1302bb854518089b994af1ecebe0bc10d235b..c46d8c7fbc3599585ad02795ab2d1f072352c8ba 100644 (file)
@@ -172,6 +172,7 @@ SCEnumCharMap http_decoder_event_table[] = {
     { "MULTIPART_INVALID_HEADER", HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER },
 
     { "TOO_MANY_WARNINGS", HTTP_DECODER_EVENT_TOO_MANY_WARNINGS },
+    { "FAILED_PROTOCOL_CHANGE", HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE },
 
     { NULL, -1 },
 };
@@ -968,7 +969,10 @@ static AppLayerResult HTPHandleResponseData(Flow *f, void *htp_state, AppLayerPa
                     }
                     consumed = htp_connp_res_data_consumed(hstate->connp);
                     hstate->slice = NULL;
-                    AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_HTTP2);
+                    if (!AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_HTTP2)) {
+                        HTPSetEvent(hstate, NULL, STREAM_TOCLIENT,
+                                HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE);
+                    }
                     // During HTTP2 upgrade, we may consume the HTTP1 part of the data
                     // and we need to parser the remaining part with HTTP2
                     if (consumed > 0 && consumed < input_len) {
@@ -2282,7 +2286,10 @@ static int HTPCallbackResponseComplete(htp_tx_t *tx)
                 dp = (uint16_t)tx->request_port_number;
             }
             // both ALPROTO_HTTP1 and ALPROTO_TLS are normal options
-            AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_UNKNOWN);
+            if (!AppLayerRequestProtocolChange(hstate->f, dp, ALPROTO_UNKNOWN)) {
+                HTPSetEvent(
+                        hstate, htud, STREAM_TOCLIENT, HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE);
+            }
             tx->request_progress = HTP_REQUEST_COMPLETE;
             tx->response_progress = HTP_RESPONSE_COMPLETE;
         }
index 7f2389213c5dfb4c6164701267c8d7de5883ba25..c8ad3717651499f12c59b5b5c3050b1c346c0af6 100644 (file)
@@ -139,6 +139,8 @@ enum {
     HTTP_DECODER_EVENT_MULTIPART_INVALID_HEADER,
 
     HTTP_DECODER_EVENT_TOO_MANY_WARNINGS,
+
+    HTTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE,
 };
 
 typedef enum HtpSwfCompressType_ {
index 449dd30298b9e0f48732ca890ab1b38b6e304058..787a6a76f166b1c3bb7b9cb91f3b5d6ad58061bb 100644 (file)
@@ -145,6 +145,7 @@ SCEnumCharMap smtp_decoder_event_table[] = {
     { "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 },
+    { "FAILED_PROTOCOL_CHANGE", SMTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE },
 
     /* MIME Events */
     { "MIME_PARSE_FAILED", SMTP_DECODER_EVENT_MIME_PARSE_FAILED },
@@ -944,7 +945,9 @@ static int SMTPProcessReply(SMTPState *state, Flow *f, AppLayerParserState *psta
         if (reply_code == SMTP_REPLY_220) {
             /* we are entering STARRTTLS data mode */
             state->parser_state |= SMTP_PARSER_STATE_COMMAND_DATA_MODE;
-            AppLayerRequestProtocolTLSUpgrade(f);
+            if (!AppLayerRequestProtocolTLSUpgrade(f)) {
+                SMTPSetEvent(state, SMTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE);
+            }
             if (state->curr_tx) {
                 SMTPTransactionComplete(state);
             }
index af6550b560d93d9f0731a6bfc424405c5026ab1a..f7f983b7ee08bb662179b54e763a862754a9cd37 100644 (file)
@@ -38,6 +38,7 @@ enum {
     SMTP_DECODER_EVENT_NO_SERVER_WELCOME_MESSAGE,
     SMTP_DECODER_EVENT_TLS_REJECTED,
     SMTP_DECODER_EVENT_DATA_COMMAND_REJECTED,
+    SMTP_DECODER_EVENT_FAILED_PROTOCOL_CHANGE,
 
     /* MIME Events */
     SMTP_DECODER_EVENT_MIME_PARSE_FAILED,