suricata
detect-tls-ja3-string.c
Go to the documentation of this file.
1 /* Copyright (C) 2017 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 /**
19  * \file
20  *
21  * \author Mats Klepsland <mats.klepsland@gmail.com>
22  *
23  * Implements support for ja3_string keyword.
24  */
25 
26 #include "suricata-common.h"
27 #include "threads.h"
28 #include "debug.h"
29 #include "decode.h"
30 #include "detect.h"
31 
32 #include "detect-parse.h"
33 #include "detect-engine.h"
34 #include "detect-engine-mpm.h"
36 #include "detect-content.h"
37 #include "detect-pcre.h"
38 #include "detect-tls-ja3-string.h"
39 
40 #include "flow.h"
41 #include "flow-util.h"
42 #include "flow-var.h"
43 
44 #include "conf.h"
45 #include "conf-yaml-loader.h"
46 
47 #include "util-debug.h"
48 #include "util-unittest.h"
49 #include "util-spm.h"
50 #include "util-print.h"
51 #include "util-ja3.h"
52 
53 #include "stream-tcp.h"
54 
55 #include "app-layer.h"
56 #include "app-layer-ssl.h"
57 
58 #include "util-unittest.h"
59 #include "util-unittest-helper.h"
60 
61 static int DetectTlsJa3StringSetup(DetectEngineCtx *, Signature *, const char *);
62 static void DetectTlsJa3StringRegisterTests(void);
63 static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
64  const DetectEngineTransforms *transforms,
65  Flow *_f, const uint8_t _flow_flags,
66  void *txv, const int list_id);
67 static int g_tls_ja3_str_buffer_id = 0;
68 
69 /**
70  * \brief Registration function for keyword: ja3_string
71  */
73 {
75  sigmatch_table[DETECT_AL_TLS_JA3_STRING].desc = "content modifier to match the JA3 string buffer";
76  sigmatch_table[DETECT_AL_TLS_JA3_STRING].url = DOC_URL DOC_VERSION "/rules/ja3-keywords.html#ja3-string";
78  sigmatch_table[DETECT_AL_TLS_JA3_STRING].Setup = DetectTlsJa3StringSetup;
80  sigmatch_table[DETECT_AL_TLS_JA3_STRING].RegisterTests = DetectTlsJa3StringRegisterTests;
81 
83 
86 
89 
90  DetectBufferTypeSetDescriptionByName("ja3_string", "TLS JA3 string");
91 
92  g_tls_ja3_str_buffer_id = DetectBufferTypeGetByName("ja3_string");
93 }
94 
95 /**
96  * \brief this function setup the ja3_string modifier keyword used in the rule
97  *
98  * \param de_ctx Pointer to the Detection Engine Context
99  * \param s Pointer to the Signature to which the current keyword belongs
100  * \param str Should hold an empty string always
101  *
102  * \retval 0 On success
103  */
104 static int DetectTlsJa3StringSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
105 {
106  DetectBufferSetActiveList(s, g_tls_ja3_str_buffer_id);
107  s->alproto = ALPROTO_TLS;
108 
109  if (RunmodeIsUnittests())
110  return 0;
111 
112  /* Check if JA3 is disabled */
113  if (Ja3IsDisabled("rule"))
114  return -1;
115 
116  return 0;
117 }
118 
119 static InspectionBuffer *GetData(DetectEngineThreadCtx *det_ctx,
120  const DetectEngineTransforms *transforms, Flow *_f,
121  const uint8_t _flow_flags, void *txv, const int list_id)
122 {
123  InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
124  if (buffer->inspect == NULL) {
125  SSLState *ssl_state = (SSLState *)_f->alstate;
126 
127  if (ssl_state->ja3_str == NULL ||
128  ssl_state->ja3_str->data == NULL) {
129  return NULL;
130  }
131 
132  const uint32_t data_len = strlen(ssl_state->ja3_str->data);
133  const uint8_t *data = (uint8_t *)ssl_state->ja3_str->data;
134 
135  InspectionBufferSetup(buffer, data, data_len);
136  InspectionBufferApplyTransforms(buffer, transforms);
137  }
138 
139  return buffer;
140 }
141 
142 #ifndef HAVE_NSS
143 
144 static void DetectTlsJa3StringRegisterTests(void)
145 {
146  /* Don't register any tests */
147 }
148 
149 #else /* HAVE_NSS */
150 
151 #ifdef UNITTESTS
152 
153 /**
154  * \test Test matching on a simple client hello packet
155  */
156 static int DetectTlsJa3StringTest01(void)
157 {
158  /* Client hello */
159  uint8_t buf[] = { 0x16, 0x03, 0x03, 0x00, 0x82, 0x01, 0x00, 0x00, 0x7E,
160  0x03, 0x03, 0x57, 0x04, 0x9F, 0x5D, 0xC9, 0x5C, 0x87,
161  0xAE, 0xF2, 0xA7, 0x4A, 0xFC, 0x59, 0x78, 0x23, 0x31,
162  0x61, 0x2D, 0x29, 0x92, 0xB6, 0x70, 0xA5, 0xA1, 0xFC,
163  0x0E, 0x79, 0xFE, 0xC3, 0x97, 0x37, 0xC0, 0x00, 0x00,
164  0x44, 0x00, 0x04, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0D,
165  0x00, 0x10, 0x00, 0x13, 0x00, 0x16, 0x00, 0x2F, 0x00,
166  0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x35,
167  0x00, 0x36, 0x00, 0x37, 0x00, 0x38, 0x00, 0x39, 0x00,
168  0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, 0x40,
169  0x00, 0x41, 0x00, 0x44, 0x00, 0x45, 0x00, 0x66, 0x00,
170  0x67, 0x00, 0x68, 0x00, 0x69, 0x00, 0x6A, 0x00, 0x6B,
171  0x00, 0x84, 0x00, 0x87, 0x00, 0xFF, 0x01, 0x00, 0x00,
172  0x13, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0D, 0x00, 0x00,
173  0x0A, 0x67, 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x2E, 0x63,
174  0x6F, 0x6D, };
175 
176 
177  Flow f;
178  SSLState *ssl_state = NULL;
179  Packet *p = NULL;
180  Signature *s = NULL;
181  ThreadVars tv;
182  DetectEngineThreadCtx *det_ctx = NULL;
183  TcpSession ssn;
185 
186  memset(&tv, 0, sizeof(ThreadVars));
187  memset(&f, 0, sizeof(Flow));
188  memset(&ssn, 0, sizeof(TcpSession));
189 
190  p = UTHBuildPacketReal(buf, sizeof(buf), IPPROTO_TCP,
191  "192.168.1.5", "192.168.1.1",
192  41424, 443);
193 
194  FLOW_INITIALIZE(&f);
195  f.protoctx = (void *)&ssn;
196  f.flags |= FLOW_IPV4;
197  f.proto = IPPROTO_TCP;
199 
200  p->flow = &f;
203  f.alproto = ALPROTO_TLS;
204 
206 
208  FAIL_IF_NULL(de_ctx);
209 
211  de_ctx->flags |= DE_QUIET;
212 
213  s = DetectEngineAppendSig(de_ctx, "alert tls any any -> any any "
214  "(msg:\"Test ja3_string\"; ja3_string; "
215  "content:\"-65-68-69-102-103-104-105-106-107-132-135-255,0,,\"; "
216  "sid:1;)");
217  FAIL_IF_NULL(s);
218 
219  SigGroupBuild(de_ctx);
220  DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
221 
222  FLOWLOCK_WRLOCK(&f);
223  int r = AppLayerParserParse(NULL, alp_tctx, &f, ALPROTO_TLS,
224  STREAM_TOSERVER, buf, sizeof(buf));
225  FLOWLOCK_UNLOCK(&f);
226  FAIL_IF(r != 0);
227 
228  ssl_state = f.alstate;
229  FAIL_IF_NULL(ssl_state);
230 
231  FAIL_IF_NULL(ssl_state->ja3_str);
232  FAIL_IF_NULL(ssl_state->ja3_str->data);
233 
234  SigMatchSignatures(&tv, de_ctx, det_ctx, p);
235 
237 
238  AppLayerParserThreadCtxFree(alp_tctx);
239  DetectEngineThreadCtxDeinit(&tv, det_ctx);
240  DetectEngineCtxFree(de_ctx);
241 
243  FLOW_DESTROY(&f);
244  UTHFreePacket(p);
245 
246  PASS;
247 }
248 
249 #endif /* UNITTESTS */
250 
251 static void DetectTlsJa3StringRegisterTests(void)
252 {
253 #ifdef UNITTESTS
254  UtRegisterTest("DetectTlsJa3StringTest01", DetectTlsJa3StringTest01);
255 #endif /* UNITTESTS */
256 }
257 
258 #endif /* HAVE_NSS */
Signature * DetectEngineAppendSig(DetectEngineCtx *de_ctx, const char *sigstr)
Parse and append a Signature into the Detection Engine Context signature list.
SigTableElmt sigmatch_table[DETECT_TBLSIZE]
Definition: detect.h:1403
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition: detect.h:1146
struct Flow_ * flow
Definition: decode.h:444
int PacketAlertCheck(Packet *p, uint32_t sid)
Check if a certain sid alerted, this is used in the test functions.
uint8_t proto
Definition: flow.h:346
#define FLOWLOCK_UNLOCK(fb)
Definition: flow.h:235
#define PASS
Pass the test.
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectMpmAppLayerRegistery *mpm_reg, int list_id)
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
void AppLayerParserThreadCtxFree(AppLayerParserThreadCtx *tctx)
Destroys the app layer parser thread context obtained using AppLayerParserThreadCtxAlloc().
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:95
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:195
char * data
Definition: util-ja3.h:30
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
#define FLOWLOCK_WRLOCK(fb)
Definition: flow.h:232
int Ja3IsDisabled(const char *type)
Check if JA3 is disabled.
Definition: util-ja3.c:262
TmEcode DetectEngineThreadCtxInit(ThreadVars *, void *, void **)
initialize thread specific detection engine context
InspectionBuffer * InspectionBufferGet(DetectEngineThreadCtx *det_ctx, const int list_id)
const char * name
Definition: detect.h:1160
Signature container.
Definition: detect.h:492
#define TRUE
void * protoctx
Definition: flow.h:398
main detection engine ctx
Definition: detect.h:720
TmEcode DetectEngineThreadCtxDeinit(ThreadVars *, void *)
SSLv[2.0|3.[0|1|2|3]] state structure.
void * alstate
Definition: flow.h:436
#define DE_QUIET
Definition: detect.h:298
int DetectBufferTypeGetByName(const char *name)
#define str(s)
uint8_t flags
Definition: detect.h:721
void(* Free)(void *)
Definition: detect.h:1151
#define FLOW_DESTROY(f)
Definition: flow-util.h:115
int SigGroupBuild(DetectEngineCtx *de_ctx)
Convert the signature list into the runtime match structure.
uint16_t mpm_matcher
Definition: detect.h:769
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p)
wrapper for old tests
Definition: detect.c:1752
#define SIG_FLAG_TOSERVER
Definition: detect.h:243
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
void DetectAppLayerInspectEngineRegister2(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr2 Callback2, InspectionBufferGetDataPtr GetData)
register inspect engine at start up time
Packet * UTHBuildPacketReal(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, const char *src, const char *dst, uint16_t sport, uint16_t dport)
UTHBuildPacketReal is a function that create tcp/udp packets for unittests specifying ip and port sou...
uint8_t flowflags
Definition: decode.h:438
#define FLOW_PKT_TOSERVER
Definition: flow.h:193
AppProto alproto
Definition: detect.h:496
AppLayerParserThreadCtx * AppLayerParserThreadCtxAlloc(void)
Gets a new app layer protocol&#39;s parser thread context.
JA3Buffer * ja3_str
int RunmodeIsUnittests(void)
Definition: suricata.c:261
int DetectEngineInspectBufferGeneric(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, const DetectEngineAppInspectionEngine *engine, const Signature *s, Flow *f, uint8_t flags, void *alstate, void *txv, uint64_t tx_id)
Do the content inspection & validation for a signature.
const char * desc
Definition: detect.h:1162
int mpm_default_matcher
Definition: util-mpm.h:166
void InspectionBufferSetup(InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len)
setup the buffer with our initial data
void InspectionBufferApplyTransforms(InspectionBuffer *buffer, const DetectEngineTransforms *transforms)
void DetectTlsJa3StringRegister(void)
Registration function for keyword: ja3_string.
#define SIGMATCH_NOOPT
Definition: detect.h:1328
int(* Match)(ThreadVars *, DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *)
Definition: detect.h:1129
const char * url
Definition: detect.h:1163
#define FLOW_INITIALIZE(f)
Definition: flow-util.h:39
#define STREAM_TOSERVER
Definition: stream.h:31
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself...
#define PKT_HAS_FLOW
Definition: decode.h:1101
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
int DetectBufferSetActiveList(Signature *s, const int list)
const uint8_t * inspect
Definition: detect.h:349
#define DOC_URL
Definition: suricata.h:86
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
Per thread variable structure.
Definition: threadvars.h:57
AppProto alproto
application level protocol
Definition: flow.h:407
uint32_t flags
Definition: decode.h:442
#define DOC_VERSION
Definition: suricata.h:91
uint16_t flags
Definition: detect.h:1154
void DetectEngineCtxFree(DetectEngineCtx *)
Free a DetectEngineCtx::
uint8_t protomap
Definition: flow.h:402
Flow data structure.
Definition: flow.h:327
#define FLOW_IPV4
Definition: flow.h:93
uint32_t flags
Definition: flow.h:377
#define PKT_STREAM_EST
Definition: decode.h:1099
void(* RegisterTests)(void)
Definition: detect.h:1152
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
int AppLayerParserParse(ThreadVars *tv, AppLayerParserThreadCtx *alp_tctx, Flow *f, AppProto alproto, uint8_t flags, uint8_t *input, uint32_t input_len)
DetectEngineCtx * DetectEngineCtxInit(void)
void DetectAppLayerMpmRegister2(const char *name, int direction, int priority, int(*PrefilterRegister)(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectMpmAppLayerRegistery *mpm_reg, int list_id), InspectionBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
register a MPM engine