140 lines
2.7 KiB
JavaScript
140 lines
2.7 KiB
JavaScript
/*
|
|
* Re-implementation of Salesforce's JA3/JA3s hash in JavaScript for Zeek.
|
|
*
|
|
* https://github.com/salesforce/ja3/
|
|
*/
|
|
"use strict";
|
|
const crypto = require('crypto');
|
|
|
|
const grease = new Set([
|
|
2570n,
|
|
6682n,
|
|
10794n,
|
|
14906n,
|
|
19018n,
|
|
23130n,
|
|
27242n,
|
|
31354n,
|
|
35466n,
|
|
39578n,
|
|
43690n,
|
|
47802n,
|
|
51914n,
|
|
56026n,
|
|
60138n,
|
|
64250n,
|
|
]);
|
|
|
|
/*
|
|
* ja3
|
|
*/
|
|
const conn_ssl_exts = new Map();
|
|
const conn_ssl_ec_point_formats = new Map();
|
|
const conn_ssl_curves = new Map();
|
|
|
|
zeek.on('ssl_extension', (c, is_orig, code, val) => {
|
|
if ( ! is_orig )
|
|
return;
|
|
|
|
if ( grease.has(code) )
|
|
return;
|
|
|
|
let uid = c.uid;
|
|
|
|
var exts = conn_ssl_exts.get(uid);
|
|
if ( exts === undefined ) {
|
|
exts = [];
|
|
conn_ssl_exts.set(uid, exts);
|
|
}
|
|
|
|
exts.push(code);
|
|
});
|
|
|
|
zeek.on('ssl_extension_ec_point_formats', (c, is_orig, point_formats) => {
|
|
if ( ! is_orig )
|
|
return;
|
|
|
|
let fmts = []
|
|
for ( const format of point_formats ) {
|
|
if ( grease.has(format) )
|
|
continue;
|
|
|
|
fmts.push(format);
|
|
}
|
|
|
|
conn_ssl_ec_point_formats.set(c.uid, fmts);
|
|
});
|
|
|
|
zeek.on('ssl_extension_elliptic_curves', (c, is_orig, curves) => {
|
|
if ( ! is_orig )
|
|
return;
|
|
|
|
let non_grease = [];
|
|
for ( const curve of curves ) {
|
|
if ( grease.has(curve) )
|
|
continue;
|
|
|
|
non_grease.push(curve);
|
|
}
|
|
|
|
conn_ssl_curves.set(c.uid, non_grease);
|
|
});
|
|
|
|
zeek.on('ssl_client_hello', (c, version, record_version, possible_ts,
|
|
client_random, session_id, ciphers) => {
|
|
let uid = c.uid;
|
|
let ja3_parts = [
|
|
version,
|
|
ciphers.join('-'),
|
|
(conn_ssl_exts.get(uid) || []).join('-'),
|
|
(conn_ssl_curves.get(uid) || []).join('-'),
|
|
(conn_ssl_ec_point_formats.get(uid) || []).join('-'),
|
|
];
|
|
|
|
let ja3_string = ja3_parts.join(',');
|
|
let tlsfp_1 = crypto.createHash('md5').update(ja3_string).digest('hex');
|
|
|
|
c.ssl.js_ja3 = tlsfp_1;
|
|
|
|
conn_ssl_exts.delete(uid);
|
|
conn_ssl_curves.delete(uid);
|
|
conn_ssl_ec_point_formats.delete(uid);
|
|
});
|
|
|
|
/*
|
|
* ja3s
|
|
*/
|
|
const ja3s_conn_ssl_exts = new Map();
|
|
|
|
zeek.on('ssl_extension', (c, is_orig, code, val) => {
|
|
if ( is_orig )
|
|
return;
|
|
|
|
let uid = c.uid;
|
|
var exts = [];
|
|
|
|
var exts = ja3s_conn_ssl_exts.get(uid);
|
|
if ( exts === undefined ) {
|
|
exts = [];
|
|
ja3s_conn_ssl_exts.set(uid, exts);
|
|
}
|
|
exts.push(code);
|
|
});
|
|
|
|
zeek.on('ssl_server_hello', (c, version, record_version, possible_ts,
|
|
server_random, session_id, cipher, comp_method) => {
|
|
let uid = c.uid;
|
|
let ja3s_parts = [
|
|
version,
|
|
cipher,
|
|
(ja3s_conn_ssl_exts.get(uid) || []).join('-'),
|
|
];
|
|
|
|
let ja3s_string = ja3s_parts.join(',');
|
|
let ja3sfp_1= crypto.createHash('md5').update(ja3s_string).digest('hex');
|
|
|
|
c.ssl.js_ja3s = ja3sfp_1;
|
|
|
|
ja3s_conn_ssl_exts.delete(uid);
|
|
});
|