Skip to content

Commit 46da609

Browse files
catenacybervictorjulien
authored andcommitted
detect/ssl: properly handle negation in ssl_version keyword
Ticket: 3220 DetectSslVersionMatch did not handle properly negation. It could never match on a signatrue with ssl_version: !tls1.3 That is because, if we had such a signature and network traffic with tls1.1, we were looking into DetectSslVersionData field for tls1.1, which was not set, instead of looking at field for tls1.3 which was set with negated flag. Previous DetectSslVersionData was holding redundant information. It did not need to have it for each ssl version, but just globally. Also, it did not need to hold the version as a value in the array, as it was redundant with the index of the array. (cherry picked from commit c93e698)
1 parent 8774212 commit 46da609

4 files changed

Lines changed: 42 additions & 59 deletions

File tree

doc/userguide/rules/tls-keywords.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ Example::
214214
alert tls any any -> any any (msg:"match SSLv2 and SSLv3"; \
215215
ssl_version:sslv2,sslv3; sid:200031;)
216216

217+
The list can be prefixed with ``!`` to match if version is different than
218+
all the versions listed in the signature. Such a negation does not match
219+
on a yet undetermined version.
220+
217221
tls.fingerprint
218222
---------------
219223

src/detect-ssl-version.c

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static int DetectSslVersionMatch(DetectEngineThreadCtx *det_ctx,
9898

9999
int ret = 0;
100100
uint16_t ver = 0;
101-
uint8_t sig_ver = TLS_UNKNOWN;
101+
bool sig_ver = false;
102102

103103
const DetectSslVersionData *ssl = (const DetectSslVersionData *)m;
104104
SSLState *app_state = (SSLState *)state;
@@ -119,29 +119,29 @@ static int DetectSslVersionMatch(DetectEngineThreadCtx *det_ctx,
119119

120120
switch (ver) {
121121
case SSL_VERSION_2:
122-
if (ver == ssl->data[SSLv2].ver)
122+
if (ssl->data[SSLv2])
123123
ret = 1;
124-
sig_ver = SSLv2;
124+
sig_ver = true;
125125
break;
126126
case SSL_VERSION_3:
127-
if (ver == ssl->data[SSLv3].ver)
127+
if (ssl->data[SSLv3])
128128
ret = 1;
129-
sig_ver = SSLv3;
129+
sig_ver = true;
130130
break;
131131
case TLS_VERSION_10:
132-
if (ver == ssl->data[TLS10].ver)
132+
if (ssl->data[TLS10])
133133
ret = 1;
134-
sig_ver = TLS10;
134+
sig_ver = true;
135135
break;
136136
case TLS_VERSION_11:
137-
if (ver == ssl->data[TLS11].ver)
137+
if (ssl->data[TLS11])
138138
ret = 1;
139-
sig_ver = TLS11;
139+
sig_ver = true;
140140
break;
141141
case TLS_VERSION_12:
142-
if (ver == ssl->data[TLS12].ver)
142+
if (ssl->data[TLS12])
143143
ret = 1;
144-
sig_ver = TLS12;
144+
sig_ver = true;
145145
break;
146146
case TLS_VERSION_13_DRAFT28:
147147
case TLS_VERSION_13_DRAFT27:
@@ -157,35 +157,33 @@ static int DetectSslVersionMatch(DetectEngineThreadCtx *det_ctx,
157157
case TLS_VERSION_13_DRAFT17:
158158
case TLS_VERSION_13_DRAFT16:
159159
case TLS_VERSION_13_PRE_DRAFT16:
160-
if (((ver >> 8) & 0xff) == 0x7f)
161-
ver = TLS_VERSION_13;
162-
/* fall through */
163160
case TLS_VERSION_13:
164-
if (ver == ssl->data[TLS13].ver)
161+
if (ssl->data[TLS13])
165162
ret = 1;
166-
sig_ver = TLS13;
163+
sig_ver = true;
167164
break;
168165
}
169166

170-
if (sig_ver == TLS_UNKNOWN)
167+
if (!sig_ver)
171168
SCReturnInt(0);
172169

173-
SCReturnInt(ret ^ ((ssl->data[sig_ver].flags & DETECT_SSL_VERSION_NEGATED) ? 1 : 0));
170+
// matches if ret == 1 and negate is false
171+
// or if ret == 0 and negate is true
172+
SCReturnInt(ret ^ (ssl->negate ? 1 : 0));
174173
}
175174

176175
struct SSLVersionKeywords {
177176
const char *word;
178177
int index;
179-
uint16_t value;
180178
};
181179

182180
struct SSLVersionKeywords ssl_version_keywords[TLS_SIZE] = {
183-
{ "sslv2", SSLv2, SSL_VERSION_2 },
184-
{ "sslv3", SSLv3, SSL_VERSION_3 },
185-
{ "tls1.0", TLS10, TLS_VERSION_10 },
186-
{ "tls1.1", TLS11, TLS_VERSION_11 },
187-
{ "tls1.2", TLS12, TLS_VERSION_12 },
188-
{ "tls1.3", TLS13, TLS_VERSION_13 },
181+
{ "sslv2", SSLv2 },
182+
{ "sslv3", SSLv3 },
183+
{ "tls1.0", TLS10 },
184+
{ "tls1.1", TLS11 },
185+
{ "tls1.2", TLS12 },
186+
{ "tls1.3", TLS13 },
189187
};
190188

191189
/**
@@ -203,7 +201,6 @@ static DetectSslVersionData *DetectSslVersionParse(DetectEngineCtx *de_ctx, cons
203201
DetectSslVersionData *ssl = NULL;
204202
const char *tmp_str = str;
205203
size_t tmp_len = 0;
206-
uint8_t found = 0;
207204

208205
/* We have a correct ssl_version options */
209206
ssl = SCCalloc(1, sizeof(DetectSslVersionData));
@@ -218,13 +215,12 @@ static DetectSslVersionData *DetectSslVersionParse(DetectEngineCtx *de_ctx, cons
218215
SCLogError("Invalid empty value");
219216
goto error;
220217
}
218+
if (tmp_str[0] == '!') {
219+
ssl->negate = true;
220+
tmp_str++;
221+
}
221222
// iterate every version separated by comma
222223
while (tmp_str[0] != 0) {
223-
uint8_t neg = 0;
224-
if (tmp_str[0] == '!') {
225-
neg = 1;
226-
tmp_str++;
227-
}
228224
// counts word length
229225
tmp_len = 0;
230226
while (tmp_str[tmp_len] != 0 && !isspace(tmp_str[tmp_len]) && tmp_str[tmp_len] != ',') {
@@ -235,13 +231,11 @@ static DetectSslVersionData *DetectSslVersionParse(DetectEngineCtx *de_ctx, cons
235231
for (size_t i = 0; i < TLS_SIZE; i++) {
236232
if (tmp_len == strlen(ssl_version_keywords[i].word) &&
237233
strncasecmp(ssl_version_keywords[i].word, tmp_str, tmp_len) == 0) {
238-
if (ssl->data[ssl_version_keywords[i].index].ver != 0) {
234+
if (ssl->data[ssl_version_keywords[i].index]) {
239235
SCLogError("Invalid duplicate value");
240236
goto error;
241237
}
242-
ssl->data[ssl_version_keywords[i].index].ver = ssl_version_keywords[i].value;
243-
if (neg == 1)
244-
ssl->data[ssl_version_keywords[i].index].flags |= DETECT_SSL_VERSION_NEGATED;
238+
ssl->data[ssl_version_keywords[i].index] = true;
245239
is_keyword = true;
246240
break;
247241
}
@@ -251,16 +245,6 @@ static DetectSslVersionData *DetectSslVersionParse(DetectEngineCtx *de_ctx, cons
251245
goto error;
252246
}
253247

254-
/* check consistency between negative and positive values :
255-
* if there is a negative value, it overrides positive values
256-
*/
257-
if (found == 0) {
258-
found |= 1 << neg;
259-
} else if (found != 1 << neg) {
260-
SCLogError("Invalid value mixing negative and positive forms");
261-
goto error;
262-
}
263-
264248
tmp_str += tmp_len;
265249
while (isspace(tmp_str[0]) || tmp_str[0] == ',') {
266250
tmp_str++;

src/detect-ssl-version.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@
2525
#ifndef DETECT_SSL_VERSION_H
2626
#define DETECT_SSL_VERSION_H
2727

28-
#define DETECT_SSL_VERSION_NEGATED 0x01
29-
3028
enum {
3129
SSLv2 = 0,
3230
SSLv3 = 1,
@@ -36,16 +34,13 @@ enum {
3634
TLS13 = 5,
3735

3836
TLS_SIZE = 6,
39-
TLS_UNKNOWN = 7,
4037
};
4138

42-
typedef struct SSLVersionData_ {
43-
uint16_t ver; /** ssl version to match */
44-
uint8_t flags;
45-
} SSLVersionData;
46-
4739
typedef struct DetectSslVersionData_ {
48-
SSLVersionData data[TLS_SIZE];
40+
// negate is global : `tls1.1, !tls1.0` does not make sense
41+
bool negate;
42+
// index is ssl version to match on
43+
bool data[TLS_SIZE];
4944
} DetectSslVersionData;
5045

5146
/* prototypes */

src/tests/detect-ssl-version.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static int DetectSslVersionTestParse01(void)
3333
DetectSslVersionData *ssl = NULL;
3434
ssl = DetectSslVersionParse(NULL, "SSlv3");
3535
FAIL_IF_NULL(ssl);
36-
FAIL_IF_NOT(ssl->data[SSLv3].ver == SSL_VERSION_3);
36+
FAIL_IF_NOT(ssl->data[SSLv3]);
3737
DetectSslVersionFree(NULL, ssl);
3838
PASS;
3939
}
@@ -73,13 +73,13 @@ static int DetectSslVersionTestParse03(void)
7373
DetectSslVersionData *ssl = NULL;
7474
ssl = DetectSslVersionParse(NULL, "SSlv3 , tls1.0");
7575
FAIL_IF_NULL(ssl);
76-
FAIL_IF_NOT(ssl->data[SSLv3].ver == SSL_VERSION_3);
77-
FAIL_IF_NOT(ssl->data[TLS10].ver == TLS_VERSION_10);
76+
FAIL_IF_NOT(ssl->data[SSLv3]);
77+
FAIL_IF_NOT(ssl->data[TLS10]);
7878
DetectSslVersionFree(NULL, ssl);
7979
ssl = DetectSslVersionParse(NULL, " !tls1.2");
8080
FAIL_IF_NULL(ssl);
81-
FAIL_IF_NOT(ssl->data[TLS12].ver == TLS_VERSION_12);
82-
FAIL_IF_NOT(ssl->data[TLS12].flags & DETECT_SSL_VERSION_NEGATED);
81+
FAIL_IF_NOT(ssl->data[TLS12]);
82+
FAIL_IF_NOT(ssl->negate);
8383
DetectSslVersionFree(NULL, ssl);
8484
PASS;
8585
}

0 commit comments

Comments
 (0)