suricata
detect-tls-random.c
Go to the documentation of this file.
1/* Copyright (C) 2022 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 "threads.h"
20#include "detect.h"
21
22#include "detect-parse.h"
23#include "detect-engine.h"
25#include "detect-engine-mpm.h"
26#include "detect-content.h"
27
28#include "flow.h"
29#include "stream-tcp.h"
30
31#include "app-layer.h"
32#include "app-layer-ssl.h"
34#include "detect-tls-random.h"
35
36#define DETECT_TLS_RANDOM_TIME_LEN 4
37#define DETECT_TLS_RANDOM_BYTES_LEN 28
38
39static int DetectTlsRandomTimeSetup(DetectEngineCtx *, Signature *, const char *);
40static int DetectTlsRandomBytesSetup(DetectEngineCtx *, Signature *, const char *);
41static int DetectTlsRandomSetup(DetectEngineCtx *, Signature *, const char *);
42static InspectionBuffer *GetRandomTimeData(DetectEngineThreadCtx *det_ctx,
43 const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
44 const int list_id);
45static InspectionBuffer *GetRandomBytesData(DetectEngineThreadCtx *det_ctx,
46 const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
47 const int list_id);
48static InspectionBuffer *GetRandomData(DetectEngineThreadCtx *det_ctx,
49 const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
50 const int list_id);
51
52static int g_tls_random_time_buffer_id = 0;
53static int g_tls_random_bytes_buffer_id = 0;
54static int g_tls_random_buffer_id = 0;
55
57{
58 sigmatch_table[DETECT_TLS_RANDOM_TIME].name = "tls.random_time";
59 sigmatch_table[DETECT_TLS_RANDOM_TIME].desc = "sticky buffer to match specifically and only "
60 "on the first 4 bytes of a TLS random buffer";
61 sigmatch_table[DETECT_TLS_RANDOM_TIME].url = "/rules/tls-keywords.html#tls-random-time";
62 sigmatch_table[DETECT_TLS_RANDOM_TIME].Setup = DetectTlsRandomTimeSetup;
64
65 /* Register engine for Server random */
69 GetRandomTimeData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
70
71 /* Register engine for Client random */
75 GetRandomTimeData, ALPROTO_TLS, TLS_STATE_SERVER_HELLO);
76
77 DetectBufferTypeSetDescriptionByName("tls.random_time", "TLS Random Time");
78
79 g_tls_random_time_buffer_id = DetectBufferTypeGetByName("tls.random_time");
80}
81
83{
84 sigmatch_table[DETECT_TLS_RANDOM_BYTES].name = "tls.random_bytes";
86 "sticky buffer to match specifically and only on the last 28 bytes of a TLS random "
87 "buffer";
88 sigmatch_table[DETECT_TLS_RANDOM_BYTES].url = "/rules/tls-keywords.html#tls-random-bytes";
89 sigmatch_table[DETECT_TLS_RANDOM_BYTES].Setup = DetectTlsRandomBytesSetup;
91
92 /* Register engine for Server random */
96 GetRandomBytesData, ALPROTO_TLS, TLS_STATE_CLIENT_HELLO_DONE);
97
98 /* Register engine for Client random */
102 GetRandomBytesData, ALPROTO_TLS, TLS_STATE_SERVER_HELLO);
103
104 DetectBufferTypeSetDescriptionByName("tls.random_bytes", "TLS Random Bytes");
105
106 g_tls_random_bytes_buffer_id = DetectBufferTypeGetByName("tls.random_bytes");
107}
108
109/**
110 * \brief Registration function for keyword: tls.random
111 */
113{
116
117 sigmatch_table[DETECT_TLS_RANDOM].name = "tls.random";
119 "sticky buffer to match specifically and only on a TLS random buffer";
120 sigmatch_table[DETECT_TLS_RANDOM].url = "/rules/tls-keywords.html#tls-random";
121 sigmatch_table[DETECT_TLS_RANDOM].Setup = DetectTlsRandomSetup;
123
124 /* Register engine for Server random */
126 DetectEngineInspectBufferGeneric, GetRandomData);
128 GetRandomData, ALPROTO_TLS, 0);
129
130 /* Register engine for Client random */
132 DetectEngineInspectBufferGeneric, GetRandomData);
134 GetRandomData, ALPROTO_TLS, 0);
135
136 DetectBufferTypeSetDescriptionByName("tls.random", "TLS Random");
137
138 g_tls_random_buffer_id = DetectBufferTypeGetByName("tls.random");
139}
140
141/**
142 * \brief this function setup the tls.random_time sticky buffer keyword used in the rule
143 *
144 * \param de_ctx Pointer to the Detection Engine Context
145 * \param s Pointer to the Signature to which the current keyword belongs
146 * \param str Should hold an empty string always
147 *
148 * \retval 0 On success
149 * \retval -1 On failure
150 */
151static int DetectTlsRandomTimeSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
152{
153 if (SCDetectBufferSetActiveList(de_ctx, s, g_tls_random_time_buffer_id) < 0)
154 return -1;
155
157 return -1;
158
159 return 0;
160}
161
162/**
163 * \brief this function setup the tls.random_bytes sticky buffer keyword used in the rule
164 *
165 * \param de_ctx Pointer to the Detection Engine Context
166 * \param s Pointer to the Signature to which the current keyword belongs
167 * \param str Should hold an empty string always
168 *
169 * \retval 0 On success
170 * \retval -1 On failure
171 */
172static int DetectTlsRandomBytesSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
173{
174 if (SCDetectBufferSetActiveList(de_ctx, s, g_tls_random_bytes_buffer_id) < 0)
175 return -1;
176
178 return -1;
179
180 return 0;
181}
182
183/**
184 * \brief this function setup the tls.random sticky buffer keyword used in the rule
185 *
186 * \param de_ctx Pointer to the Detection Engine Context
187 * \param s Pointer to the Signature to which the current keyword belongs
188 * \param str Should hold an empty string always
189 *
190 * \retval 0 On success
191 * \retval -1 On failure
192 */
193static int DetectTlsRandomSetup(DetectEngineCtx *de_ctx, Signature *s, const char *str)
194{
195 if (SCDetectBufferSetActiveList(de_ctx, s, g_tls_random_buffer_id) < 0)
196 return -1;
197
199 return -1;
200
201 return 0;
202}
203
204static InspectionBuffer *GetRandomTimeData(DetectEngineThreadCtx *det_ctx,
205 const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
206 const int list_id)
207{
208 InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
209 if (buffer->inspect == NULL) {
210 const SSLState *ssl_state = (SSLState *)f->alstate;
211 if (flow_flags & STREAM_TOSERVER) {
212 if (!(ssl_state->flags & TLS_TS_RANDOM_SET))
213 return NULL;
214 } else {
215 if (!(ssl_state->flags & TLS_TC_RANDOM_SET))
216 return NULL;
217 }
218 const uint32_t data_len = DETECT_TLS_RANDOM_TIME_LEN;
219 const uint8_t *data;
220 if (flow_flags & STREAM_TOSERVER) {
221 data = ssl_state->client_connp.random;
222 } else {
223 data = ssl_state->server_connp.random;
224 }
226 det_ctx, list_id, buffer, data, data_len, transforms);
227 }
228 return buffer;
229}
230
231static InspectionBuffer *GetRandomBytesData(DetectEngineThreadCtx *det_ctx,
232 const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
233 const int list_id)
234{
235 InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
236 if (buffer->inspect == NULL) {
237 const SSLState *ssl_state = (SSLState *)f->alstate;
238 if (flow_flags & STREAM_TOSERVER) {
239 if (!(ssl_state->flags & TLS_TS_RANDOM_SET))
240 return NULL;
241 } else {
242 if (!(ssl_state->flags & TLS_TC_RANDOM_SET))
243 return NULL;
244 }
245 const uint32_t data_len = DETECT_TLS_RANDOM_BYTES_LEN;
246 const uint8_t *data;
247 if (flow_flags & STREAM_TOSERVER) {
248 data = ssl_state->client_connp.random + DETECT_TLS_RANDOM_TIME_LEN;
249 } else {
250 data = ssl_state->server_connp.random + DETECT_TLS_RANDOM_TIME_LEN;
251 }
253 det_ctx, list_id, buffer, data, data_len, transforms);
254 }
255 return buffer;
256}
257
258static InspectionBuffer *GetRandomData(DetectEngineThreadCtx *det_ctx,
259 const DetectEngineTransforms *transforms, Flow *f, const uint8_t flow_flags, void *txv,
260 const int list_id)
261{
262 InspectionBuffer *buffer = InspectionBufferGet(det_ctx, list_id);
263 if (buffer->inspect == NULL) {
264 const SSLState *ssl_state = (SSLState *)f->alstate;
265 if (flow_flags & STREAM_TOSERVER) {
266 if (!(ssl_state->flags & TLS_TS_RANDOM_SET))
267 return NULL;
268 } else {
269 if (!(ssl_state->flags & TLS_TC_RANDOM_SET))
270 return NULL;
271 }
272 const uint32_t data_len = TLS_RANDOM_LEN;
273 const uint8_t *data;
274 if (flow_flags & STREAM_TOSERVER) {
275 data = ssl_state->client_connp.random;
276 } else {
277 data = ssl_state->server_connp.random;
278 }
280 det_ctx, list_id, buffer, data, data_len, transforms);
281 }
282 return buffer;
283}
@ ALPROTO_TLS
#define TLS_TS_RANDOM_SET
#define TLS_TC_RANDOM_SET
@ TLS_STATE_CLIENT_HELLO_DONE
@ TLS_STATE_SERVER_HELLO
#define TLS_RANDOM_LEN
int SCDetectBufferSetActiveList(DetectEngineCtx *de_ctx, Signature *s, const int list)
void InspectionBufferSetupAndApplyTransforms(DetectEngineThreadCtx *det_ctx, const int list_id, InspectionBuffer *buffer, const uint8_t *data, const uint32_t data_len, const DetectEngineTransforms *transforms)
setup the buffer with our initial data
InspectionBuffer * InspectionBufferGet(DetectEngineThreadCtx *det_ctx, const int list_id)
void DetectAppLayerMpmRegister(const char *name, int direction, int priority, PrefilterRegisterFunc PrefilterRegister, InspectionBufferGetDataPtr GetData, AppProto alproto, int tx_min_progress)
register an app layer keyword for mpm
int PrefilterGenericMpmRegister(DetectEngineCtx *de_ctx, SigGroupHead *sgh, MpmCtx *mpm_ctx, const DetectBufferMpmRegistry *mpm_reg, int list_id)
@ DETECT_TLS_RANDOM
@ DETECT_TLS_RANDOM_BYTES
@ DETECT_TLS_RANDOM_TIME
void DetectBufferTypeSetDescriptionByName(const char *name, const char *desc)
uint8_t 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.
void DetectAppLayerInspectEngineRegister(const char *name, AppProto alproto, uint32_t dir, int progress, InspectEngineFuncPtr Callback, InspectionBufferGetDataPtr GetData)
Registers an app inspection engine.
int DetectBufferTypeGetByName(const char *name)
int SCDetectSignatureSetAppProto(Signature *s, AppProto alproto)
SigTableElmt * sigmatch_table
#define DETECT_TLS_RANDOM_TIME_LEN
#define DETECT_TLS_RANDOM_BYTES_LEN
void DetectTlsRandomRegister(void)
Registration function for keyword: tls.random.
void DetectTlsRandomBytesRegister(void)
void DetectTlsRandomTimeRegister(void)
#define SIGMATCH_NOOPT
Definition detect.h:1651
#define SIG_FLAG_TOCLIENT
Definition detect.h:272
#define SIGMATCH_INFO_STICKY_BUFFER
Definition detect.h:1676
#define SIG_FLAG_TOSERVER
Definition detect.h:271
DetectEngineCtx * de_ctx
main detection engine ctx
Definition detect.h:932
Flow data structure.
Definition flow.h:356
void * alstate
Definition flow.h:479
SSLv[2.0|3.[0|1|2|3]] state structure.
const char * url
Definition detect.h:1462
int(* Setup)(DetectEngineCtx *, Signature *, const char *)
Definition detect.h:1441
uint16_t flags
Definition detect.h:1450
const char * desc
Definition detect.h:1461
const char * name
Definition detect.h:1459
Signature container.
Definition detect.h:668
#define str(s)