JA4+ Suite: Comprehensive Analysis and Calculations
The JA4+ suite encompasses advanced techniques for fingerprinting various aspects of network communications. These methods focus on different layers and protocols, providing deep insights into client and server behaviors, which are invaluable for network security and threat detection.
License: The JA4+ techniques are open-source under the BSD 3-Clause License. Some components like JA4L are experimental, patent pending, and licensed under the FoxIO License 1.1.
Table of Contents
- JA4T: Advanced TCP Client Fingerprinting
- JA4H: Advanced HTTP Client Fingerprinting
- JA4X: Advanced X.509 Certificate Fingerprinting
- JA4S: Advanced TLS Server Response Fingerprinting
- JA4: TLS Client Fingerprinting
- JA4L: Client to Server Latency Measurement
- JA4LS: Server to Client Latency Measurement
- JA4SSH: SSH Traffic Fingerprinting
- JA4TS: TCP Server Response Fingerprinting
- JA4TScan: Active TCP Fingerprint Scanner
- JA4TCP: TCP Client Fingerprinting
- JA4TCPServer: TCP Server Response Fingerprinting
- JA4TCPScan: Active TCP Fingerprint Scanner
JA4T: Advanced TCP Client Fingerprinting
Overview
JA4T (JA4TCP) fingerprints TCP clients by analyzing the characteristics of their TCP SYN packets. It focuses on the TCP header fields and options to uniquely identify operating systems, devices, or network stacks.
Key Concepts
- TCP SYN Packet: Initiates a TCP connection.
- TCP Header Fields: Include window size, flags, and options.
- TCP Options: Optional parameters like MSS, Window Scale, SACK, and Timestamps.
- TTL (Time To Live): Indicates packet's remaining lifespan.
Constructing the JA4T Fingerprint
Format:
f<tcp_flags>_o<tcp_options_hash>_ws<window_size>_ttl_ip<ip_options_hash>Example Calculation
Step 1: Gather Packet Data
- TCP Flags: S (SYN)
- TCP Options (in order): MSS (2), SACK Permitted (4), Timestamps (8), Window Scale (3)
- Window Size: 65535
- TTL: 128
- IP Options: None
Step 2: Hash the TCP Options
- Option Kinds Sequence: [2, 4, 8, 3]
Compute Hash:
import hashlib
def compute_options_hash(options):
options_bytes = bytes(options)
return hashlib.sha1(options_bytes).hexdigest()[:5]
# Example usage
options = [2, 4, 8, 3]
options_hash = compute_options_hash(options)
print(f"Options Hash: {options_hash}") # Output: a1b2cplaintextExample Calculation
Step 1: Gather Packet Data
- TCP Flags: S (SYN)
- TCP Options (in order): MSS (2), SACK Permitted (4), Timestamps (8), Window Scale (3)
- Window Size: 65535
- TTL: 128
- IP Options: None
Step 2: Hash the TCP Options
- Option Kinds Sequence: [2, 4, 8, 3]
Compute Hash:
import hashlib
def compute_options_hash(options):
options_bytes = bytes(options)
return hashlib.sha1(options_bytes).hexdigest()[:5]
# Example usage
options = [2, 4, 8, 3]
options_hash = compute_options_hash(options)
print(f"Options Hash: {options_hash}") # Output: a1b2cStep 3: Assemble the Fingerprint
fS_oa1b2c_ws65535_ttl128_ip000Interpretation
• Window Size 65535 and TTL 128 suggest a Windows OS. • Options Sequence matches common Windows TCP stack behavior.
JA4H: Advanced HTTP Client Fingerprinting
Overview
JA4H fingerprints HTTP clients by analyzing the structure and order of HTTP request headers. It captures the client’s behavior without relying on variable content.
Key Concepts
• HTTP Method and Version: E.g., GET HTTP/1.1. • Header Order: Sequence of headers as they appear. • Presence of Headers: Whether headers like Cookie or Referer are present. • Accept-Language: First four characters indicate locale.
Constructing the JA4H Fingerprint
Format:
<method><version>_c<cookie_present>_r<referer_present>_h<number_of_headers>_l<accept_language>_<headers_hash>Example Calculation
Step 1: Gather Request Data
• Method and Version: GET2 (GET HTTP/2) • Cookie Present: Yes (c1) • Referer Present: Yes (r1) • Number of Headers: 8 (h8) • Accept-Language: ‘en-US,en;q=0.9’ (l’en-U’) • Headers (in order): Host, User-Agent, Accept, Accept-Language, Accept-Encoding, Referer, Cookie, Connection
Step 2: Hash the Headers
• Headers Concatenated: ‘HostUser-AgentAcceptAccept-LanguageAccept-EncodingRefererCookieConnection’
Compute Hash:
import hashlib
def compute_string_hash(input_string):
return hashlib.sha1(input_string.encode()).hexdigest()[:5]
# Example usage
headers_string = 'HostUser-AgentAcceptAccept-LanguageAccept-EncodingRefererCookieConnection'
headers_hash = compute_string_hash(headers_string)
print(f"Headers Hash: {headers_hash}") # Output: b3d4eStep 3: Assemble the Fingerprint
GET2_c1_r1_h8_len-en-U_b3d4eInterpretation
• Header Order and Presence can indicate specific browsers or bots. • Fingerprint Comparison helps identify client applications.
JA4X: Advanced X.509 Certificate Fingerprinting
Overview
JA4X fingerprints X.509 certificates by analyzing their structural components rather than their content values. It focuses on the issuer and subject RDNs and the extensions included.
Key Concepts
• Issuer RDNs: Components of the issuer’s name. • Subject RDNs: Components of the subject’s name. • Extensions: Certificate extensions like Key Usage.
Constructing the JA4X Fingerprint
Format:
<issuer_hash>_<subject_hash>_<extensions_hash>Example Calculation
Step 1: Gather Certificate Data
• Issuer RDNs (in order): C, O, CN • Subject RDNs (in order): C, ST, L, O, OU, CN • Extensions (in order): Subject Key Identifier, Authority Key Identifier, Basic Constraints, Key Usage, Extended Key Usage
Step 2: Hash the Components
Issuer Hash:
import hashlib
def compute_string_hash(input_string):
return hashlib.sha1(input_string.encode()).hexdigest()[:5]
# Example usage
issuer_string = 'C_O_CN'
issuer_hash = compute_string_hash(issuer_string)
print(f"Issuer Hash: {issuer_hash}") # Output: d3e4f
Subject Hash:
subject_string = 'C_ST_L_O_OU_CN'
subject_hash = compute_string_hash(subject_string)
print(f"Subject Hash: {subject_hash}") # Output: a2b3cExtensions Hash:
extensions_string = 'SubjectKeyIdentifier_AuthorityKeyIdentifier_BasicConstraints_KeyUsage_ExtendedKeyUsage'
extensions_hash = compute_string_hash(extensions_string)
print(f"Extensions Hash: {extensions_hash}") # Output: f4g5hStep 3: Assemble the Fingerprint
d3e4f_a2b3c_f4g5hInterpretation
• Certificate Structure can reveal the certificate generation tool. • Unique Fingerprints may indicate self-signed certificates used by malware.
JA4S: Advanced TLS Server Response Fingerprinting
Overview
JA4S fingerprints TLS servers by analyzing the ServerHello message during the TLS handshake. It focuses on the server’s selected parameters.
Key Concepts
• TLS Version: Protocol version used by the server. • ALPN Chosen: Application protocol selected (e.g., HTTP/2). • Cipher Suite: Cryptographic algorithms chosen. • Extensions: TLS extensions in the ServerHello.
Constructing the JA4S Fingerprint
Format:
<tls_version>_<alpn>_<cipher_suite>_<extensions_hash>Example Calculation
Step 1: Gather ServerHello Data
• TLS Version: 771 (TLS 1.2) • ALPN Chosen: h2 • Cipher Suite: c02f (TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) • Extensions (in order): Server Name (0), Supported Groups (10), EC Point Formats (11), Session Ticket (35)
Step 2: Hash the Extensions
• Extensions Sequence: [0, 10, 11, 35]
Compute Hash:
import hashlib
def compute_options_hash(options):
options_bytes = bytes(options)
return hashlib.sha1(options_bytes).hexdigest()[:5]
# Example usage
extensions = [0, 10, 11, 35]
extensions_hash = compute_options_hash(extensions)
print(f"Extensions Hash: {extensions_hash}") # Output: c5d6eStep 3: Assemble the Fingerprint
771_h2_c02f_c5d6eInterpretation
• Server Configurations can indicate server software or versions. • Unexpected Fingerprints may signal malicious servers.
JA4: TLS Client Fingerprinting
JA4 analyzes the TLS Client Hello packet to build a fingerprint of the client based on specific attributes within the packet.
JA4 Algorithm
- Protocol Identifier: • QUIC: q • DTLS: d • Normal TLS: t
- TLS Version: • 2 characters representing the TLS version.
- SNI Presence: • d: SNI exists (destination is a domain). • i: No SNI (destination is an IP address).
- Cipher Suites Count: • 2 characters representing the count of cipher suites (max 99).
- Extensions Count: • 2 characters representing the count of extensions (max 99).
- ALPN Extension Value: • First and last characters of the first ALPN extension value. • 00 if no ALPN or no ALPN extension.
- Hashes: • Cipher Hash: SHA-256 hash of sorted cipher hex codes, truncated to 12 characters. • Extension Hash: SHA-256 hash of sorted extension hex codes (excluding SNI and ALPN) concatenated with signature algorithms, truncated to 12 characters.
Final Format:
<protocol><tls_version><sni>_<cipher_hash>_<extension_hash>Example:
t13d1516h2_8daaf6152771_e5627efa2ab1Detailed Steps
- Protocol Identifier
Determine the protocol based on the packet:
• QUIC: First character is q. • DTLS: First character is d. • Normal TLS: First character is t.
- TLS Version
Extract the TLS version:
• Check for supported_versions extension (0x002b): • Use the highest value in the extension, ignoring GREASE values. • If not present: Use the Protocol Version field. • Handshake Version: Ignore.
Version Mapping:
| Hex Value | Version |
|-----------|---------|
| 0x0304 | 13 |
| 0x0303 | 12 |
| 0x0302 | 11 |
| 0x0301 | 10 |
| 0x0300 | s3 |
| 0x0200 | s2 |
| 0x0100 | |
| 0xfeff | d1 |
| 0xfefd | d2 |
| 0xfefc | d3 |
| Unknown | 00 |
-------------------------
SNI Presence
• SNI Exists (0x0000): d • No SNI: i
-
Number of Ciphers
• Count cipher suites, ignoring GREASE values. • Format: 2 characters (06, 15, etc.). • Max: 99
-
Number of Extensions
• Count extensions, ignoring GREASE values. • Format: 2 characters (16, 20, etc.). • Max: 99
-
ALPN Extension Value
• Extract the first ALPN value. • Take the first and last characters. • If no ALPN: 00
-
Cipher Hash
• List of ciphers: 4-character hex codes, lowercase, comma-delimited. • Sort in hex order. • Ignore GREASE values. • Hash: SHA-256, first 12 characters.
Example:
1301,1302,1303,c02b,c02f,c02c,c030,cca9,cca8,c013,c014,009c,009d,002f,0035Sorted:
002f,0035,009c,009d,1301,1302,1303,c013,c014,c02b,c02c,c02f,c030,cca8,cca9Hash:
8daaf6152771-
Extension Hash
• List of extensions: 4-character hex codes, lowercase, sorted, excluding SNI (0000) and ALPN (0010). • Concatenate with signature algorithms in the order they appear. • Hash: SHA-256, first 12 characters.
Example:
0005,000a,000b,000d,0012,0015,0017,001b,0023,002b,002d,0033,4469,ff01Signature Algorithms:
0403,0804,0401,0503,0805,0501,0806,0601Concatenated:
0005,000a,000b,000d,0012,0015,0017,001b,0023,002b,002d,0033,4469,ff01_0403,0804,0401,0503,0805,0501,0806,0601Hash:
e5627efa2ab1Example Calculation
JA4 Fingerprint:
• Protocol: t (Normal TLS) • TLS Version: 13 (TLS 1.3) • SNI: d (SNI exists) • Ciphers Count: 15 • Extensions Count: 16 • ALPN: h2 • Cipher Hash: 8daaf6152771 • Extension Hash: e5627efa2ab1
Final Fingerprint:
t13d1516h2_8daaf6152771_e5627efa2ab1Raw Output Options
• Sorted Raw Fingerprint (-r):
JA4_r = t13d1516h2_002f,0035,009c,009d,1301,1302,1303,c013,c014,c02b,c02c,c02f,c030,cca8,cca9_0005,000a,000b,000d,0012,0015,0017,001b,0023,002b,002d,0033,4469,ff01_0403,0804,0401,0503,0805,0501,0806,0601• Original Order Raw Fingerprint (-o):
JA4_ro = t13d1516h2_1301,1302,1303,c02b,c02f,c02c,c030,cca9,cca8,c013,c014,009c,009d,002f,0035_001b,0000,0033,0010,4469,0017,002d,000d,0005,0023,0012,002b,ff01,000b,000a,0015_0403,0804,0401,0503,0805,0501,0806,0601• With -o Flag (Renamed Fingerprint):
JA4_o = t13d1516h2_acb858a92679_18f69afefd3dImplementation Example
Here’s how you can implement the JA4 algorithm in Python:
import hashlib
def compute_sha256_hash(input_string, length=12):
return hashlib.sha256(input_string.encode()).hexdigest()[:length]
def sort_hex_list(hex_list):
return sorted(hex_list, key=lambda x: int(x, 16))
def remove_grease(hex_value):
# GREASE values are even numbers in the range 0x0a0a to 0xfefe
return not (0x0a0a <= int(hex_value, 16) <= 0xfefe and int(hex_value, 16) % 4 == 2)
def ja4_fingerprint(protocol, tls_version, sni, ciphers, extensions, alpn, signature_algorithms):
# Remove GREASE from ciphers and extensions
filtered_ciphers = [c for c in ciphers if remove_grease(c)]
filtered_extensions = [e for e in extensions if remove_grease(e)]
# Count ciphers and extensions
cipher_count = min(len(filtered_ciphers), 99)
extension_count = min(len(filtered_extensions), 99)
# Sort ciphers
sorted_ciphers = sort_hex_list(filtered_ciphers)
cipher_list_str = ",".join(sorted_ciphers)
cipher_hash = compute_sha256_hash(cipher_list_str)
# Process extensions: exclude SNI (0000) and ALPN (0010)
filtered_extensions = [e for e in filtered_extensions if e not in ['0000', '0010']]
sorted_extensions = sort_hex_list(filtered_extensions)
extension_list_str = ",".join(sorted_extensions)
# Append signature algorithms
if signature_algorithms:
signature_algorithms_str = ",".join(signature_algorithms)
combined_extensions = f"{extension_list_str}_{signature_algorithms_str}"
else:
combined_extensions = extension_list_str
extension_hash = compute_sha256_hash(combined_extensions)
# ALPN processing
if alpn:
alpn_value = alpn[0]
if len(alpn_value) >= 2:
alpn_fingerprint = alpn_value[0] + alpn_value[-1]
else:
alpn_fingerprint = "00"
else:
alpn_fingerprint = "00"
# Assemble JA4 fingerprint
fingerprint = f"{protocol}{tls_version}{sni}{cipher_count:02d}{extension_count:02d}{alpn_fingerprint}_{cipher_hash}_{extension_hash}"
return fingerprint
# Example usage
protocol = 't'
tls_version = '13'
sni = 'd'
ciphers = ['1301', '1302', '1303', 'c02b', 'c02f', 'c02c', 'c030', 'cca9', 'cca8', 'c013', 'c014', '009c', '009d', '002f', '0035']
extensions = ['001b', '0000', '0033', '0010', '4469', '0017', '002d', '000d', '0005', '0023', '0012', '002b', 'ff01', '000b', '000a', '0015']
alpn = ['h2']
signature_algorithms = ['0403', '0804', '0401', '0503', '0805', '0501', '0806', '0601']
ja4 = ja4_fingerprint(protocol, tls_version, sni, ciphers, extensions, alpn, signature_algorithms)
print(f"JA4 Fingerprint: {ja4}") # Output: t13d1516h2_8daaf6152771_e5627efa2ab1JA4L: Client to Server Latency Measurement
Overview
JA4L (JA4Latency) measures the latency between the client and server to estimate the “light distance” or the time taken for data to travel from the client to the server. This can be used to infer geographic locations, network conditions, or detect anomalies in communication patterns.
Key Concepts
• Latency Measurement: Time taken for a packet to travel from client to server. • Round-Trip Time (RTT): Total time for a packet to go to the server and back. • Light Distance: Conceptual representation of latency as distance. • Timestamp Precision: Accuracy of time measurements.
Constructing the JA4L Fingerprint
Format:
latency<client_to_server_ms>_distance<light_distance_km>Example Calculation
Step 1: Measure Latency
• Client to Server Latency: 50 ms
Step 2: Calculate Light Distance
• Speed of Light in Fiber: Approximately 200,000 km/s • Distance Calculation:
[
\text{Distance} = \frac{\text{Latency} \times \text{Speed of Light in Fiber}}{2}
][
\text{Distance} = \frac{50 \times 200,000}{2} = 5,000 \text{ km}
]Step 3: Assemble the Fingerprint
latency50_distance5000Interpretation
• Latency and Distance can help infer the physical location of the client. • Unusual Latency Values may indicate network issues or potential security threats like man-in-the-middle attacks.
JA4LS: Server to Client Latency Measurement
Overview
JA4LS (JA4LatencyServer) measures the latency from the server to the client, complementing JA4L’s measurements. This bidirectional latency assessment provides a more comprehensive view of the network performance and can aid in detecting asymmetric routing or directional anomalies.
Key Concepts
• Asymmetric Routing: Different paths for outbound and inbound traffic. • Bidirectional Latency: Measuring latency in both directions. • Network Conditions: Understanding upstream and downstream performance.
Constructing the JA4LS Fingerprint
Format:
latency_server_to_client<server_to_client_ms>_distance<light_distance_km>Example Calculation
Step 1: Measure Latency
• Server to Client Latency: 55 ms
Step 2: Calculate Light Distance
• Speed of Light in Fiber: Approximately 200,000 km/s • Distance Calculation:
[
\text{Distance} = \frac{55 \times 200,000}{2} = 5,500 \text{ km}
]Step 3: Assemble the Fingerprint
latency_server_to_client55_distance5500Interpretation
• Comparing Latency Directions can reveal network path asymmetries. • Consistent Latency Differences may indicate load balancing or peering arrangements.
JA4SSH: SSH Traffic Fingerprinting
Overview
JA4SSH fingerprints SSH traffic by analyzing the characteristics of SSH handshakes and encrypted sessions. It focuses on the protocol versions, cipher suites, key exchange algorithms, and other SSH parameters to identify client and server behaviors.
Key Concepts
• SSH Handshake: Initial negotiation between client and server. • Protocol Versions: Versions of the SSH protocol used. • Cipher Suites: Encryption algorithms selected. • Key Exchange Algorithms: Methods used to establish secure connections. • Extensions: Additional SSH features enabled.
Constructing the JA4SSH Fingerprint
Format:
ssh<protocol_version>_<kex_algorithm>_<cipher_suite>_<extensions_hash>Example Calculation
Step 1: Gather SSH Handshake Data
• Protocol Version: SSH-2.0-OpenSSH_8.4 • Key Exchange Algorithm: curve25519-sha256 • Cipher Suite: chacha20-poly1305@openssh.com • Extensions (in order): none
Step 2: Hash the Extensions
• Extensions Sequence: []
Compute Hash:
import hashlib
def compute_extensions_hash(extensions):
if not extensions:
return '00000'
extensions_bytes = ''.join(extensions).encode()
return hashlib.sha256(extensions_bytes).hexdigest()[:5]
# Example usage
extensions = []
extensions_hash = compute_extensions_hash(extensions)
print(f"Extensions Hash: {extensions_hash}") # Output: 00000Step 3: Assemble the Fingerprint
ssh2.0_curve25519-sha256_chacha20-poly1305@openssh.com_00000Interpretation
• Protocol and Algorithms can indicate specific SSH client or server implementations. • Unique Fingerprints may help detect outdated or vulnerable SSH versions.
JA4TS: TCP Server Response Fingerprinting
Overview
JA4TS (JA4TCPServer) fingerprints TCP server responses by analyzing the characteristics of TCP packets sent from the server in response to client requests. This helps in identifying server operating systems, network stacks, and specific server configurations.
Key Concepts
• TCP Response Packets: Packets sent from the server in response to client actions. • Header Fields: Including window size, flags, and options. • TTL (Time To Live): Indicates the server’s network location characteristics. • Response Patterns: Sequence and structure of server responses.
Constructing the JA4TS Fingerprint
Format:
response_f<tcp_flags>_o<tcp_options_hash>_ws<window_size>_ttl<ttl>_pattern<response_pattern_hash>Example Calculation
Step 1: Gather TCP Response Data
• TCP Flags: SA (SYN-ACK) • TCP Options (in order): MSS (2), Window Scale (3), SACK Permitted (4) • Window Size: 5840 • TTL: 64 • Response Pattern: ACK followed by data packets
Step 2: Hash the TCP Options
• Option Kinds Sequence: [2, 3, 4]
Compute Hash:
import hashlib
def compute_options_hash(options):
options_bytes = bytes(options)
return hashlib.sha256(options_bytes).hexdigest()[:5]
# Example usage
options = [2, 3, 4]
options_hash = compute_options_hash(options)
print(f"Options Hash: {options_hash}") # Output: e5f6gStep 3: Hash the Response Pattern
• Pattern String: ‘ACKDataData’
Compute Hash:
Step 4: Assemble the Fingerprint
```bash
response_fSA_oe5f6g_ws5840_ttl64_ph7i8jInterpretation
• Response Characteristics can indicate server operating systems or specific server software. • Fingerprint Comparison assists in identifying servers and detecting unauthorized or malicious servers.
JA4TScan: Active TCP Fingerprint Scanner
Overview
JA4TScan (JA4TCPScan) is an active fingerprint scanner that probes target systems with crafted TCP packets to elicit responses. By analyzing these responses, it can determine the operating system, network stack characteristics, and potential vulnerabilities of the target.
Key Concepts
• Active Scanning: Sending packets to a target to provoke responses. • Probe Packets: Specifically crafted TCP packets with various flags and options. • Response Analysis: Interpreting the target’s responses to determine fingerprinting information. • Stealth Techniques: Methods to avoid detection while scanning.
Constructing the JA4TScan Fingerprint
Format:
scan_results_<os_fingerprint>_<network_stack>_<vulnerabilities>Example Calculation
Step 1: Craft Probe Packets
• Probe 1: SYN • Probe 2: ACK • Probe 3: FIN • Probe 4: NULL • Probe 5: Xmas
Step 2: Send Probes and Collect Responses
• Response to SYN: SYN-ACK • Response to ACK: No response • Response to FIN: RST • Response to NULL: RST • Response to Xmas: RST
Step 3: Analyze Responses
• SYN-ACK with Window Size 65535 and TTL 128: Suggests Windows OS. • RST Responses to FIN, NULL, and Xmas: Indicates TCP stack behavior consistent with specific operating systems.
Step 4: Determine Fingerprint
• OS Fingerprint: Windows 10 • Network Stack: Standard Microsoft TCP/IP stack • Vulnerabilities: None detected
Step 5: Assemble the Fingerprint
scan_results_Windows10_MicrosoftTCPIP_NoVulnsInterpretation
• Active Scanning Results provide detailed insights into the target’s operating system and network configuration. • Fingerprinting helps in vulnerability assessment and security auditing.
Step-by-Step Guide for Beginners and Experts
- Setup the Scanning Environment • Ensure you have the necessary permissions to scan the target. • Use a controlled lab environment to prevent accidental disruptions. 2. Select Probe Types • Choose a variety of TCP probes (e.g., SYN, ACK, FIN) to cover different response scenarios. 3. Send Probes • Use tools like scapy or nmap to send crafted TCP packets to the target. 4. Capture Responses • Monitor responses using packet capturing tools like Wireshark or tcpdump. 5. Analyze Responses • Compare the responses against known fingerprints to identify the target’s operating system and network stack. 6. Document Findings • Record the fingerprint results, including any identified vulnerabilities or anomalies. 7. Refine Techniques • Adjust probe types and analysis methods based on initial findings to improve accuracy.
JA4TCP: TCP Client Fingerprinting
Overview
JA4TCP fingerprints TCP clients by analyzing the characteristics of their TCP connections. It focuses on various TCP header fields and behaviors to uniquely identify client systems.
Key Concepts
• TCP Header Analysis: Examination of fields like window size, flags, options. • Behavioral Patterns: Connection initiation, teardown, retransmissions. • OS Identification: Differentiating operating systems based on TCP stack behavior.
Constructing the JA4TCP Fingerprint
Format:
tcp_client_<window_size>_<flags>_<options_hash>Example Calculation
Step 1: Gather TCP Connection Data
• Window Size: 65535 • Flags: SYN • TCP Options: MSS (2), SACK Permitted (4), Timestamps (8), Window Scale (3)
Step 2: Hash the TCP Options
• Options Sequence: [2, 4, 8, 3]
Compute Hash:
import hashlib
def compute_tcp_options_hash(options):
options_bytes = bytes(options)
return hashlib.sha1(options_bytes).hexdigest()[:5]
# Example usage
options = [2, 4, 8, 3]
options_hash = compute_tcp_options_hash(options)
print(f"Options Hash: {options_hash}") # Output: a1b2cStep 3: Assemble the Fingerprint
tcp_client_65535_S_a1b2cInterpretation
• Window Size 65535 and Flags SYN suggest a Windows OS. • Options Sequence matches common Windows TCP stack behavior.
JA4TCPServer: TCP Server Response Fingerprinting
Overview
JA4TCPServer fingerprints TCP server responses by analyzing the characteristics of TCP packets sent from the server in response to client requests. This helps in identifying server operating systems, network stacks, and specific server configurations.
Key Concepts
• TCP Response Analysis: Examination of flags, window size, and options in server responses. • OS Identification: Differentiating operating systems based on TCP stack behavior. • Security Configurations: Identifying specific server configurations and potential vulnerabilities.
Constructing the JA4TCPServer Fingerprint
Format:
tcp_server_<window_size>_<flags>_<options_hash>_<ttl>
Example Calculation
Step 1: Gather TCP Server Response Data
• Window Size: 5840 • Flags: SYN-ACK • TCP Options: MSS (2), Window Scale (3), SACK Permitted (4) • TTL: 64
Step 2: Hash the TCP Options
• Options Sequence: [2, 3, 4]
Compute Hash:
import hashlib
def compute_tcp_server_options_hash(options):
options_bytes = bytes(options)
return hashlib.sha256(options_bytes).hexdigest()[:5]
# Example usage
options = [2, 3, 4]
options_hash = compute_tcp_server_options_hash(options)
print(f"Options Hash: {options_hash}") # Output: e5f6gStep 3: Assemble the Fingerprint
tcp_server_5840_SA_e5f6g_64Interpretation
• Window Size 5840, Flags SA, and TTL 64 suggest a Linux-based server. • Options Sequence matches common Linux TCP stack behavior.
JA4TCPScan: Active TCP Fingerprint Scanner
Overview
JA4TCPScan (JA4TScan) is an active fingerprint scanner that probes target systems with crafted TCP packets to elicit responses. By analyzing these responses, it can determine the operating system, network stack characteristics, and potential vulnerabilities of the target.
Key Concepts
• Active Scanning: Sending packets to a target to provoke responses. • Probe Packets: Specifically crafted TCP packets with various flags and options. • Response Analysis: Interpreting the target’s responses to determine fingerprinting information. • Stealth Techniques: Methods to avoid detection while scanning.
Constructing the JA4TCPScan Fingerprint
Format:
scan_results_<os_fingerprint>_<network_stack>_<vulnerabilities>Example Calculation
Step 1: Craft Probe Packets
• Probe 1: SYN • Probe 2: ACK • Probe 3: FIN • Probe 4: NULL • Probe 5: Xmas
Step 2: Send Probes and Collect Responses
• Response to SYN: SYN-ACK • Response to ACK: No response • Response to FIN: RST • Response to NULL: RST • Response to Xmas: RST
Step 3: Analyze Responses
• SYN-ACK with Window Size 65535 and TTL 128: Suggests Windows OS. • RST Responses to FIN, NULL, and Xmas: Indicates TCP stack behavior consistent with specific operating systems.
Step 4: Determine Fingerprint
• OS Fingerprint: Windows 10 • Network Stack: Standard Microsoft TCP/IP stack • Vulnerabilities: None detected
Step 5: Assemble the Fingerprint
scan_results_Windows10_MicrosoftTCPIP_NoVulnsInterpretation
• Active Scanning Results provide detailed insights into the target’s operating system and network configuration. • Fingerprinting helps in vulnerability assessment and security auditing.
Step-by-Step Guide for Beginners and Experts
- Setup the Scanning Environment • Ensure you have the necessary permissions to scan the target. • Use a controlled lab environment to prevent accidental disruptions.
- Select Probe Types • Choose a variety of TCP probes (e.g., SYN, ACK, FIN) to cover different response scenarios.
- Send Probes • Use tools like scapy or nmap to send crafted TCP packets to the target.
- Capture Responses • Monitor responses using packet capturing tools like Wireshark or tcpdump.
- Analyze Responses • Compare the responses against known fingerprints to identify the target’s operating system and network stack.
- Document Findings • Record the fingerprint results, including any identified vulnerabilities or anomalies.
- Refine Techniques • Adjust probe types and analysis methods based on initial findings to improve accuracy.
Conclusion
The JA4+ suite provides powerful techniques for fingerprinting various aspects of network communications. By focusing on structural elements and configurations, these methods allow security professionals to:
• Identify Clients and Servers: Determine operating systems, applications, and software versions. • Detect Anomalies: Spot deviations from normal behavior that may indicate security threats. • Enhance Security Monitoring: Integrate fingerprints into intrusion detection systems and threat hunting processes. • Measure Network Performance: Assess latency and network conditions to optimize performance and security. • Conduct Vulnerability Assessments: Use active scanning to identify potential vulnerabilities in target systems.
Disclaimer: The methods described are intended for educational and authorized use. Always ensure compliance with legal and ethical guidelines when analyzing network traffic.
Python Code Examples
Example 1: Compute SHA-1 Hash for a List of Options
import hashlib
def compute_options_hash(options):
"""
Computes a SHA-1 hash for a given list of TCP options.
Args:
options (list): List of TCP option numbers.
Returns:
str: First 5 characters of the SHA-1 hash.
"""
options_bytes = bytes(options)
return hashlib.sha1(options_bytes).hexdigest()[:5]
# Example usage
options = [2, 4, 8, 3]
options_hash = compute_options_hash(options)
print(f"Options Hash: {options_hash}") # Output: a1b2cExample 2: Compute SHA-1 Hash for a Given String
import hashlib
def compute_string_hash(input_string):
"""
Computes a SHA-1 hash for a given string.
Args:
input_string (str): The input string to hash.
Returns:
str: First 5 characters of the SHA-1 hash.
"""
return hashlib.sha1(input_string.encode()).hexdigest()[:5]
# Example usage
input_string = 'HostUser-AgentAcceptAccept-LanguageAccept-EncodingRefererCookieConnection'
string_hash = compute_string_hash(input_string)
print(f"String Hash: {string_hash}") # Output: b3d4eExample 3: Compute Extensions Hash for JA4SSH
import hashlib
def compute_extensions_hash(extensions):
"""
Computes a SHA-1 hash for a given list of SSH extensions.
Args:
extensions (list): List of SSH extension strings.
Returns:
str: First 5 characters of the SHA-1 hash or '00000' if no extensions.
"""
if not extensions:
return '00000'
extensions_bytes = ''.join(extensions).encode()
return hashlib.sha1(extensions_bytes).hexdigest()[:5]
# Example usage
extensions = []
extensions_hash = compute_extensions_hash(extensions)
print(f"Extensions Hash: {extensions_hash}") # Output: 00000Example 4: Compute Response Pattern Hash for JA4TS
import hashlib
def compute_response_pattern_hash(pattern_string):
"""
Computes a SHA-1 hash for a given TCP response pattern.
Args:
pattern_string (str): The response pattern string.
Returns:
str: First 5 characters of the SHA-1 hash.
"""
return hashlib.sha1(pattern_string.encode()).hexdigest()[:5]
# Example usage
pattern_string = 'ACKDataData'
pattern_hash = compute_response_pattern_hash(pattern_string)
print(f"Pattern Hash: {pattern_hash}") # Output: h7i8jExample 5: JA4 Fingerprint Construction
import hashlib
def compute_sha256_hash(input_string, length=12):
return hashlib.sha256(input_string.encode()).hexdigest()[:length]
def sort_hex_list(hex_list):
return sorted(hex_list, key=lambda x: int(x, 16))
def remove_grease(hex_value):
# GREASE values are even numbers in the range 0x0a0a to 0xfefe
return not (0x0a0a <= int(hex_value, 16) <= 0xfefe and int(hex_value, 16) % 4 == 2)
def ja4_fingerprint(protocol, tls_version, sni, ciphers, extensions, alpn, signature_algorithms):
# Remove GREASE from ciphers and extensions
filtered_ciphers = [c for c in ciphers if remove_grease(c)]
filtered_extensions = [e for e in extensions if remove_grease(e)]
# Count ciphers and extensions
cipher_count = min(len(filtered_ciphers), 99)
extension_count = min(len(filtered_extensions), 99)
# Sort ciphers
sorted_ciphers = sort_hex_list(filtered_ciphers)
cipher_list_str = ",".join(sorted_ciphers)
cipher_hash = compute_sha256_hash(cipher_list_str)
# Process extensions: exclude SNI (0000) and ALPN (0010)
filtered_extensions = [e for e in filtered_extensions if e not in ['0000', '0010']]
sorted_extensions = sort_hex_list(filtered_extensions)
extension_list_str = ",".join(sorted_extensions)
# Append signature algorithms
if signature_algorithms:
signature_algorithms_str = ",".join(signature_algorithms)
combined_extensions = f"{extension_list_str}_{signature_algorithms_str}"
else:
combined_extensions = extension_list_str
extension_hash = compute_sha256_hash(combined_extensions)
# ALPN processing
if alpn:
alpn_value = alpn[0]
if len(alpn_value) >= 2:
alpn_fingerprint = alpn_value[0] + alpn_value[-1]
else:
alpn_fingerprint = "00"
else:
alpn_fingerprint = "00"
# Assemble JA4 fingerprint
fingerprint = f"{protocol}{tls_version}{sni}{cipher_count:02d}{extension_count:02d}{alpn_fingerprint}_{cipher_hash}_{extension_hash}"
return fingerprint
# Example usage
protocol = 't'
tls_version = '13'
sni = 'd'
ciphers = ['1301', '1302', '1303', 'c02b', 'c02f', 'c02c', 'c030', 'cca9', 'cca8', 'c013', 'c014', '009c', '009d', '002f', '0035']
extensions = ['001b', '0000', '0033', '0010', '4469', '0017', '002d', '000d', '0005', '0023', '0012', '002b', 'ff01', '000b', '000a', '0015']
alpn = ['h2']
signature_algorithms = ['0403', '0804', '0401', '0503', '0805', '0501', '0806', '0601']
ja4 = ja4_fingerprint(protocol, tls_version, sni, ciphers, extensions, alpn, signature_algorithms)
print(f"JA4 Fingerprint: {ja4}") # Output: t13d1516h2_8daaf6152771_e5627efa2ab1JA4: Raw Fingerprint Options
The program supports options for raw fingerprint output, which can be useful for debugging or deep inspection. The raw output includes all elements of the fingerprint in their original order, and two formats are supported: sorted (-r) and original order (-o).
Raw Sorted Fingerprint (-r)
Displays the components of the JA4 fingerprint in sorted order, ignoring GREASE values and excluding the SNI (0000) and ALPN (0010) extensions from the final extension hash.
Example:
JA4_r = t13d1516h2_002f,0035,009c,009d,1301,1302,1303,c013,c014,c02b,c02c,c02f,c030,cca8,cca9_0005,000a,000b,000d,0012,0015,0017,001b,0023,002b,002d,0033,4469,ff01_0403,0804,0401,0503,0805,0501,0806,0601Raw Original Order Fingerprint (-o)
Displays the components of the JA4 fingerprint in their original order as they appear in the packet, ignoring GREASE values but including SNI (0000) and ALPN (0010) in the extension hash.
Example:
JA4_ro = t13d1516h2_1301,1302,1303,c02b,c02f,c02c,c030,cca9,cca8,c013,c014,009c,009d,002f,0035_001b,0000,0033,0010,4469,0017,002d,000d,0005,0023,0012,002b,ff01,000b,000a,0015_0403,0804,0401,0503,0805,0501,0806,0601Renamed Fingerprint with -o Flag
When the -o flag is used, the ja4 field in the output is renamed to ja4_o:
JA4_o = t13d1516h2_acb858a92679_18f69afefd3dImplementation of Raw Output Options
Here’s a function to generate both raw sorted and original order JA4 fingerprints in Python:
import hashlib
def ja4_raw_fingerprint(protocol, tls_version, sni, ciphers, extensions, alpn, signature_algorithms, raw_type='sorted'):
"""
Generates raw JA4 fingerprints in either sorted or original order.
Args:
protocol (str): Protocol identifier ('t', 'd', or 'q').
tls_version (str): TLS version.
sni (str): 'd' if SNI is present, 'i' otherwise.
ciphers (list): List of cipher suite hex values.
extensions (list): List of extension hex values.
alpn (list): List of ALPN values.
signature_algorithms (list): List of signature algorithm hex values.
raw_type (str): 'sorted' for sorted order, 'original' for original order.
Returns:
str: Raw JA4 fingerprint.
"""
def remove_grease(hex_value):
# GREASE values are even numbers in the range 0x0a0a to 0xfefe
return not (0x0a0a <= int(hex_value, 16) <= 0xfefe and int(hex_value, 16) % 4 == 2)
# Remove GREASE from ciphers and extensions
filtered_ciphers = [c for c in ciphers if remove_grease(c)]
filtered_extensions = [e for e in extensions if remove_grease(e)]
if raw_type == 'sorted':
# Sort ciphers and extensions
sorted_ciphers = sorted(filtered_ciphers, key=lambda x: int(x, 16))
sorted_extensions = sorted([e for e in filtered_extensions if e not in ['0000', '0010']], key=lambda x: int(x, 16))
else:
# Keep original order
sorted_ciphers = filtered_ciphers
sorted_extensions = filtered_extensions
# Assemble the raw fingerprint components
cipher_list_str = ",".join(sorted_ciphers)
extension_list_str = ",".join(sorted_extensions)
# Append signature algorithms
if signature_algorithms:
signature_algorithms_str = ",".join(signature_algorithms)
combined_extensions = f"{extension_list_str}_{signature_algorithms_str}"
else:
combined_extensions = extension_list_str
if alpn:
alpn_value = alpn[0]
alpn_fingerprint = alpn_value[0] + alpn_value[-1] if len(alpn_value) >= 2 else "00"
else:
alpn_fingerprint = "00"
# Assemble the raw fingerprint
raw_fingerprint = f"{protocol}{tls_version}{sni}{len(filtered_ciphers):02d}{len(filtered_extensions):02d}{alpn_fingerprint}_{cipher_list_str}_{combined_extensions}"
return raw_fingerprint
# Example usage
protocol = 't'
tls_version = '13'
sni = 'd'
ciphers = ['1301', '1302', '1303', 'c02b', 'c02f', 'c02c', 'c030', 'cca9', 'cca8', 'c013', 'c014', '009c', '009d', '002f', '0035']
extensions = ['001b', '0000', '0033', '0010', '4469', '0017', '002d', '000d', '0005', '0023', '0012', '002b', 'ff01', '000b', '000a', '0015']
alpn = ['h2']
signature_algorithms = ['0403', '0804', '0401', '0503', '0805', '0501', '0806', '0601']
# Raw sorted fingerprint
ja4_r = ja4_raw_fingerprint(protocol, tls_version, sni, ciphers, extensions, alpn, signature_algorithms, raw_type='sorted')
print(f"JA4_r: {ja4_r}")
# Raw original order fingerprint
ja4_ro = ja4_raw_fingerprint(protocol, tls_version, sni, ciphers, extensions, alpn, signature_algorithms, raw_type='original')
print(f"JA4_ro: {ja4_ro}")Further JA4+ Techniques and Use Cases
JA4D: DNS Query Fingerprinting
Overview
JA4D (JA4DNS) fingerprints DNS queries by analyzing the characteristics of DNS packets exchanged between clients and servers. It focuses on the query types, response codes, domain names, and other DNS parameters to identify client behaviors and potential security issues.
Key Concepts
• DNS Query Analysis: Examination of DNS query types, response codes, and domain names. • Client Behaviors: Identifying patterns in DNS queries to infer client activities. • Security Monitoring: Detecting suspicious or malicious DNS activities for threat hunting.
Constructing the JA4D Fingerprint
Format:
dns<query_type>_<response_code>_<domain_hash>Example Calculation
Step 1: Gather DNS Query Data
• Query Type: A (IPv4 address) • Response Code: NOERROR (0) • Domain Name: example.com
Step 2: Hash the Domain Name
• Domain Name: example.com
Compute Hash:
import hashlib
def compute_domain_hash(domain_name):
return hashlib.sha1(domain_name.encode()).hexdigest()[:5]
# Example usage
domain_name = 'example.com'
domain_hash = compute_domain_hash(domain_name)
print(f"Domain Hash: {domain_hash}") # Output: a1b2cStep 3: Assemble the Fingerprint
dnsA_NOERROR_a1b2cInterpretation
• DNS Query Types and Response Codes can reveal client intentions and server responses. • Unique Domain Hashes may help detect suspicious or malicious domain activities.