Skip to content

Commit

Permalink
detect/ja: use multi-protocol support
Browse files Browse the repository at this point in the history
instead of hardcoding list

Ticket: 7304
  • Loading branch information
catenacyber committed Nov 27, 2024
1 parent bbc62a6 commit 7f018f5
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 17 deletions.
70 changes: 68 additions & 2 deletions src/detect-ja4-hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ int Ja4IsDisabled(const char *type);
static InspectionBuffer *Ja4DetectGetHash(DetectEngineThreadCtx *det_ctx,
const DetectEngineTransforms *transforms, Flow *_f, const uint8_t _flow_flags, void *txv,
const int list_id);
#ifdef UNITTESTS
static void DetectJa4RegisterTests(void);
#endif

static int g_ja4_hash_buffer_id = 0;
#endif
Expand All @@ -70,6 +73,9 @@ void DetectJa4HashRegister(void)
sigmatch_table[DETECT_AL_JA4_HASH].url = "/rules/ja4-keywords.html#ja4-hash";
#ifdef HAVE_JA4
sigmatch_table[DETECT_AL_JA4_HASH].Setup = DetectJa4HashSetup;
#ifdef UNITTESTS
sigmatch_table[DETECT_AL_JA4_HASH].RegisterTests = DetectJa4RegisterTests;
#endif
#else /* HAVE_JA4 */
sigmatch_table[DETECT_AL_JA4_HASH].Setup = DetectJA4SetupNoSupport;
#endif /* HAVE_JA4 */
Expand Down Expand Up @@ -111,7 +117,8 @@ static int DetectJa4HashSetup(DetectEngineCtx *de_ctx, Signature *s, const char
if (DetectBufferSetActiveList(de_ctx, s, g_ja4_hash_buffer_id) < 0)
return -1;

if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_TLS && s->alproto != ALPROTO_QUIC) {
AppProto alprotos[] = { ALPROTO_TLS, ALPROTO_QUIC, ALPROTO_UNKNOWN };
if (DetectSignatureSetMultiAppProto(s, alprotos) < 0) {
SCLogError("rule contains conflicting protocols.");
return -1;
}
Expand All @@ -126,7 +133,6 @@ static int DetectJa4HashSetup(DetectEngineCtx *de_ctx, Signature *s, const char
}
return -2;
}
s->init_data->init_flags |= SIG_FLAG_INIT_JA;

return 0;
}
Expand Down Expand Up @@ -174,4 +180,64 @@ static InspectionBuffer *Ja4DetectGetHash(DetectEngineThreadCtx *det_ctx,
}
return buffer;
}

