mirror of
https://github.com/optim-enterprises-bv/nDPId.git
synced 2025-10-30 17:57:48 +00:00
Added python example to check JA3 hashes against known hashes via JA3er.com
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
This commit is contained in:
@@ -41,6 +41,13 @@ Captures and saves risky flows to a PCAP file.
|
||||
|
||||
Validate nDPId JSON strings against pre-defined JSON schema's.
|
||||
See `schema/`.
|
||||
Required by `tests/run_tests.sh`
|
||||
|
||||
## py-semantic-validation
|
||||
|
||||
Validate nDPId JSON strings against internal event semantics.
|
||||
Required by `tests/run_tests.sh`
|
||||
|
||||
## py-ja3-checker
|
||||
|
||||
Captures JA3 hashes from nDPIsrvd and checks them against known hashes from [ja3er.com](https://ja3er.com).
|
||||
|
||||
101
examples/py-ja3-checker/py-ja3-checker.py
Executable file
101
examples/py-ja3-checker/py-ja3-checker.py
Executable file
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import json
|
||||
import os
|
||||
import requests
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.append(os.path.dirname(sys.argv[0]) + '/../share/nDPId')
|
||||
sys.path.append(os.path.dirname(sys.argv[0]) + '/../usr/share/nDPId')
|
||||
try:
|
||||
import nDPIsrvd
|
||||
from nDPIsrvd import nDPIsrvdSocket
|
||||
except ImportError:
|
||||
sys.path.append(os.path.dirname(sys.argv[0]) + '/../../dependencies')
|
||||
import nDPIsrvd
|
||||
from nDPIsrvd import nDPIsrvdSocket
|
||||
|
||||
global ja3_fps
|
||||
ja3_fps = dict()
|
||||
# 1 hour = 3600 sec/hour = (60 minutes/hour) * (60 seconds/minute)
|
||||
JA3_FP_MAX_AGE = 60 * 60
|
||||
|
||||
|
||||
class JA3ER(object):
|
||||
def __init__(self, json_dict):
|
||||
self.json = json_dict
|
||||
self.last_checked = time.time()
|
||||
|
||||
def isTooOld(self):
|
||||
current_time = time.time()
|
||||
if current_time - self.last_checked >= JA3_FP_MAX_AGE:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def isJA3InfoTooOld(ja3_hash):
|
||||
if ja3_hash in ja3_fps:
|
||||
if ja3_fps[ja3_hash].isTooOld() is True:
|
||||
print('Fingerprint {} too old, re-newing..'.format(ja3_hash))
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def getInfoFromJA3ER(ja3_hash):
|
||||
response = requests.get('https://ja3er.com/search/' + ja3_hash)
|
||||
if response.status_code == 200:
|
||||
ja3_fps[ja3_hash] = JA3ER(json.loads(response.text, strict=True))
|
||||
if 'error' not in ja3_fps[ja3_hash].json:
|
||||
print('Fingerprints for JA3 {}:'.format(ja3_hash))
|
||||
for ua in ja3_fps[ja3_hash].json:
|
||||
if 'User-Agent' in ua:
|
||||
print('\tUser-Agent: {}\n'
|
||||
'\t Last seen: {}, '
|
||||
'Count: {}'.format(ua['User-Agent'],
|
||||
ua['Last_seen'],
|
||||
ua['Count']))
|
||||
elif 'Comment' in ua:
|
||||
print('\tComment...: {}\n'
|
||||
'\t Reported: {}'
|
||||
.format(ua['Comment'].replace('\r', '')
|
||||
.replace('\n', ' '), ua['Reported']))
|
||||
else:
|
||||
print(ua)
|
||||
else:
|
||||
print('No fingerprint for JA3 {} found.'.format(ja3_hash))
|
||||
|
||||
|
||||
def onJsonLineRecvd(json_dict, current_flow, global_user_data):
|
||||
if 'tls' in json_dict and 'ja3' in json_dict['tls']:
|
||||
|
||||
if json_dict['tls']['client_requested_server_name'] == 'ja3er.com':
|
||||
return True
|
||||
|
||||
if isJA3InfoTooOld(json_dict['tls']['ja3']) is True:
|
||||
getInfoFromJA3ER(json_dict['tls']['ja3'])
|
||||
|
||||
if isJA3InfoTooOld(json_dict['tls']['ja3']) is True:
|
||||
getInfoFromJA3ER(json_dict['tls']['ja3s'])
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
argparser = nDPIsrvd.defaultArgumentParser()
|
||||
args = argparser.parse_args()
|
||||
address = nDPIsrvd.validateAddress(args)
|
||||
|
||||
sys.stderr.write('Recv buffer size: {}\n'
|
||||
.format(nDPIsrvd.NETWORK_BUFFER_MAX_SIZE))
|
||||
sys.stderr.write('Connecting to {} ..\n'
|
||||
.format(address[0] + ':' +
|
||||
str(address[1])
|
||||
if type(address) is tuple else address))
|
||||
|
||||
nsock = nDPIsrvdSocket()
|
||||
nsock.connect(address)
|
||||
nsock.loop(onJsonLineRecvd, None)
|
||||
Reference in New Issue
Block a user