suricata
fuzz_applayerparserparse.c
Go to the documentation of this file.
1 /**
2  * @file
3  * @author Philippe Antoine <contact@catenacyber.fr>
4  * fuzz target for AppLayerParserParse
5  */
6 
7 #include "suricata-common.h"
8 #include "suricata.h"
10 #include "flow-util.h"
11 #include "app-layer-parser.h"
12 #include "util-unittest-helper.h"
13 #include "util-byte.h"
14 #include "conf-yaml-loader.h"
15 #include "util-conf.h"
16 #include "rust.h"
17 #include "nallocinc.c"
18 
19 #define HEADER_LEN 6
20 
21 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
22 int LLVMFuzzerInitialize(int *argc, char ***argv);
23 
25 
26 extern const char *configNoChecksum;
27 
28 /* input buffer is structured this way :
29  * 6 bytes header,
30  * then sequence of buffers separated by magic bytes 01 D5 CA 7A */
31 
32 /* The 6 bytes header is
33  * alproto
34  * proto
35  * source port (uint16_t)
36  * destination port (uint16_t) */
37 
38 const uint8_t separator[] = {0x01, 0xD5, 0xCA, 0x7A};
41 char *target_suffix = NULL;
42 SC_ATOMIC_EXTERN(unsigned int, engine_stage);
43 
44 int LLVMFuzzerInitialize(int *argc, char ***argv)
45 {
46  target_suffix = getenv("FUZZ_APPLAYER");
47  // else
48  if (!target_suffix) {
49  target_suffix = strrchr((*argv)[0], '_');
50  }
51  nalloc_init((*argv)[0]);
53  return 0;
54 }
55 
56 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
57 {
58  Flow * f;
59  TcpSession ssn;
60  const uint8_t * albuffer;
61  uint8_t * alnext;
62  size_t alsize;
63  // used to find under and overflows
64  // otherwise overflows do not fail as they read the next packet
65  uint8_t * isolatedBuffer;
66 
67  if (alp_tctx == NULL) {
68  //Redirects logs to /dev/null
69  setenv("SC_LOG_OP_IFACE", "file", 0);
70  setenv("SC_LOG_FILE", "/dev/null", 0);
71 
72  InitGlobal();
75 
76  //redirect logs to /tmp
77  ConfigSetLogDirectory("/tmp/");
78  // disables checksums validation for fuzzing
80  abort();
81  }
82 
85  SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
86  if (target_suffix != NULL) {
87  AppProto applayer = StringToAppProto(target_suffix + 1);
88  if (applayer != ALPROTO_UNKNOWN) {
89  forceLayer = applayer;
90  printf("Forcing %s=%" PRIu16 "\n", AppProtoToString(forceLayer), forceLayer);
91  }
92  }
93  // http is the output name, but we want to fuzz HTTP1
94  if (forceLayer == ALPROTO_HTTP) {
96  }
97  }
98 
99  if (size < HEADER_LEN) {
100  return 0;
101  }
102 
103  if (data[0] >= g_alproto_max) {
104  return 0;
105  }
106  //no UTHBuildFlow to have storage
107  f = FlowAlloc();
108  if (f == NULL) {
109  return 0;
110  }
112  f->src.addr_data32[0] = 0x01020304;
113  f->dst.addr_data32[0] = 0x05060708;
114  f->sp = (uint16_t)((data[2] << 8) | data[3]);
115  f->dp = (uint16_t)((data[4] << 8) | data[5]);
116  f->proto = data[1];
117  memset(&ssn, 0, sizeof(TcpSession));
118  f->protoctx = &ssn;
120  if (forceLayer > 0) {
121  f->alproto = forceLayer;
122  } else {
123  f->alproto = data[0];
124  }
125 
126  nalloc_start(data, size);
127  FLOWLOCK_WRLOCK(f);
128  /*
129  * We want to fuzz multiple calls to AppLayerParserParse
130  * because some parts of the code are only reached after
131  * multiple packets (in SMTP for example).
132  * So we treat our input as a list of buffers with magic separator.
133  */
134  albuffer = data + HEADER_LEN;
135  alsize = size - HEADER_LEN;
136  uint8_t flags = STREAM_START;
137  int flip = 0;
138  alnext = memmem(albuffer, alsize, separator, 4);
139  while (alnext) {
140  if (flip) {
141  flags |= STREAM_TOCLIENT;
142  flags &= ~(STREAM_TOSERVER);
143  flip = 0;
144  } else {
145  flags |= STREAM_TOSERVER;
146  flags &= ~(STREAM_TOCLIENT);
147  flip = 1;
148  }
149 
150  if (alnext != albuffer) {
151  // only if we have some data
152  isolatedBuffer = malloc(alnext - albuffer);
153  if (isolatedBuffer == NULL) {
154  goto bail;
155  }
156  memcpy(isolatedBuffer, albuffer, alnext - albuffer);
157  (void)AppLayerParserParse(NULL, alp_tctx, f, f->alproto, flags, isolatedBuffer,
158  (uint32_t)(alnext - albuffer));
159  free(isolatedBuffer);
160  if (FlowChangeProto(f)) {
161  // exits if a protocol change is requested
162  alsize = 0;
163  break;
164  }
165  flags &= ~(STREAM_START);
166  if (f->alparser &&
167  (((flags & STREAM_TOSERVER) != 0 && SCAppLayerParserStateIssetFlag(f->alparser,
169  ((flags & STREAM_TOCLIENT) != 0 &&
172  //no final chunk
173  alsize = 0;
174  break;
175  }
176 
177  AppLayerParserTransactionsCleanup(f, flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
178  }
179  alsize -= alnext - albuffer + 4;
180  albuffer = alnext + 4;
181  if (alsize == 0) {
182  break;
183  }
184  alnext = memmem(albuffer, alsize, separator, 4);
185  }
186  if (alsize > 0 ) {
187  if (flip) {
188  flags |= STREAM_TOCLIENT;
189  flags &= ~(STREAM_TOSERVER);
190  flip = 0;
191  } else {
192  flags |= STREAM_TOSERVER;
193  flags &= ~(STREAM_TOCLIENT);
194  flip = 1;
195  }
196  flags |= STREAM_EOF;
197  isolatedBuffer = malloc(alsize);
198  if (isolatedBuffer == NULL) {
199  goto bail;
200  }
201  memcpy(isolatedBuffer, albuffer, alsize);
202  (void)AppLayerParserParse(
203  NULL, alp_tctx, f, f->alproto, flags, isolatedBuffer, (uint32_t)alsize);
204  free(isolatedBuffer);
205  }
206 
207 bail:
208  FLOWLOCK_UNLOCK(f);
209  FlowFree(f);
210  nalloc_end();
211 
212  return 0;
213 }
util-byte.h
SCConfYamlLoadString
int SCConfYamlLoadString(const char *string, size_t len)
Load configuration from a YAML string.
Definition: conf-yaml-loader.c:535
SCAppLayerParserStateIssetFlag
uint16_t SCAppLayerParserStateIssetFlag(AppLayerParserState *pstate, uint16_t flag)
Definition: app-layer-parser.c:1833
surifuzz
SCInstance surifuzz
Definition: fuzz_applayerparserparse.c:39
flow-util.h
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:386
AppLayerParserTransactionsCleanup
void AppLayerParserTransactionsCleanup(Flow *f, const uint8_t pkt_dir)
remove obsolete (inspected and logged) transactions
Definition: app-layer-parser.c:889
FLOW_SGH_TOCLIENT
#define FLOW_SGH_TOCLIENT
Definition: flow.h:75
Flow_::proto
uint8_t proto
Definition: flow.h:370
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:86
LLVMFuzzerInitialize
int LLVMFuzzerInitialize(int *argc, char ***argv)
Definition: fuzz_applayerparserparse.c:44
configNoChecksum
const char * configNoChecksum
Definition: confyaml.c:1
Flow_
Flow data structure.
Definition: flow.h:348
Flow_::protomap
uint8_t protomap
Definition: flow.h:437
AppProtoToString
const char * AppProtoToString(AppProto alproto)
Maps the ALPROTO_*, to its string equivalent.
Definition: app-layer-protos.c:41
rust.h
GlobalsInitPreConfig
void GlobalsInitPreConfig(void)
Definition: suricata.c:385
Flow_::dp
Port dp
Definition: flow.h:364
HEADER_LEN
#define HEADER_LEN
Definition: fuzz_applayerparserparse.c:19
APP_LAYER_PARSER_EOF_TS
#define APP_LAYER_PARSER_EOF_TS
Definition: app-layer-parser.h:53
Flow_::protoctx
void * protoctx
Definition: flow.h:433
FLOW_IPV4
#define FLOW_IPV4
Definition: flow.h:100
nallocinc.c
util-unittest-helper.h
FLOWLOCK_UNLOCK
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:265
SCRunmodeSet
void SCRunmodeSet(SCRunMode run_mode)
Set the current run mode.
Definition: suricata.c:287
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:470
Flow_::dst
FlowAddress dst
Definition: flow.h:351
app-layer-detect-proto.h
separator
const uint8_t separator[]
Definition: fuzz_applayerparserparse.c:38
g_alproto_max
AppProto g_alproto_max
Definition: app-layer-protos.c:30
SURICATA_RUNTIME
@ SURICATA_RUNTIME
Definition: suricata.h:101
alp_tctx
AppLayerParserThreadCtx * alp_tctx
Definition: fuzz_applayerparserparse.c:24
StringToAppProto
AppProto StringToAppProto(const char *proto_name)
Maps a string to its ALPROTO_* equivalent.
Definition: app-layer-protos.c:61
FLOWLOCK_WRLOCK
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:262
PostConfLoadedSetup
int PostConfLoadedSetup(SCInstance *suri)
Definition: suricata.c:2736
app-layer-parser.h
FlowGetProtoMapping
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:99
conf-yaml-loader.h
APP_LAYER_PARSER_EOF_TC
#define APP_LAYER_PARSER_EOF_TC
Definition: app-layer-parser.h:54
setenv
void setenv(const char *name, const char *value, int overwrite)
Flow_::src
FlowAddress src
Definition: flow.h:351
target_suffix
char * target_suffix
Definition: fuzz_applayerparserparse.c:41
AppLayerParserThreadCtxAlloc
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol's parser thread context.
Definition: app-layer-parser.c:297
nalloc_init
#define nalloc_init(x)
Definition: nallocinc.c:49
util-conf.h
flags
uint8_t flags
Definition: decode-gre.h:0
AppLayerParserParse
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, const uint8_t *input, uint32_t input_len)
Definition: app-layer-parser.c:1277
suricata-common.h
nalloc_start
#define nalloc_start(x, y)
Definition: nallocinc.c:51
FlowFree
void FlowFree(Flow *f)
cleanup & free the memory of a flow
Definition: flow-util.c:84
ALPROTO_HTTP1
@ ALPROTO_HTTP1
Definition: app-layer-protos.h:36
nalloc_end
#define nalloc_end()
Definition: nallocinc.c:52
ConfigSetLogDirectory
TmEcode ConfigSetLogDirectory(const char *name)
Definition: util-conf.c:33
FLOW_SGH_TOSERVER
#define FLOW_SGH_TOSERVER
Definition: flow.h:73
Flow_::flags
uint32_t flags
Definition: flow.h:413
ALPROTO_HTTP
@ ALPROTO_HTTP
Definition: app-layer-protos.h:76
ALPROTO_UNKNOWN
@ ALPROTO_UNKNOWN
Definition: app-layer-protos.h:29
suricata.h
nalloc_restrict_file_prefix
#define nalloc_restrict_file_prefix(x)
Definition: nallocinc.c:50
SCInstance_
Definition: suricata.h:133
SC_ATOMIC_EXTERN
SC_ATOMIC_EXTERN(unsigned int, engine_stage)
AppLayerParserThreadCtx_
Definition: app-layer-parser.c:60
InitGlobal
int InitGlobal(void)
Global initialization common to all runmodes.
Definition: suricata.c:2985
FlowChangeProto
int FlowChangeProto(Flow *f)
Check if change proto flag is set for flow.
Definition: flow.c:197
Flow_::sp
Port sp
Definition: flow.h:353
TcpSession_
Definition: stream-tcp-private.h:283
FlowAlloc
Flow * FlowAlloc(void)
allocate a flow
Definition: flow-util.c:56
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:442
RUNMODE_PCAP_FILE
@ RUNMODE_PCAP_FILE
Definition: runmodes.h:30
LLVMFuzzerTestOneInput
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
Definition: fuzz_applayerparserparse.c:56
forceLayer
AppProto forceLayer
Definition: fuzz_applayerparserparse.c:40