#ifdef UNITTESTS
static int DetectJa4TestParse01(void)
{
DetectEngineCtx *de_ctx = DetectEngineCtxInit();

// invalid tests
Signature *s =
SigInit(de_ctx, "alert ip any any -> any any (sid: 1; file.data; content: \"toto\"; "
"ja4.hash; content: \"q13d0310h3_55b375c5d22e_cd85d2d88918\";)");
// cannot have file.data with ja4.hash (quic or tls)
FAIL_IF_NOT_NULL(s);
s = SigInit(de_ctx, "alert ip any any -> any any (sid: 1; "
"ja4.hash; content: \"q13d0310h3_55b375c5d22e_cd85d2d88918\"; file.data; "
"content: \"toto\";)");
// cannot have file.data with ja4.hash (quic or tls)
FAIL_IF_NOT_NULL(s);
s = SigInit(de_ctx, "alert smb any any -> any any (sid: 1; "
"ja4.hash; content: \"q13d0310h3_55b375c5d22e_cd85d2d88918\";)");
// cannot have alproto=smb with ja4.hash (quic or tls)
FAIL_IF_NOT_NULL(s);
s = SigInit(de_ctx, "alert ip any any -> any any (sid: 1; "
"ja4.hash; content: \"q13d0310h3_55b375c5d22e_cd85d2d88918\"; smb.share; "
"content:\"toto\";)");
// cannot have a smb keyword with ja4.hash (quic or tls)
FAIL_IF_NOT_NULL(s);
s = SigInit(de_ctx, "alert ip any any -> any any (sid: 1; "
"smb.share; content:\"toto\"; ja4.hash; content: "
"\"q13d0310h3_55b375c5d22e_cd85d2d88918\";)");
// cannot have a smb keyword with ja4.hash (quic or tls)
FAIL_IF_NOT_NULL(s);

// valid tests
s = SigInit(de_ctx, "alert ip any any -> any any (sid: 1; "
"ja4.hash; content: \"q13d0310h3_55b375c5d22e_cd85d2d88918\";)");
// just ja4.hash any proto
FAIL_IF_NULL(s);
s = SigInit(de_ctx, "alert quic any any -> any any (sid: 1; "
"ja4.hash; content: \"q13d0310h3_55b375c5d22e_cd85d2d88918\";)");
// just ja4.hash only quic
FAIL_IF_NULL(s);
s = SigInit(de_ctx, "alert tls any any -> any any (sid: 1; "
"ja4.hash; content: \"q13d0310h3_55b375c5d22e_cd85d2d88918\";)");
// just ja4.hash only tls
FAIL_IF_NULL(s);
s = SigInit(de_ctx, "alert ip any any -> any any (sid: 1; "
"ja4.hash; content: \"q13d0310h3_55b375c5d22e_cd85d2d88918\"; "
"quic.version; content:\"|00|\";)");
// ja4.hash and a quic keyword
FAIL_IF_NULL(s);
DetectEngineCtxFree(de_ctx);
PASS;
}

static void DetectJa4RegisterTests(void)
{
UtRegisterTest("DetectJa4TestParse01", DetectJa4TestParse01);
}
#endif

#endif // HAVE_JA4
20 changes: 15 additions & 5 deletions src/detect-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -2151,11 +2151,6 @@ static int SigValidate(DetectEngineCtx *de_ctx, Signature *s)
}
DetectLuaPostSetup(s);

