From de1c40c44fdf621701717a5790ea10aaef126773 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Tue, 26 Apr 2011 14:21:28 -0600 Subject: [PATCH] Set decoder event on fragment overlaps. --- rules/decoder-events.rules | 1 + src/decode-events.h | 1 + src/defrag.c | 136 +++++++++++++++---------------------- src/detect-decode-event.h | 1 + 4 files changed, 59 insertions(+), 80 deletions(-) diff --git a/rules/decoder-events.rules b/rules/decoder-events.rules index 76ae1c72d1..0e4992b6e4 100644 --- a/rules/decoder-events.rules +++ b/rules/decoder-events.rules @@ -70,5 +70,6 @@ alert pkthdr any any -> any any (msg:"SURICATA VLAN header too small "; decode-e alert pkthdr any any -> any any (msg:"SURICATA VLAN unknown type"; decode-event:vlan.unknown_type; sid:22000066; rev:1;) alert pkthdr any any -> any any (msg:"SURICATA IP raw invalid IP version "; decode-event:ipraw.invalid_ip_version; sid:22000067; rev:1;) alert pkthdr any any -> any any (msg:"SURICATA FRAG Packet size too large"; decode-event:frag.too_large; sid:22000067; rev:1;) +alert pkthdr any any -> any any (msg:"SURICATA FRAG Fragmentation overlap"; decode-event:frag.overlap; sid:22000068; rev:1;) diff --git a/src/decode-events.h b/src/decode-events.h index 7a09ae55b9..7f0120689b 100644 --- a/src/decode-events.h +++ b/src/decode-events.h @@ -182,6 +182,7 @@ enum { /* Fragmentation reasembly events. */ FRAG_PKT_TOO_LARGE, + FRAG_OVERLAP, /* should always be last! */ DECODE_EVENT_MAX, diff --git a/src/defrag.c b/src/defrag.c index ca44a32e60..d076ccc154 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -816,6 +816,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, tracker->timeout.tv_sec += dc->timeout; Frag *prev = NULL, *next; + int overlap = 0; if (!TAILQ_EMPTY(&tracker->frags)) { TAILQ_FOREACH(prev, &tracker->frags, next) { ltrim = 0; @@ -826,13 +827,16 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, if (frag_offset < prev->offset + prev->data_len) { if (frag_offset >= prev->offset) { ltrim = prev->offset + prev->data_len - frag_offset; + overlap++; } if ((next != NULL) && (frag_end > next->offset)) { next->ltrim = frag_end - next->offset; + overlap++; } if ((frag_offset < prev->offset) && (frag_end >= prev->offset + prev->data_len)) { prev->skip = 1; + overlap++; } goto insert; } @@ -841,13 +845,16 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, if (frag_offset < prev->offset + prev->data_len) { if (frag_offset > prev->offset) { ltrim = prev->offset + prev->data_len - frag_offset; + overlap++; } if ((next != NULL) && (frag_end > next->offset)) { next->ltrim = frag_end - next->offset; + overlap++; } if ((frag_offset < prev->offset) && (frag_end >= prev->offset + prev->data_len)) { prev->skip = 1; + overlap++; } goto insert; } @@ -856,10 +863,12 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, if (frag_offset < prev->offset + prev->data_len) { if (frag_offset >= prev->offset) { ltrim = prev->offset + prev->data_len - frag_offset; + overlap++; } if ((frag_offset < prev->offset) && (frag_end > prev->offset + prev->data_len)) { prev->skip = 1; + overlap++; } goto insert; } @@ -868,23 +877,28 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, if (frag_offset < prev->offset + prev->data_len) { if (frag_offset >= prev->offset) { ltrim = prev->offset + prev->data_len - frag_offset; + overlap++; } if ((frag_offset < prev->offset) && (frag_end >= prev->offset + prev->data_len)) { prev->skip = 1; + overlap++; } goto insert; } break; case DEFRAG_POLICY_FIRST: if ((frag_offset >= prev->offset) && - (frag_end <= prev->offset + prev->data_len)) + (frag_end <= prev->offset + prev->data_len)) { + overlap++; goto done; + } if (frag_offset < prev->offset) { goto insert; } if (frag_offset < prev->offset + prev->data_len) { ltrim = prev->offset + prev->data_len - frag_offset; + overlap++; goto insert; } break; @@ -892,6 +906,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragContext *dc, if (frag_offset <= prev->offset) { if (frag_end > prev->offset) { prev->ltrim = frag_end - prev->offset; + overlap++; } goto insert; } @@ -967,6 +982,9 @@ insert: } done: + if (overlap) { + DECODER_SET_EVENT(p, FRAG_OVERLAP); + } SCMutexUnlock(&tracker->lock); return r; } @@ -1757,13 +1775,29 @@ DefragDoSturgesNovakTest(int policy, u_char *expected, size_t expected_len) default_policy = policy; /* Send all but the last. */ - for (i = 0; i < 16; i++) { + for (i = 0; i < 9; i++) { + Packet *tp = Defrag(NULL, NULL, dc, packets[i]); + if (tp != NULL) { + SCFree(tp); + goto end; + } + if (DECODER_ISSET_EVENT(packets[i], FRAG_OVERLAP)) { + goto end; + } + } + int overlap = 0; + for (; i < 16; i++) { Packet *tp = Defrag(NULL, NULL, dc, packets[i]); if (tp != NULL) { SCFree(tp); goto end; } + if (DECODER_ISSET_EVENT(packets[i], FRAG_OVERLAP)) { + overlap++; + } } + if (!overlap) + goto end; /* And now the last one. */ Packet *reassembled = Defrag(NULL, NULL, dc, packets[16]); @@ -1880,87 +1914,29 @@ IPV6DefragDoSturgesNovakTest(int policy, u_char *expected, size_t expected_len) default_policy = policy; /* Send all but the last. */ - Packet *tp; - tp = Defrag(NULL, NULL, dc, packets[0]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[1]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[2]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[3]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[4]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[5]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[6]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[7]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[8]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[9]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[10]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[11]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[12]); - if (tp != NULL) { - SCFree(tp); - goto end; - } - tp = Defrag(NULL, NULL, dc, packets[13]); - if (tp != NULL) { - SCFree(tp); - goto end; + for (i = 0; i < 9; i++) { + Packet *tp = Defrag(NULL, NULL, dc, packets[i]); + if (tp != NULL) { + SCFree(tp); + goto end; + } + if (DECODER_ISSET_EVENT(packets[i], FRAG_OVERLAP)) { + goto end; + } } - tp = Defrag(NULL, NULL, dc, packets[14]); - if (tp != NULL) { - SCFree(tp); - goto end; + int overlap = 0; + for (; i < 16; i++) { + Packet *tp = Defrag(NULL, NULL, dc, packets[i]); + if (tp != NULL) { + SCFree(tp); + goto end; + } + if (DECODER_ISSET_EVENT(packets[i], FRAG_OVERLAP)) { + overlap++; + } } - tp = Defrag(NULL, NULL, dc, packets[15]); - if (tp != NULL) { - SCFree(tp); + if (!overlap) goto end; - } /* And now the last one. */ Packet *reassembled = Defrag(NULL, NULL, dc, packets[16]); diff --git a/src/detect-decode-event.h b/src/detect-decode-event.h index ab97cf8ea4..2858ccebc6 100644 --- a/src/detect-decode-event.h +++ b/src/detect-decode-event.h @@ -111,6 +111,7 @@ struct DetectDecodeEvents_ { { "vlan.header_too_small",VLAN_HEADER_TOO_SMALL, }, { "vlan.unknown_type",VLAN_UNKNOWN_TYPE, }, { "frag.too_large", FRAG_PKT_TOO_LARGE, }, + { "frag.overlap", FRAG_OVERLAP, }, { NULL, 0 }, }; #endif /* DETECT_EVENTS */