suricata
detect-base64-data.c
Go to the documentation of this file.
1 /* Copyright (C) 2015 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 #include "suricata-common.h"
19 #include "detect.h"
20 #include "detect-engine.h"
22 #include "detect-parse.h"
23 #include "detect-base64-data.h"
24 
25 #include "util-unittest.h"
26 
27 static int DetectBase64DataSetup(DetectEngineCtx *, Signature *, const char *);
28 static void DetectBase64DataRegisterTests(void);
29 
31 {
32  sigmatch_table[DETECT_BASE64_DATA].name = "base64_data";
34  "Content match base64 decoded data.";
36  DOC_URL DOC_VERSION "/rules/payload-keywords.html#base64-data";
37  sigmatch_table[DETECT_BASE64_DATA].Setup = DetectBase64DataSetup;
39  DetectBase64DataRegisterTests;
40 
42 }
43 
44 static int DetectBase64DataSetup(DetectEngineCtx *de_ctx, Signature *s,
45  const char *str)
46 {
47  SigMatch *pm = NULL;
48 
49  /* Check for a preceding base64_decode. */
51  if (pm == NULL) {
53  "\"base64_data\" keyword seen without preceding base64_decode.");
54  return -1;
55  }
56 
58  return 0;
59 }
60 
62  DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f)
63 {
64  if (det_ctx->base64_decoded_len) {
65  return DetectEngineContentInspection(de_ctx, det_ctx, s,
69  }
70 
71  return 0;
72 }
73 
74 #ifdef UNITTESTS
75 
76 #include "detect-engine.h"
77 
78 static int g_file_data_buffer_id = 0;
79 
80 static int DetectBase64DataSetupTest01(void)
81 {
82  DetectEngineCtx *de_ctx = NULL;
83  SigMatch *sm;
84  int retval = 0;
85 
86  de_ctx = DetectEngineCtxInit();
87  if (de_ctx == NULL) {
88  goto end;
89  }
90 
91  de_ctx->flags |= DE_QUIET;
92  de_ctx->sig_list = SigInit(de_ctx,
93  "alert smtp any any -> any any (msg:\"DetectBase64DataSetupTest\"; "
94  "base64_decode; base64_data; content:\"content\"; sid:1; rev:1;)");
95  if (de_ctx->sig_list == NULL) {
96  printf("SigInit failed: ");
97  goto end;
98  }
99 
100  sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH];
101  if (sm == NULL) {
102  printf("DETECT_SM_LIST_PMATCH should not be NULL: ");
103  goto end;
104  }
105  if (sm->type != DETECT_BASE64_DECODE) {
106  printf("sm->type should be DETECT_BASE64_DECODE: ");
107  goto end;
108  }
109 
110  if (de_ctx->sig_list->sm_lists[DETECT_SM_LIST_BASE64_DATA] == NULL) {
111  printf("DETECT_SM_LIST_BASE64_DATA should not be NULL: ");
112  goto end;
113  }
114 
115  retval = 1;
116 end:
117  if (de_ctx != NULL) {
118  SigGroupCleanup(de_ctx);
119  SigCleanSignatures(de_ctx);
120  DetectEngineCtxFree(de_ctx);
121  }
122  return retval;
123 }
124 
125 static int DetectBase64DataSetupTest02(void)
126 {
127  DetectEngineCtx *de_ctx = NULL;
128  SigMatch *sm;
129  int retval = 0;
130 
131  de_ctx = DetectEngineCtxInit();
132  if (de_ctx == NULL) {
133  goto end;
134  }
135 
136  de_ctx->flags |= DE_QUIET;
137  de_ctx->sig_list = SigInit(de_ctx,
138  "alert smtp any any -> any any ( "
139  "msg:\"DetectBase64DataSetupTest\"; "
140  "file_data; "
141  "content:\"SGV\"; "
142  "base64_decode: bytes 16; "
143  "base64_data; "
144  "content:\"content\"; "
145  "sid:1; rev:1;)");
146  if (de_ctx->sig_list == NULL) {
147  printf("SigInit failed: ");
148  goto end;
149  }
150 
151  sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_PMATCH];
152  if (sm != NULL) {
153  printf("DETECT_SM_LIST_PMATCH is not NULL: ");
154  goto end;
155  }
156 
157  sm = de_ctx->sig_list->sm_lists[g_file_data_buffer_id];
158  if (sm == NULL) {
159  printf("DETECT_SM_LIST_FILEDATA is NULL: ");
160  goto end;
161  }
162 
163  sm = de_ctx->sig_list->sm_lists[DETECT_SM_LIST_BASE64_DATA];
164  if (sm == NULL) {
165  printf("DETECT_SM_LIST_BASE64_DATA is NULL: ");
166  goto end;
167  }
168 
169  retval = 1;
170 end:
171  if (de_ctx != NULL) {
172  SigGroupCleanup(de_ctx);
173  SigCleanSignatures(de_ctx);
174  DetectEngineCtxFree(de_ctx);
175  }
176  return retval;
177 }
178 
179 /**
180  * \test Test that the rule fails to load if the detection list is
181  * changed after base64_data.
182  */
183 static int DetectBase64DataSetupTest03(void)
184 {
185  DetectEngineCtx *de_ctx = NULL;
186  int retval = 0;
187 
188  de_ctx = DetectEngineCtxInit();
189  if (de_ctx == NULL) {
190  goto end;
191  }
192 
193  de_ctx->flags |= DE_QUIET;
194  de_ctx->sig_list = SigInit(de_ctx,
195  "alert smtp any any -> any any ( "
196  "msg:\"DetectBase64DataSetupTest\"; "
197  "base64_decode: bytes 16; "
198  "base64_data; "
199  "content:\"content\"; "
200  "file_data; "
201  "content:\"SGV\"; "
202  "sid:1; rev:1;)");
203  if (de_ctx->sig_list != NULL) {
204  printf("SigInit should have failed: ");
205  goto end;
206  }
207 
208  retval = 1;
209 end:
210  if (de_ctx != NULL) {
211  SigGroupCleanup(de_ctx);
212  SigCleanSignatures(de_ctx);
213  DetectEngineCtxFree(de_ctx);
214  }
215  return retval;
216 }
217 
218 /**
219  * \test Test that the list can be changed to post-detection lists
220  * after the base64 keyword.
221  */
222 static int DetectBase64DataSetupTest04(void)
223 {
224  DetectEngineCtx *de_ctx = NULL;
225  int retval = 0;
226 
227  de_ctx = DetectEngineCtxInit();
228  if (de_ctx == NULL) {
229  goto end;
230  }
231 
232  de_ctx->flags |= DE_QUIET;
233  de_ctx->sig_list = SigInit(de_ctx,
234  "alert tcp any any -> any any (msg:\"some b64thing\"; flow:established,from_server; file_data; content:\"sometext\"; fast_pattern; base64_decode:relative; base64_data; content:\"foobar\"; nocase; tag:session,120,seconds; sid:1111111; rev:1;)");
235  if (de_ctx->sig_list == NULL) {
236  printf("SigInit failed: ");
237  goto end;
238  }
239 
240  retval = 1;
241 end:
242  if (de_ctx != NULL) {
243  SigGroupCleanup(de_ctx);
244  SigCleanSignatures(de_ctx);
245  DetectEngineCtxFree(de_ctx);
246  }
247  return retval;
248 }
249 
250 #endif
251 
252 static void DetectBase64DataRegisterTests(void)
253 {
254 #ifdef UNITTESTS
255  g_file_data_buffer_id = DetectBufferTypeGetByName("file_data");
256 
257  UtRegisterTest("DetectBase64DataSetupTest01", DetectBase64DataSetupTest01);
258  UtRegisterTest("DetectBase64DataSetupTest02", DetectBase64DataSetupTest02);
259  UtRegisterTest("DetectBase64DataSetupTest03", DetectBase64DataSetupTest03);
260  UtRegisterTest("DetectBase64DataSetupTest04", DetectBase64DataSetupTest04);
261 #endif /* UNITTESTS */
262 }
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1439
SignatureInitData * init_data
Definition: detect.h:586
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1179
Signature * SigInit(DetectEngineCtx *, const char *)
Parses a signature and adds it to the Detection Engine Context.
int DetectEngineContentInspection(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, const SigMatchData *smd, Packet *p, Flow *f, uint8_t *buffer, uint32_t buffer_len, uint32_t stream_start_offset, uint8_t flags, uint8_t inspection_mode)
Run the actual payload match functions.
Signature * sig_list
Definition: detect.h:762
void SigCleanSignatures(DetectEngineCtx *de_ctx)
const char * name
Definition: detect.h:1193
Signature container.
Definition: detect.h:517
int DetectBase64DataDoMatch(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const Signature *s, Flow *f)
main detection engine ctx
Definition: detect.h:756
#define DE_QUIET
Definition: detect.h:287
int DetectBufferTypeGetByName(const char *name)
#define str(s)
uint8_t flags
Definition: detect.h:757
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void DetectBase64DataRegister(void)
SigMatchData * sm_arrays[DETECT_SM_LIST_MAX]
Definition: detect.h:570
int SigGroupCleanup(DetectEngineCtx *de_ctx)
uint8_t type
Definition: detect.h:314
const char * desc
Definition: detect.h:1195
#define SIGMATCH_NOOPT
Definition: detect.h:1362
SigMatch * DetectGetLastSMFromLists(const Signature *s,...)
Returns the sm with the largest index (added latest) from the lists passed to us. ...
Definition: detect-parse.c:407
const char * url
Definition: detect.h:1196
uint8_t * base64_decoded
Definition: detect.h:1128
#define DETECT_CI_FLAGS_SINGLE
#define DOC_URL
Definition: suricata.h:86
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1187
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
Flow data structure.
Definition: flow.h:325
void(* RegisterTests)(void)
Definition: detect.h:1185
a single match condition for a signature
Definition: detect.h:313
DetectEngineCtx * DetectEngineCtxInit(void)