support for several tcp evasion attacks. Thanks to Judy Novak and G2 Inc for reporting them

remotes/origin/master-1.0.x
Gurvinder Singh 15 years ago committed by Victor Julien
parent bc55fb27dc
commit 6a5bc52461

@ -1595,7 +1595,7 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx,
/* if app layer protocol has been detected, then restore the reassembled /* if app layer protocol has been detected, then restore the reassembled
seq. to the value till reassembling has been done and unset the queue seq. to the value till reassembling has been done and unset the queue
init flag permanently for this tcp session */ init flag permanently for this tcp session */
} else if (stream->tmp_ra_base_seq > stream->ra_base_seq) { } else if (SEQ_GT(stream->tmp_ra_base_seq, stream->ra_base_seq)) {
stream->ra_base_seq = stream->tmp_ra_base_seq; stream->ra_base_seq = stream->tmp_ra_base_seq;
ra_ctx->stream_q->flags &= ~STREAMQUEUE_FLAG_INIT; ra_ctx->stream_q->flags &= ~STREAMQUEUE_FLAG_INIT;
ra_base_seq = stream->ra_base_seq; ra_base_seq = stream->ra_base_seq;
@ -1606,7 +1606,12 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx,
/* set the ra_bas_seq to stream->ra_base_seq as now app layer protocol /* set the ra_bas_seq to stream->ra_base_seq as now app layer protocol
has been detected */ has been detected */
} else { } else {
ra_base_seq = stream->ra_base_seq; if (SEQ_GT(stream->tmp_ra_base_seq, stream->ra_base_seq)) {
stream->ra_base_seq = stream->tmp_ra_base_seq;
ra_base_seq = stream->ra_base_seq;
} else {
ra_base_seq = stream->ra_base_seq;
}
} }
/* check if we have enough data to send to L7 */ /* check if we have enough data to send to L7 */
@ -2446,7 +2451,7 @@ void StreamTcpCreateTestPacket(uint8_t *payload, uint8_t value,
* \param stream Reassembled stream returned from the reassembly functions * \param stream Reassembled stream returned from the reassembly functions
*/ */
static int StreamTcpCheckStreamContents(uint8_t *stream_policy, uint16_t sp_size, TcpStream *stream) { int StreamTcpCheckStreamContents(uint8_t *stream_policy, uint16_t sp_size, TcpStream *stream) {
TcpSegment *temp; TcpSegment *temp;
uint16_t i = 0; uint16_t i = 0;
uint8_t j; uint8_t j;
@ -5902,6 +5907,123 @@ end:
return ret; return ret;
} }
/**
* \test Test to make sure we detect the sequence wrap around and continue
* stream reassembly properly.
*
* \retval On success it returns 1 and on failure 0.
*/
static int StreamTcpReassembleTest47 (void) {
int ret = 0;
Packet p;
Flow f;
TCPHdr tcph;
Port sp;
Port dp;
Address src;
Address dst;
struct in_addr in;
TcpSession ssn;
memset(&p, 0, sizeof (Packet));
memset(&f, 0, sizeof (Flow));
memset(&tcph, 0, sizeof (TCPHdr));
memset(&src, 0, sizeof(Address));
memset(&dst, 0, sizeof(Address));
memset(&ssn, 0, sizeof(TcpSession));
/* prevent L7 from kicking in */
StreamMsgQueueSetMinInitChunkLen(FLOW_PKT_TOSERVER, 0);
StreamMsgQueueSetMinInitChunkLen(FLOW_PKT_TOCLIENT, 0);
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 0);
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 0);
FLOW_INITIALIZE(&f);
StreamTcpInitConfig(TRUE);
TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx();
AppLayerDetectProtoThreadInit();
uint8_t httpbuf1[] = "GET /EVILSUFF HTTP/1.1\r\n\r\n";
uint32_t httplen1 = sizeof(httpbuf1) - 1; /* minus the \0 */
inet_pton(AF_INET, "1.2.3.4", &in);
src.family = AF_INET;
src.addr_data32[0] = in.s_addr;
inet_pton(AF_INET, "1.2.3.5", &in);
dst.family = AF_INET;
dst.addr_data32[0] = in.s_addr;
sp = 200;
dp = 220;
ssn.server.ra_base_seq = 572799781UL;
ssn.server.isn = 572799781UL;
ssn.server.last_ack = 572799782UL;
ssn.client.ra_base_seq = 4294967289UL;
ssn.client.isn = 4294967289UL;
ssn.client.last_ack = 21;
f.alproto = ALPROTO_UNKNOWN;
f.src = src;
f.dst = dst;
f.sp = sp;
f.dp = dp;
f.protoctx = &ssn;
p.flow = &f;
tcph.th_win = htons(5480);
ssn.state = TCP_ESTABLISHED;
TcpStream *s = NULL;
uint8_t cnt = 0;
for (cnt=0; cnt < httplen1; cnt++) {
tcph.th_seq = htonl(ssn.client.isn + 1 + cnt);
tcph.th_ack = htonl(572799782UL);
tcph.th_flags = TH_ACK|TH_PUSH;
p.tcph = &tcph;
p.flowflags = FLOW_PKT_TOSERVER;
p.payload = &httpbuf1[cnt];
p.payload_len = 1;
s = &ssn.client;
if (StreamTcpReassembleHandleSegment(ra_ctx, &ssn, s, &p) == -1) {
printf("failed in segments reassembly, while processing toserver "
"packet\n");
goto end;
}
p.flowflags = FLOW_PKT_TOCLIENT;
p.payload = NULL;
p.payload_len = 0;
tcph.th_seq = htonl(572799782UL);
tcph.th_ack = htonl(ssn.client.isn + 1 + cnt);
tcph.th_flags = TH_ACK;
p.tcph = &tcph;
s = &ssn.server;
if (StreamTcpReassembleHandleSegment(ra_ctx, &ssn, s, &p) == -1) {
printf("failed in segments reassembly, while processing toserver "
"packet\n");
goto end;
}
/* Process stream smsgs we may have in queue */
if (StreamTcpReassembleProcessAppLayer(ra_ctx) < 0) {
printf("failed in processing stream smsgs\n");
goto end;
}
}
if (f.alproto != ALPROTO_HTTP) {
printf("App layer protocol (HTTP) should have been detected\n");
goto end;
}
ret = 1;
end:
StreamTcpFreeConfig(TRUE);
StreamTcpReassembleFreeThreadCtx(ra_ctx);
return ret;
}
#endif /* UNITTESTS */ #endif /* UNITTESTS */
/** \brief The Function Register the Unit tests to test the reassembly engine /** \brief The Function Register the Unit tests to test the reassembly engine
@ -5956,5 +6078,6 @@ void StreamTcpReassembleRegisterTests(void) {
UtRegisterTest("StreamTcpReassembleTest44 -- Memcap Test", StreamTcpReassembleTest44, 1); UtRegisterTest("StreamTcpReassembleTest44 -- Memcap Test", StreamTcpReassembleTest44, 1);
UtRegisterTest("StreamTcpReassembleTest45 -- Depth Test", StreamTcpReassembleTest45, 1); UtRegisterTest("StreamTcpReassembleTest45 -- Depth Test", StreamTcpReassembleTest45, 1);
UtRegisterTest("StreamTcpReassembleTest46 -- Depth Test", StreamTcpReassembleTest46, 1); UtRegisterTest("StreamTcpReassembleTest46 -- Depth Test", StreamTcpReassembleTest46, 1);
UtRegisterTest("StreamTcpReassembleTest47 -- TCP Sequence Wraparound Test", StreamTcpReassembleTest47, 1);
#endif /* UNITTESTS */ #endif /* UNITTESTS */
} }

