| |
| |
| |
| |
|
|
| import netaddr |
|
|
|
|
| def isIPv4(ip): |
| try: |
| return netaddr.valid_ipv4(ip) |
| except: |
| return False |
|
|
|
|
| def isIPv6(ip): |
| try: |
| return netaddr.valid_ipv6(ip) |
| except: |
| return False |
|
|
|
|
| def addError(message, error): |
| '''add an error note to a message''' |
| if 'errors' not in message: |
| message['errors'] = list() |
| if isinstance(message['errors'], list): |
| message['errors'].append(error) |
|
|
|
|
| class message(object): |
| def __init__(self): |
| ''' |
| uses heuristic to find and attach the source IP address of the alert |
| ''' |
|
|
| |
| self.registration = ['*'] |
| self.priority = 1 |
|
|
| def onMessage(self, message): |
| ''' |
| Examine possible ip addresses for the following: |
| ipv6 in an ipv4 field |
| ipv4 in another field |
| '-' or other invalid ip in the ip field |
| Also sets ipv4 in two fields: |
| ipaddress (decimal mapping IP) |
| ipv4address (string mapping) |
| Elastic search is inconsistent about returning IPs as |
| decimal or IPs. |
| In a query an IP field is returned as string. |
| In a facets an IP field is returned as decimal. |
| No ES field type exists for ipv6, so always having |
| a string version is the most flexible option. |
| ''' |
|
|
| |
| if 'events' in message: |
| if 'documentsource' in message['events'][0]: |
| if 'details' in message['events'][0]['documentsource']: |
| event = message['events'][0]['documentsource']['details'] |
| if 'details' not in message: |
| message['details'] = {} |
| |
| |
| if 'http_x_forwarded_for' in event: |
| |
| ipText = event['http_x_forwarded_for'].split(',')[0] |
| if isIPv4(ipText) and 'sourceipaddress' not in event: |
| message['details']['sourceipaddress'] = ipText |
| if isIPv4(ipText) and 'sourceipv4address' not in event: |
| message['details']['sourceipv4address'] = ipText |
| if isIPv6(ipText) and 'sourceipv6address' not in event: |
| message['details']['sourceipv6address'] = ipText |
|
|
| if 'sourceipaddress' in event: |
| ipText = event['sourceipaddress'] |
| if isIPv6(ipText): |
| event['sourceipv6address'] = ipText |
| message['details']['sourceipaddress'] = '0.0.0.0' |
| addError(message, 'plugin: {0} error: {1}'.format('ipFixUp.py', 'sourceipaddress is ipv6, moved')) |
| elif isIPv4(ipText): |
| message['details']['sourceipv4address'] = ipText |
| message['details']['sourceipaddress'] = ipText |
| else: |
| |
| message['details']['source'] = event['sourceipaddress'] |
| message['details']['sourceipaddress'] = None |
|
|
| if 'destinationipaddress' in event: |
| ipText = event['destinationipaddress'] |
| if isIPv6(ipText): |
| message['details']['destinationipv6address'] = ipText |
| message['details']['destinationipaddress'] = '0.0.0.0' |
| addError(message, 'plugin: {0} error: {1}'.format('ipFixUp.py', 'destinationipaddress is ipv6, moved')) |
| elif isIPv4(ipText): |
| message['details']['destinationipv4address'] = ipText |
| message['details']['destinationipaddress'] = ipText |
| else: |
| |
| message['details']['destination'] = event['destinationipaddress'] |
| message['details']['destinationipaddress'] = None |
|
|
| if 'cluster_client_ip' in event: |
| ipText = event['cluster_client_ip'] |
| if isIPv4(ipText): |
| message['details']['sourceipaddress'] = ipText |
|
|
| |
| |
| |
| |
| return message |
|
|