mirror of
https://github.com/gchq/CyberChef
synced 2025-01-01 07:18:47 +00:00
Added 'JA3S Fingerprint' operation
This commit is contained in:
parent
8379a9b275
commit
289a417dfb
6 changed files with 217 additions and 16 deletions
|
@ -193,7 +193,8 @@
|
||||||
"Protobuf Decode",
|
"Protobuf Decode",
|
||||||
"VarInt Encode",
|
"VarInt Encode",
|
||||||
"VarInt Decode",
|
"VarInt Decode",
|
||||||
"TLS JA3 Fingerprint",
|
"JA3 Fingerprint",
|
||||||
|
"JA3S Fingerprint",
|
||||||
"Format MAC addresses",
|
"Format MAC addresses",
|
||||||
"Change IP format",
|
"Change IP format",
|
||||||
"Group IP addresses",
|
"Group IP addresses",
|
||||||
|
|
|
@ -18,17 +18,17 @@ import Stream from "../lib/Stream.mjs";
|
||||||
import {runHash} from "../lib/Hash.mjs";
|
import {runHash} from "../lib/Hash.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLS JA3 Fingerprint operation
|
* JA3 Fingerprint operation
|
||||||
*/
|
*/
|
||||||
class TLSJA3Fingerprint extends Operation {
|
class JA3Fingerprint extends Operation {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TLSJA3Fingerprint constructor
|
* JA3Fingerprint constructor
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.name = "TLS JA3 Fingerprint";
|
this.name = "JA3 Fingerprint";
|
||||||
this.module = "Crypto";
|
this.module = "Crypto";
|
||||||
this.description = "Generates a JA3 fingerprint to help identify TLS clients based on hashing together values from the Client Hello.<br><br>Input: A hex stream of the TLS Client Hello application layer.";
|
this.description = "Generates a JA3 fingerprint to help identify TLS clients based on hashing together values from the Client Hello.<br><br>Input: A hex stream of the TLS Client Hello application layer.";
|
||||||
this.infoURL = "https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967";
|
this.infoURL = "https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967";
|
||||||
|
@ -202,4 +202,4 @@ const GREASE_CIPHERSUITES = [
|
||||||
0xfafa
|
0xfafa
|
||||||
];
|
];
|
||||||
|
|
||||||
export default TLSJA3Fingerprint;
|
export default JA3Fingerprint;
|
145
src/core/operations/JA3SFingerprint.mjs
Normal file
145
src/core/operations/JA3SFingerprint.mjs
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2021
|
||||||
|
* @license Apache-2.0
|
||||||
|
*
|
||||||
|
* JA3S created by Salesforce
|
||||||
|
* John B. Althouse
|
||||||
|
* Jeff Atkinson
|
||||||
|
* Josh Atkins
|
||||||
|
*
|
||||||
|
* Algorithm released under the BSD-3-clause licence
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import Stream from "../lib/Stream.mjs";
|
||||||
|
import {runHash} from "../lib/Hash.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JA3S Fingerprint operation
|
||||||
|
*/
|
||||||
|
class JA3SFingerprint extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JA3SFingerprint constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "JA3S Fingerprint";
|
||||||
|
this.module = "Crypto";
|
||||||
|
this.description = "Generates a JA3S fingerprint to help identify TLS servers based on hashing together values from the Server Hello.<br><br>Input: A hex stream of the TLS Server Hello record in the application layer.";
|
||||||
|
this.infoURL = "https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "string";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Input format",
|
||||||
|
type: "option",
|
||||||
|
value: ["Hex", "Base64", "Raw"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Output format",
|
||||||
|
type: "option",
|
||||||
|
value: ["Hash digest", "JA3S string", "Full details"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const [inputFormat, outputFormat] = args;
|
||||||
|
|
||||||
|
input = Utils.convertToByteArray(input, inputFormat);
|
||||||
|
const s = new Stream(new Uint8Array(input));
|
||||||
|
|
||||||
|
const handshake = s.readInt(1);
|
||||||
|
if (handshake !== 0x16)
|
||||||
|
throw new OperationError("Not handshake data.");
|
||||||
|
|
||||||
|
// Version
|
||||||
|
s.moveForwardsBy(2);
|
||||||
|
|
||||||
|
// Length
|
||||||
|
const length = s.readInt(2);
|
||||||
|
if (s.length !== length + 5)
|
||||||
|
throw new OperationError("Incorrect handshake length.");
|
||||||
|
|
||||||
|
// Handshake type
|
||||||
|
const handshakeType = s.readInt(1);
|
||||||
|
if (handshakeType !== 2)
|
||||||
|
throw new OperationError("Not a Server Hello.");
|
||||||
|
|
||||||
|
// Handshake length
|
||||||
|
const handshakeLength = s.readInt(3);
|
||||||
|
if (s.length !== handshakeLength + 9)
|
||||||
|
throw new OperationError("Not enough data in Server Hello.");
|
||||||
|
|
||||||
|
// Hello version
|
||||||
|
const helloVersion = s.readInt(2);
|
||||||
|
|
||||||
|
// Random
|
||||||
|
s.moveForwardsBy(32);
|
||||||
|
|
||||||
|
// Session ID
|
||||||
|
const sessionIDLength = s.readInt(1);
|
||||||
|
s.moveForwardsBy(sessionIDLength);
|
||||||
|
|
||||||
|
// Cipher suite
|
||||||
|
const cipherSuite = s.readInt(2);
|
||||||
|
|
||||||
|
// Compression Method
|
||||||
|
s.moveForwardsBy(1);
|
||||||
|
|
||||||
|
// Extensions
|
||||||
|
const extensionsLength = s.readInt(2);
|
||||||
|
const extensions = s.getBytes(extensionsLength);
|
||||||
|
const es = new Stream(extensions);
|
||||||
|
const exts = [];
|
||||||
|
while (es.hasMore()) {
|
||||||
|
const type = es.readInt(2);
|
||||||
|
const length = es.readInt(2);
|
||||||
|
es.moveForwardsBy(length);
|
||||||
|
exts.push(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output
|
||||||
|
const ja3s = [
|
||||||
|
helloVersion.toString(),
|
||||||
|
cipherSuite,
|
||||||
|
exts.join("-")
|
||||||
|
];
|
||||||
|
const ja3sStr = ja3s.join(",");
|
||||||
|
const ja3sHash = runHash("md5", Utils.strToArrayBuffer(ja3sStr));
|
||||||
|
|
||||||
|
switch (outputFormat) {
|
||||||
|
case "JA3S string":
|
||||||
|
return ja3sStr;
|
||||||
|
case "Full details":
|
||||||
|
return `Hash digest:
|
||||||
|
${ja3sHash}
|
||||||
|
|
||||||
|
Full JA3S string:
|
||||||
|
${ja3sStr}
|
||||||
|
|
||||||
|
TLS Version:
|
||||||
|
${helloVersion.toString()}
|
||||||
|
Cipher Suite:
|
||||||
|
${cipherSuite}
|
||||||
|
Extensions:
|
||||||
|
${exts.join("-")}`;
|
||||||
|
case "Hash digest":
|
||||||
|
default:
|
||||||
|
return ja3sHash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default JA3SFingerprint;
|
|
@ -104,7 +104,7 @@ import "./tests/Unicode.mjs";
|
||||||
import "./tests/RSA.mjs";
|
import "./tests/RSA.mjs";
|
||||||
import "./tests/CBOREncode.mjs";
|
import "./tests/CBOREncode.mjs";
|
||||||
import "./tests/CBORDecode.mjs";
|
import "./tests/CBORDecode.mjs";
|
||||||
import "./tests/TLSJA3Fingerprint.mjs";
|
import "./tests/JA3Fingerprint.mjs";
|
||||||
|
|
||||||
|
|
||||||
// Cannot test operations that use the File type yet
|
// Cannot test operations that use the File type yet
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* TLSJA3Fingerprint tests.
|
* JA3Fingerprint tests.
|
||||||
*
|
*
|
||||||
* @author n1474335 [n1474335@gmail.com]
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
* @copyright Crown Copyright 2021
|
* @copyright Crown Copyright 2021
|
||||||
|
@ -9,45 +9,45 @@ import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
TestRegister.addTests([
|
TestRegister.addTests([
|
||||||
{
|
{
|
||||||
name: "TLS JA3 Fingerprint: TLS 1.0",
|
name: "JA3 Fingerprint: TLS 1.0",
|
||||||
input: "16030100a4010000a00301543dd2dd48f517ca9a93b1e599f019fdece704a23e86c1dcac588427abbaddf200005cc014c00a0039003800880087c00fc00500350084c012c00800160013c00dc003000ac013c00900330032009a009900450044c00ec004002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff0100001b000b000403000102000a000600040018001700230000000f000101",
|
input: "16030100a4010000a00301543dd2dd48f517ca9a93b1e599f019fdece704a23e86c1dcac588427abbaddf200005cc014c00a0039003800880087c00fc00500350084c012c00800160013c00dc003000ac013c00900330032009a009900450044c00ec004002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff0100001b000b000403000102000a000600040018001700230000000f000101",
|
||||||
expectedOutput: "503053a0c5b2bd9b9334bf7f3d3b8852",
|
expectedOutput: "503053a0c5b2bd9b9334bf7f3d3b8852",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "TLS JA3 Fingerprint",
|
"op": "JA3 Fingerprint",
|
||||||
"args": ["Hex", "Hash digest"]
|
"args": ["Hex", "Hash digest"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "TLS JA3 Fingerprint: TLS 1.1",
|
name: "JA3 Fingerprint: TLS 1.1",
|
||||||
input: "16030100a4010000a00302543dd2ed907e47d0086f34bee2c52dd6ccd8de63ba9387f5e810b09d9d49b38000005cc014c00a0039003800880087c00fc00500350084c012c00800160013c00dc003000ac013c00900330032009a009900450044c00ec004002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff0100001b000b000403000102000a000600040018001700230000000f000101",
|
input: "16030100a4010000a00302543dd2ed907e47d0086f34bee2c52dd6ccd8de63ba9387f5e810b09d9d49b38000005cc014c00a0039003800880087c00fc00500350084c012c00800160013c00dc003000ac013c00900330032009a009900450044c00ec004002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff0100001b000b000403000102000a000600040018001700230000000f000101",
|
||||||
expectedOutput: "a314eb64cee6cb832aaaa372c8295bab",
|
expectedOutput: "a314eb64cee6cb832aaaa372c8295bab",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "TLS JA3 Fingerprint",
|
"op": "JA3 Fingerprint",
|
||||||
"args": ["Hex", "Hash digest"]
|
"args": ["Hex", "Hash digest"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "TLS JA3 Fingerprint: TLS 1.2",
|
name: "JA3 Fingerprint: TLS 1.2",
|
||||||
input: "1603010102010000fe0303543dd3283283692d85f9416b5ccc65d2aafca45c6530b3c6eafbf6d371b6a015000094c030c02cc028c024c014c00a00a3009f006b006a0039003800880087c032c02ec02ac026c00fc005009d003d00350084c012c00800160013c00dc003000ac02fc02bc027c023c013c00900a2009e0067004000330032009a009900450044c031c02dc029c025c00ec004009c003c002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff01000041000b000403000102000a000600040018001700230000000d002200200601060206030501050205030401040204030301030203030201020202030101000f000101",
|
input: "1603010102010000fe0303543dd3283283692d85f9416b5ccc65d2aafca45c6530b3c6eafbf6d371b6a015000094c030c02cc028c024c014c00a00a3009f006b006a0039003800880087c032c02ec02ac026c00fc005009d003d00350084c012c00800160013c00dc003000ac02fc02bc027c023c013c00900a2009e0067004000330032009a009900450044c031c02dc029c025c00ec004009c003c002f009600410007c011c007c00cc002000500040015001200090014001100080006000300ff01000041000b000403000102000a000600040018001700230000000d002200200601060206030501050205030401040204030301030203030201020202030101000f000101",
|
||||||
expectedOutput: "c1a36e1a870786cc75edddc0009eaf3a",
|
expectedOutput: "c1a36e1a870786cc75edddc0009eaf3a",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "TLS JA3 Fingerprint",
|
"op": "JA3 Fingerprint",
|
||||||
"args": ["Hex", "Hash digest"]
|
"args": ["Hex", "Hash digest"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "TLS JA3 Fingerprint: TLS 1.3",
|
name: "JA3 Fingerprint: TLS 1.3",
|
||||||
input: "1603010200010001fc03034355d402c132771a9386b6e9994ae37069e0621af504c26673b1343843c21d8d0000264a4a130113021303c02bc02fc02cc030cca9cca8cc14cc13c013c014009c009d002f0035000a010001addada0000ff01000100000000180016000013626c6f672e636c6f7564666c6172652e636f6d0017000000230000000d00140012040308040401050308050501080606010201000500050100000000001200000010000e000c02683208687474702f312e3175500000000b000201000028002b00295a5a000100001d0020cf78b9167af054b922a96752b43973107b2a57766357dd288b2b42ab5df30e08002d00020101002b000b0acaca7f12030303020301000a000a00085a5a001d001700180a0a000100001500e4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
input: "1603010200010001fc03034355d402c132771a9386b6e9994ae37069e0621af504c26673b1343843c21d8d0000264a4a130113021303c02bc02fc02cc030cca9cca8cc14cc13c013c014009c009d002f0035000a010001addada0000ff01000100000000180016000013626c6f672e636c6f7564666c6172652e636f6d0017000000230000000d00140012040308040401050308050501080606010201000500050100000000001200000010000e000c02683208687474702f312e3175500000000b000201000028002b00295a5a000100001d0020cf78b9167af054b922a96752b43973107b2a57766357dd288b2b42ab5df30e08002d00020101002b000b0acaca7f12030303020301000a000a00085a5a001d001700180a0a000100001500e4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
expectedOutput: "4826a90ec2daf4f7b4b64cc1c8bd343b",
|
expectedOutput: "4826a90ec2daf4f7b4b64cc1c8bd343b",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "TLS JA3 Fingerprint",
|
"op": "JA3 Fingerprint",
|
||||||
"args": ["Hex", "Hash digest"]
|
"args": ["Hex", "Hash digest"]
|
||||||
}
|
}
|
||||||
],
|
],
|
55
tests/operations/tests/JA3SFingerprint.mjs
Normal file
55
tests/operations/tests/JA3SFingerprint.mjs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
* JA3SFingerprint tests.
|
||||||
|
*
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2021
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "JA3S Fingerprint: TLS 1.0",
|
||||||
|
input: "160301003d020000390301543dd2ddedbfe33895bd6bc676a3fa6b9fe5773a6e04d5476d1af3bcbc1dcbbb00c011000011ff01000100000b00040300010200230000",
|
||||||
|
expectedOutput: "bed95e1b525d2f41db3a6d68fac5b566",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "JA3S Fingerprint",
|
||||||
|
"args": ["Hex", "Hash digest"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "JA3S Fingerprint: TLS 1.1",
|
||||||
|
input: "160302003d020000390302543dd2ed88131999a0120d36c14a4139671d75aae3d7d7779081d3cf7dd7725a00c013000011ff01000100000b00040300010200230000",
|
||||||
|
expectedOutput: "130fac2dc19b142500acb0abc63b6379",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "JA3S Fingerprint",
|
||||||
|
"args": ["Hex", "Hash digest"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "JA3S Fingerprint: TLS 1.2",
|
||||||
|
input: "160303003d020000390303543dd328b38b445686739d58fab733fa23838f575e0e5ad9a1b9baace6cc3b4100c02f000011ff01000100000b00040300010200230000",
|
||||||
|
expectedOutput: "ccc514751b175866924439bdbb5bba34",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "JA3S Fingerprint",
|
||||||
|
"args": ["Hex", "Hash digest"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "JA3S Fingerprint: TLS 1.3",
|
||||||
|
input: "16030100520200004e7f123ef1609fd3f4fa8668aac5822d500fb0639b22671d0fb7258597355795511bf61301002800280024001d0020ae0e282a3b7a463e71064ecbaf671586e979b0edbebf7a4735c31678c70f660c",
|
||||||
|
expectedOutput: "986ae432c402479fe7a0c6fbe02164c1",
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
"op": "JA3S Fingerprint",
|
||||||
|
"args": ["Hex", "Hash digest"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
Loading…
Reference in a new issue