@ -73,6 +73,7 @@ void StreamTcpSetSessionNoReassemblyFlag (TcpSession *, char );
void StreamTcpSetOSPolicy(TcpStream *, Packet *); void StreamTcpSetOSPolicy(TcpStream *, Packet *);
void StreamTcpReassemblePause (TcpSession *, char ); void StreamTcpReassemblePause (TcpSession *, char );
void StreamTcpReassembleUnPause (TcpSession *, char ); void StreamTcpReassembleUnPause (TcpSession *, char );
int StreamTcpCheckStreamContents(uint8_t *, uint16_t , TcpStream *);
#endif /* __STREAM_TCP_REASSEMBLE_H__ */ #endif /* __STREAM_TCP_REASSEMBLE_H__ */

File diff suppressed because it is too large Load Diff

@ -35,6 +35,10 @@
#include "stream-tcp-reassemble.h" #include "stream-tcp-reassemble.h"
#define STREAM_VERBOSE FALSE #define STREAM_VERBOSE FALSE
/* Flag to indicate that the checksum validation for the stream engine
has been enabled */
#define STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION 0x01
/*global flow data*/ /*global flow data*/
typedef struct TcpStreamCnf_ { typedef struct TcpStreamCnf_ {
uint32_t memcap; /** max stream mem usage */ uint32_t memcap; /** max stream mem usage */
@ -44,6 +48,7 @@ typedef struct TcpStreamCnf_ {
int async_oneside; int async_oneside;
uint32_t reassembly_memcap; /**< max memory usage for stream reassembly */ uint32_t reassembly_memcap; /**< max memory usage for stream reassembly */
uint32_t reassembly_depth; /**< Depth until when we reassemble the stream */ uint32_t reassembly_depth; /**< Depth until when we reassemble the stream */
uint8_t flags;
} TcpStreamCnf; } TcpStreamCnf;
TcpStreamCnf stream_config; TcpStreamCnf stream_config;

@ -239,6 +239,10 @@ flow-timeouts:
# #
# stream: # stream:
# memcap: 33554432 # 32mb tcp session memcap # memcap: 33554432 # 32mb tcp session memcap
# checksum_validation: yes # To validate the checksum of received
# packet. If csum validation is specified as
# "yes", then packet with invalid csum will not
# be processed by the engine stream/app layer.
# max_sessions: 262144 # 256k concurrent sessions # max_sessions: 262144 # 256k concurrent sessions
# prealloc_sessions: 32768 # 32k sessions prealloc'd # prealloc_sessions: 32768 # 32k sessions prealloc'd
# midstream: false # don't allow midstream session pickups # midstream: false # don't allow midstream session pickups
@ -248,6 +252,7 @@ flow-timeouts:
# depth: 1048576 # 1 MB reassembly depth # depth: 1048576 # 1 MB reassembly depth
stream: stream:
memcap: 33554432 memcap: 33554432
checksum_validation: yes
reassembly: reassembly:
memcap: 67108864 memcap: 67108864
depth: 1048576 depth: 1048576

Loading…
Cancel
Save