if ((s->init_data->init_flags & SIG_FLAG_INIT_JA) && s->alproto != ALPROTO_UNKNOWN &&
s->alproto != ALPROTO_TLS && s->alproto != ALPROTO_QUIC) {
SCLogError("Cannot have ja3/ja4 with protocol %s.", AppProtoToString(s->alproto));
SCReturnInt(0);
}
if ((s->flags & SIG_FLAG_FILESTORE) || s->file_flags != 0 ||
(s->init_data->init_flags & SIG_FLAG_INIT_FILEDATA)) {
if (s->alproto != ALPROTO_UNKNOWN &&
Expand All @@ -2165,6 +2160,21 @@ static int SigValidate(DetectEngineCtx *de_ctx, Signature *s)
"support file matching",
AppProtoToString(s->alproto));
SCReturnInt(0);
} else if (s->init_data->alprotos[0] != ALPROTO_UNKNOWN) {
bool found = false;
for (size_t i = 0; i < SIG_ALPROTO_MAX; i++) {
if (s->init_data->alprotos[i] == ALPROTO_UNKNOWN) {
break;
}
if (AppLayerParserSupportsFiles(IPPROTO_TCP, s->init_data->alprotos[i])) {
found = true;
break;
}
}
if (!found) {
SCLogError("No protocol support file matching");
SCReturnInt(0);
}
}
if (s->alproto == ALPROTO_HTTP2 && (s->file_flags & FILE_SIG_NEED_FILENAME)) {
SCLogError("protocol HTTP2 doesn't support file name matching");
Expand Down
4 changes: 2 additions & 2 deletions src/detect-tls-ja3-hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ static int DetectTlsJa3HashSetup(DetectEngineCtx *de_ctx, Signature *s, const ch
if (DetectBufferSetActiveList(de_ctx, s, g_tls_ja3_hash_buffer_id) < 0)
return -1;

if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_TLS && s->alproto != ALPROTO_QUIC) {
AppProto alprotos[] = { ALPROTO_TLS, ALPROTO_QUIC, ALPROTO_UNKNOWN };
if (DetectSignatureSetMultiAppProto(s, alprotos) < 0) {
SCLogError("rule contains conflicting protocols.");
return -1;
}
Expand All @@ -151,7 +152,6 @@ static int DetectTlsJa3HashSetup(DetectEngineCtx *de_ctx, Signature *s, const ch
}
return -2;
}
s->init_data->init_flags |= SIG_FLAG_INIT_JA;

return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions src/detect-tls-ja3-string.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ static int DetectTlsJa3StringSetup(DetectEngineCtx *de_ctx, Signature *s, const
if (DetectBufferSetActiveList(de_ctx, s, g_tls_ja3_str_buffer_id) < 0)
return -1;

if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_TLS && s->alproto != ALPROTO_QUIC) {
AppProto alprotos[] = { ALPROTO_TLS, ALPROTO_QUIC, ALPROTO_UNKNOWN };
if (DetectSignatureSetMultiAppProto(s, alprotos) < 0) {
SCLogError("rule contains conflicting protocols.");
return -1;
}
Expand All @@ -140,7 +141,6 @@ static int DetectTlsJa3StringSetup(DetectEngineCtx *de_ctx, Signature *s, const
}
return -2;
}
s->init_data->init_flags |= SIG_FLAG_INIT_JA;

return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions src/detect-tls-ja3s-hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ static int DetectTlsJa3SHashSetup(DetectEngineCtx *de_ctx, Signature *s, const c
if (DetectBufferSetActiveList(de_ctx, s, g_tls_ja3s_hash_buffer_id) < 0)
return -1;

if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_TLS && s->alproto != ALPROTO_QUIC) {
AppProto alprotos[] = { ALPROTO_TLS, ALPROTO_QUIC, ALPROTO_UNKNOWN };
if (DetectSignatureSetMultiAppProto(s, alprotos) < 0) {
SCLogError("rule contains conflicting protocols.");
return -1;
}
Expand All @@ -149,7 +150,6 @@ static int DetectTlsJa3SHashSetup(DetectEngineCtx *de_ctx, Signature *s, const c
}
return -2;
}
s->init_data->init_flags |= SIG_FLAG_INIT_JA;

return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions src/detect-tls-ja3s-string.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ static int DetectTlsJa3SStringSetup(DetectEngineCtx *de_ctx, Signature *s, const
if (DetectBufferSetActiveList(de_ctx, s, g_tls_ja3s_str_buffer_id) < 0)
return -1;

if (s->alproto != ALPROTO_UNKNOWN && s->alproto != ALPROTO_TLS && s->alproto != ALPROTO_QUIC) {
AppProto alprotos[] = { ALPROTO_TLS, ALPROTO_QUIC, ALPROTO_UNKNOWN };
if (DetectSignatureSetMultiAppProto(s, alprotos) < 0) {
SCLogError("rule contains conflicting protocols.");
return -1;
}
Expand All @@ -140,7 +141,6 @@ static int DetectTlsJa3SStringSetup(DetectEngineCtx *de_ctx, Signature *s, const
}
return -2;
}
s->init_data->init_flags |= SIG_FLAG_INIT_JA;

return 0;
}
Expand Down
3 changes: 1 addition & 2 deletions src/detect.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,7 @@ typedef struct DetectPort_ {
#define SIG_FLAG_INIT_NEED_FLUSH BIT_U32(7)
#define SIG_FLAG_INIT_PRIO_EXPLICIT \
BIT_U32(8) /**< priority is explicitly set by the priority keyword */
#define SIG_FLAG_INIT_FILEDATA BIT_U32(9) /**< signature has filedata keyword */
#define SIG_FLAG_INIT_JA BIT_U32(10) /**< signature has ja3/ja4 keyword */
#define SIG_FLAG_INIT_FILEDATA BIT_U32(9) /**< signature has filedata keyword */

/* signature mask flags */
/** \note: additions should be added to the rule analyzer as well */
Expand Down

0 comments on commit 7f018f5

Please sign in to comment.