diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 9b86782a7a..18b8d7d2d3 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -2271,7 +2271,8 @@ static inline void AppLayerInsertNewProbingParser(AppLayerProbingParser **pp, void AppLayerRegisterParserAcceptableDataDirection(uint16_t al_proto, uint8_t flags) { - al_proto_table[al_proto].flags |= (flags & (STREAM_TOSERVER | STREAM_TOCLIENT)); + al_proto_table[al_proto].first_data_dir |= + (flags & (STREAM_TOSERVER | STREAM_TOCLIENT)); return; } diff --git a/src/app-layer-parser.h b/src/app-layer-parser.h index d7e7b5ab31..9b2e270b34 100644 --- a/src/app-layer-parser.h +++ b/src/app-layer-parser.h @@ -73,8 +73,10 @@ typedef struct AppLayerProto_ { int *event_id, AppLayerEventType *event_type); ProbingParserFPtr PPAlprotoMap[2]; - /* The current values taken are STREAM_TOSERVER, STREAM_TOCLIENT */ - uint8_t flags; + /* Indicates the direction the parser is ready to see the data + * the first time for a flow. Values accepted - + * STREAM_TOSERVER, STREAM_TOCLIENT */ + uint8_t first_data_dir; #ifdef UNITTESTS void (*RegisterUnittests)(void); diff --git a/src/app-layer.c b/src/app-layer.c index 648c245d6d..61fc26eb53 100644 --- a/src/app-layer.c +++ b/src/app-layer.c @@ -202,6 +202,8 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, f->alproto = *alproto; StreamTcpSetStreamFlagAppProtoDetectionCompleted(stream); + /* if we have seen data from the other direction first, send + * data for that direction first to the parser */ if ((ssn->data_first_seen_dir & (STREAM_TOSERVER | STREAM_TOCLIENT)) && !(flags & ssn->data_first_seen_dir)) { TcpStream *opposing_stream = NULL; @@ -229,8 +231,26 @@ int AppLayerHandleTCPData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, } } + /* if the parser operates such that it needs to see data from + * a particular direction first, we check if we have seen + * data from that direction first for the flow. IF it is not + * the same, we set an event and exit. + * + * \todo We need to figure out a more robust solution for this, + * as this can lead to easy evasion tactics, where the + * attackeer can first send some dummy data in the wrong + * direction first to mislead our proto detection process. + * While doing this we need to update the parsers as well, + * since the parsers must be robust to see such wrong + * direction data. + * Either ways the moment we see the + * APPLAYER_WRONG_DIRECTION_FIRST_DATA event set for the + * flow, it shows something's fishy. + */ if (ssn->data_first_seen_dir != APP_LAYER_DATA_ALREADY_SENT_TO_APP_LAYER) { - if (al_proto_table[*alproto].flags && !(al_proto_table[*alproto].flags & ssn->data_first_seen_dir)) { + if (al_proto_table[*alproto].first_data_dir && + !(al_proto_table[*alproto].first_data_dir & ssn->data_first_seen_dir)) + { AppLayerDecoderEventsSetEventRaw(p->app_layer_events, APPLAYER_WRONG_DIRECTION_FIRST_DATA); r = -1;