Skip to content

Commit

Permalink
Wire ja4/ja4s in output json and do more work on SSL payload
Browse files Browse the repository at this point in the history
  • Loading branch information
phaag committed Mar 10, 2024
1 parent 070cd71 commit ab0810d
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 125 deletions.
3 changes: 3 additions & 0 deletions src/libnfdump/ja3/ja3.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@

#include "ssl/ssl.h"

#define JA3DEFINED(ja3) (*((uint64_t *)ja3) != 0)
#define JA3UNDEFINED(ja3) (*((uint64_t *)ja3) == 0)

uint8_t *ja3Process(ssl_t *ssl, uint8_t *hash);

char *ja3String(uint8_t *ja3Hash);
Expand Down
3 changes: 1 addition & 2 deletions src/nfdump/nfdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@ static void usage(char *name) {
"\t\t csv ',' separated, machine parseable output format.\n"
"\t\t json json output format.\n"
"\t\t json-log json log output format (one json record per line).\n"
"\t\t pipe '|' separated legacy machine parseable output format.\n"
"\t\t null no flow records, but statistics output.\n"
"\t\t null no flow records, only statistics output.\n"
"\t\t\tmode may be extended by '6' for full IPv6 listing. e.g.long6, extended6.\n"
"-E <file>\tPrint exporter and sampling info for collected flows.\n"
"-v <file>\tverify netflow data file. Print version and blocks.\n"
Expand Down
2 changes: 1 addition & 1 deletion src/nfdump/nflowcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ static inline void PreProcess(void *inPtr, preprocess_t process, recordHandle_t

uint32_t payloadLength = ExtensionLength(payload);
ssl_t *ssl = (ssl_t *)recordHandle->sslInfo;
if (*((uint64_t *)(recordHandle->ja3)) == 0) {
if (JA3DEFINED(recordHandle->ja3)) {
if (ssl == NULL) {
ssl = sslProcess((const uint8_t *)payload, payloadLength);
recordHandle->sslInfo = (void *)ssl;
Expand Down
203 changes: 104 additions & 99 deletions src/nfdump/nfstat.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/output/output_fmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1066,7 +1066,7 @@ static void String_ja3(FILE *stream, recordHandle_t *recordHandle) {
uint32_t payloadLength = ExtensionLength(payload);
ssl_t *ssl = (ssl_t *)recordHandle->sslInfo;

if (*((uint64_t *)(recordHandle->ja3)) == 0) {
if (JA3UNDEFINED(recordHandle->ja3)) {
if (ssl == NULL) {
ssl = sslProcess((const uint8_t *)payload, payloadLength);
recordHandle->sslInfo = (void *)ssl;
Expand Down
53 changes: 42 additions & 11 deletions src/output/output_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#include <time.h>

#include "ja3/ja3.h"
#include "ja4/ja4.h"
#include "ja4/ja4s.h"
#include "maxmind/maxmind.h"
#include "nfdump.h"
#include "nffile.h"
Expand Down Expand Up @@ -400,31 +402,60 @@ static void stringEXlatency(FILE *stream, void *extensionRecord, const char *ind

} // End of stringEXlatency

static void String_ja3(FILE *stream, recordHandle_t *recordHandle, void *extensionRecord, const char *indent, const char *fs) {
static void String_payload(FILE *stream, recordHandle_t *recordHandle, void *extensionRecord, const char *indent, const char *fs) {
EXgenericFlow_t *genericFlow = (EXgenericFlow_t *)recordHandle->extensionList[EXgenericFlowID];
EXinPayload_t *payload = (EXinPayload_t *)extensionRecord;
uint32_t payloadLength = ExtensionLength(payload);

if (payloadLength == 0) {
// payload handled in output json:
// ssl, ja3, ja4

if (payloadLength == 0 || genericFlow->proto != IPPROTO_TCP) {
return;
}

ssl_t *ssl = (ssl_t *)recordHandle->sslInfo;
if (*((uint64_t *)(recordHandle->ja3)) == 0) {
if (JA3UNDEFINED(recordHandle->ja3)) {
if (ssl == NULL) {
ssl = sslProcess((const uint8_t *)payload, payloadLength);
recordHandle->sslInfo = (void *)ssl;
}
ja3Process(ssl, recordHandle->ja3);
}

if (ssl && ssl->sniName[0]) {
fprintf(stream, " \"sni\" : %s,\n", ssl->sniName);
}
if (*((uint64_t *)(recordHandle->ja3)) == 0) {
fprintf(stream, " \"ja3 hash\" : %s,\n", ja3String(recordHandle->ja3));
if (ssl) {
switch (ssl->tlsCharVersion[0]) {
case 's':
fprintf(stream, "%s\"tls\" : SSL%c%s", indent, ssl->tlsCharVersion[1], fs);
break;
case '1':
fprintf(stream, "%s\"tls\" : TLS1.%c%s", indent, ssl->tlsCharVersion[1], fs);
break;
default:
fprintf(stream, "%s\"tls\" : 0x%4x%s", indent, ssl->tlsVersion, fs);
break;
}

if (ssl->sniName[0]) {
fprintf(stream, "%s\"sni\" : %s%s\n", indent, ssl->sniName, fs);
}
if (JA3DEFINED(recordHandle->ja3)) {
fprintf(stream, "%s\"ja3 hash\" : %s%s\n", indent, ja3String(recordHandle->ja3), fs);
}

char buff[64];
if (ssl->type == CLIENTssl) {
ja4_t *ja4 = ja4Process(ssl, genericFlow->proto);
if (ja4) fprintf(stream, "%s\"ja4 hash\" : %s%s\n", indent, ja4String(ja4, buff), fs);

} else {
if (JA3DEFINED(recordHandle->ja3)) fprintf(stream, " ja3s hash = %s\n", ja3String(recordHandle->ja3));
ja4s_t *ja4s = ja4sProcess(ssl, genericFlow->proto);
if (ja4s) fprintf(stream, "%s\"ja4s hash\" : %s%s\n", indent, ja4sString(ja4s, buff), fs);
}
}

} // End of String_ja3
} // End of String_payload

static void stringEXtunIPv4(FILE *stream, void *extensionRecord, const char *indent, const char *fs) {
EXtunIPv4_t *tunIPv4 = (EXtunIPv4_t *)extensionRecord;
Expand Down Expand Up @@ -691,10 +722,10 @@ static void flow_record_to_json(FILE *stream, recordHandle_t *recordHandle, int
stringEXlatency(stream, ptr, indent, fs);
break;
case EXinPayloadID:
String_ja3(stream, recordHandle, ptr, indent, fs);
String_payload(stream, recordHandle, ptr, indent, fs);
break;
case EXoutPayloadID:
String_ja3(stream, recordHandle, ptr, indent, fs);
String_payload(stream, recordHandle, ptr, indent, fs);
break;
case EXtunIPv4ID:
stringEXtunIPv4(stream, ptr, indent, fs);
Expand Down
35 changes: 24 additions & 11 deletions src/output/output_raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -711,9 +711,9 @@ static void inoutPayload(FILE *stream, recordHandle_t *recordHandle, uint8_t *pa

if (ascii) {
fprintf(stream, "%.*s\n", max, payload);
} else {
} else if (genericFlow->proto == IPPROTO_TCP) {
ssl_t *ssl = (ssl_t *)recordHandle->sslInfo;
if (*((uint64_t *)(recordHandle->ja3)) == 0) {
if (JA3UNDEFINED(recordHandle->ja3)) {
if (ssl == NULL) {
ssl = sslProcess((const uint8_t *)payload, length);
recordHandle->sslInfo = (void *)ssl;
Expand All @@ -722,17 +722,30 @@ static void inoutPayload(FILE *stream, recordHandle_t *recordHandle, uint8_t *pa
}

if (ssl) {
char buff[64];
switch (ssl->tlsCharVersion[0]) {
case 's':
fprintf(stream, " TLS version = SSL %c ", ssl->tlsCharVersion[1]);
break;
case '1':
fprintf(stream, " TLS version = 1.%c", ssl->tlsCharVersion[1]);
break;
default:
fprintf(stream, " TLS version = 0x%4x", ssl->tlsVersion);
break;
}

if (ssl->sniName[0]) fprintf(stream, " sni name = %s\n", ssl->sniName);

char buff[64];
if (ssl->type == CLIENTssl) {
ja4_t *ja4 = ja4Process(ssl, IPPROTO_TCP);
fprintf(stream, " ja3 hash = %s\n", ja3String(recordHandle->ja3));
fprintf(stream, " ja4 hash = %s\n", ja4String(ja4, buff));
if (JA3DEFINED(recordHandle->ja3)) fprintf(stream, " ja3 hash = %s\n", ja3String(recordHandle->ja3));
ja4_t *ja4 = ja4Process(ssl, genericFlow->proto);
if (ja4) fprintf(stream, " ja4 hash = %s\n", ja4String(ja4, buff));

} else {
ja4s_t *ja4s = ja4sProcess(ssl, IPPROTO_TCP);
fprintf(stream, " ja3s hash = %s\n", ja3String(recordHandle->ja3));
fprintf(stream, " ja4s hash = %s\n", ja4sString(ja4s, buff));
if (JA3DEFINED(recordHandle->ja3)) fprintf(stream, " ja3s hash = %s\n", ja3String(recordHandle->ja3));
ja4s_t *ja4s = ja4sProcess(ssl, genericFlow->proto);
if (ja4s) fprintf(stream, " ja4s hash = %s\n", ja4sString(ja4s, buff));
}
}
}
Expand Down Expand Up @@ -765,11 +778,11 @@ static void stringsEXinmon(FILE *stream, void *extensionRecord) {
void raw_prolog(void) {
// empty prolog
recordCount = 0;
} // End of pipe_prolog
} // End of raw_prolog

void raw_epilog(void) {
// empty epilog
} // End of pipe_epilog
} // End of raw_epilog

void raw_record(FILE *stream, recordHandle_t *recordHandle, int tag) {
recordHeaderV3_t *recordHeaderV3 = recordHandle->recordHeaderV3;
Expand Down

0 comments on commit ab0810d

Please sign in to comment.