feat: include recon identity in exports
This commit is contained in:
@@ -2040,14 +2040,50 @@ def _csv_escape(v):
|
||||
return v
|
||||
|
||||
|
||||
def _identity_label(identity):
|
||||
identity = identity or {}
|
||||
manufacturer = identity.get('manufacturer') or 'Unknown'
|
||||
model = identity.get('model')
|
||||
if model:
|
||||
return '%s %s' % (manufacturer, model)
|
||||
if manufacturer == 'Unknown' and identity.get('oui'):
|
||||
return 'Unknown (%s)' % identity['oui']
|
||||
return manufacturer
|
||||
|
||||
|
||||
def _association_label(association):
|
||||
parts = [association.get('ssid') or '(hidden)']
|
||||
if association.get('bssid'):
|
||||
parts.append(association['bssid'])
|
||||
if association.get('sources'):
|
||||
parts.append('[' + ', '.join(association['sources']) + ']')
|
||||
return ' '.join(parts)
|
||||
|
||||
|
||||
def _aps_csv(data):
|
||||
out = ['bssid,ssid,hidden,band,channel,freq,encryption,signal,vendor,first_seen,last_seen']
|
||||
out = ['bssid,ssid,hidden,band,channel,freq,encryption,signal,vendor,first_seen,last_seen,Device Identity,Client Count,Confirmed SSIDs']
|
||||
for a in (data or {}).get('aps') or []:
|
||||
confirmed = []
|
||||
for client in a.get('clients') or []:
|
||||
for association in client.get('associations') or []:
|
||||
if association.get('bssid') == a.get('bssid'):
|
||||
confirmed.append(association.get('ssid') or '(hidden)')
|
||||
out.append(','.join(_csv_escape(x) for x in [
|
||||
a.get('bssid'), a.get('ssid'), int(bool(a.get('hidden'))),
|
||||
a.get('band'), a.get('channel'), a.get('freq'),
|
||||
a.get('encryption'), a.get('signal'), a.get('vendor'),
|
||||
_fmt_ts(a.get('first_seen')), _fmt_ts(a.get('last_seen'))]))
|
||||
_fmt_ts(a.get('first_seen')), _fmt_ts(a.get('last_seen')),
|
||||
_identity_label(a.get('device_identity')), a.get('client_count', 0),
|
||||
'; '.join(sorted(set(confirmed)))]))
|
||||
clients = (data or {}).get('clients') or []
|
||||
if clients:
|
||||
out.append('client_mac,client_identity,confirmed_associations')
|
||||
for client in clients:
|
||||
associations = [_association_label(a)
|
||||
for a in client.get('associations') or []]
|
||||
out.append(','.join(_csv_escape(x) for x in [
|
||||
client.get('mac'), _identity_label(client.get('vendor')),
|
||||
'; '.join(associations)]))
|
||||
out.append('unassociated,%d' % ((data or {}).get('unassociated') or 0))
|
||||
return '\r\n'.join(out) + '\r\n'
|
||||
|
||||
@@ -2249,14 +2285,30 @@ def _recon_html_download(scan_id, data, client_count, archive=None):
|
||||
ap_rows.append([a.get('ssid') or '(hidden)', a.get('bssid'),
|
||||
a.get('band') or '--',
|
||||
a.get('channel') if a.get('channel') is not None else '--',
|
||||
_signal_html(a.get('signal')),
|
||||
a.get('encryption') or '--',
|
||||
a.get('vendor') or '--',
|
||||
_fmt_ts(a.get('first_seen')), _fmt_ts(a.get('last_seen'))])
|
||||
_signal_html(a.get('signal')),
|
||||
a.get('encryption') or '--',
|
||||
_identity_label(a.get('device_identity')),
|
||||
a.get('client_count', 0),
|
||||
_fmt_ts(a.get('first_seen')), _fmt_ts(a.get('last_seen'))])
|
||||
body_parts.append('<h2>Access Points</h2>')
|
||||
body_parts.append(_html_table(['SSID', 'BSSID', 'Band', 'Ch', 'Signal',
|
||||
'Encryption', 'Vendor', 'First seen', 'Last seen'],
|
||||
ap_rows, raw_columns=(4,)))
|
||||
'Encryption', 'Device Identity', 'Clients',
|
||||
'First seen', 'Last seen'],
|
||||
ap_rows, raw_columns=(4,)))
|
||||
confirmed_rows = []
|
||||
for client in data.get('clients') or []:
|
||||
for association in client.get('associations') or []:
|
||||
confirmed_rows.append([
|
||||
client.get('mac'), _identity_label(client.get('vendor')),
|
||||
association.get('ssid') or '(hidden)', association.get('bssid') or '--',
|
||||
', '.join(association.get('sources') or [])])
|
||||
body_parts.append('<h2>Confirmed Clients</h2>')
|
||||
if confirmed_rows:
|
||||
body_parts.append(_html_table(
|
||||
['Client MAC', 'Device Identity', 'SSID', 'BSSID', 'Evidence'],
|
||||
confirmed_rows))
|
||||
else:
|
||||
body_parts.append('<p class="empty">No confirmed clients.</p>')
|
||||
subtitle = ('Pager recon capture report (archived history)'
|
||||
if archive else 'Pager recon capture report')
|
||||
return Download(_html_doc('Scan #%d' % scan.get('id'),
|
||||
|
||||
Reference in New Issue
Block a user