Converting GoAML into MISPEvent

pull/168/head
chrisr3d 2018-02-28 15:07:55 +01:00
parent cad62464c5
commit 8f5c08e2c6
No known key found for this signature in database
GPG Key ID: 6BBED1B63A6D639F
1 changed files with 58 additions and 37 deletions

View File

@ -1,7 +1,7 @@
import json, datetime import json, datetime
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from collections import defaultdict from collections import defaultdict
from pymisp import MISPEvent from pymisp import MISPEvent, MISPObject
misperrors = {'error': 'Error'} misperrors = {'error': 'Error'}
moduleinfo = {'version': 1, 'author': 'Christian Studer', moduleinfo = {'version': 1, 'author': 'Christian Studer',
@ -18,12 +18,12 @@ t_person_objects = {'nodes': ['addresses'],
'leaves': ['first_name', 'middle_name', 'last_name', 'gender', 'title', 'mothers_name', 'birthdate', 'leaves': ['first_name', 'middle_name', 'last_name', 'gender', 'title', 'mothers_name', 'birthdate',
'passport_number', 'passport_country', 'id_number', 'birth_place', 'alias', 'nationality1']} 'passport_number', 'passport_country', 'id_number', 'birth_place', 'alias', 'nationality1']}
t_account_objects = {'nodes': ['signatory'], t_account_objects = {'nodes': ['signatory'],
'leaves': ['institution_name', 'institution_code', 'swift', 'branch', 'non_banking_insitution', 'leaves': ['institution_name', 'institution_code', 'swift', 'branch', 'non_banking_insitution',
'account', 'currency_code', 'account_name', 'iban', 'client_number', 'opened', 'closed', 'account', 'currency_code', 'account_name', 'iban', 'client_number', 'opened', 'closed',
'personal_account_type', 'balance', 'date_balance', 'status_code', 'beneficiary', 'personal_account_type', 'balance', 'date_balance', 'status_code', 'beneficiary',
'beneficiary_comment', 'comments']} 'beneficiary_comment', 'comments']}
entity_objects = {'nodes': ['addresses'], entity_objects = {'nodes': ['addresses'],
'leaves': ['name', 'commercial_name', 'incorporation_legal_form', 'incorporation_number', 'business', 'phone']} 'leaves': ['name', 'commercial_name', 'incorporation_legal_form', 'incorporation_number', 'business', 'phone']}
goAMLobjects = {'report': {'nodes': ['reporting_person', 'location'], goAMLobjects = {'report': {'nodes': ['reporting_person', 'location'],
'leaves': ['rentity_id', 'submission_code', 'report_code', 'submission_date', 'currency_code_local']}, 'leaves': ['rentity_id', 'submission_code', 'report_code', 'submission_date', 'currency_code_local']},
@ -42,30 +42,30 @@ goAMLobjects = {'report': {'nodes': ['reporting_person', 'location'],
'from_entity': entity_objects, 'to_entity': entity_objects, 'from_entity': entity_objects, 'to_entity': entity_objects,
} }
t_account_mapping = {'t_account': 'bank-account', 'institution_name': 'institution-name', 'institution_code': 'institution-code', t_account_mapping = {'misp_name': 'bank-account', 'institution_name': 'institution-name', 'institution_code': 'institution-code',
'iban': 'iban', 'swift': 'swift', 'branch': 'branch', 'non_banking_institution': 'non-bank-institution', 'iban': 'iban', 'swift': 'swift', 'branch': 'branch', 'non_banking_institution': 'non-bank-institution',
'account': 'account', 'currency_code': 'currency-code', 'account_name': 'account-name', 'account': 'account', 'currency_code': 'currency-code', 'account_name': 'account-name',
'client_number': 'client-number', 'personal_account_type': 'personal-account-type', 'opened': 'opened', 'client_number': 'client-number', 'personal_account_type': 'personal-account-type', 'opened': 'opened',
'closed': 'closed', 'balance': 'balance', 'status_code': 'status-code', 'beneficiary': 'beneficiary', 'closed': 'closed', 'balance': 'balance', 'status_code': 'status-code', 'beneficiary': 'beneficiary',
'beneficiary_comment': 'beneficiary-comment', 'comments': 'comments'} 'beneficiary_comment': 'beneficiary-comment', 'comments': 'comments'}
t_person_mapping = {'t_person': 'person', 'comments': 'text', 'first_name': 'first-name', 'middle_name': 'middle-name', t_person_mapping = {'misp_name': 'person', 'comments': 'text', 'first_name': 'first-name', 'middle_name': 'middle-name',
'last_name': 'last-name', 'title': 'title', 'mothers_name': 'mothers-name', 'alias': 'alias', 'last_name': 'last-name', 'title': 'title', 'mothers_name': 'mothers-name', 'alias': 'alias',
'birthdate': 'date-of-birth', 'birth_place': 'place-of-birth', 'gender': 'gender','nationality1': 'nationality', 'birthdate': 'date-of-birth', 'birth_place': 'place-of-birth', 'gender': 'gender','nationality1': 'nationality',
'passport_number': 'passport-number', 'passport_country': 'passport-country', 'ssn': 'social-security-number', 'passport_number': 'passport-number', 'passport_country': 'passport-country', 'ssn': 'social-security-number',
'id_number': 'identity-card-number'} 'id_number': 'identity-card-number'}
location_mapping = {'location': 'geolocation', 'city': 'city', 'state': 'region', 'country-code': 'country', 'address': 'address', location_mapping = {'misp_name': 'geolocation', 'city': 'city', 'state': 'region', 'country_code': 'country', 'address': 'address',
'zip': 'zipcode'} 'zip': 'zipcode'}
t_entity_mapping = {'entity': 'legal-entity', 'name': 'name', 'business': 'business', 'commercial_name': 'commercial-name', t_entity_mapping = {'misp_name': 'legal-entity', 'name': 'name', 'business': 'business', 'commercial_name': 'commercial-name',
'phone': 'phone-number', 'incorporation_legal_form': 'legal-form', 'incorporation_number': 'registration-number'} 'phone': 'phone-number', 'incorporation_legal_form': 'legal-form', 'incorporation_number': 'registration-number'}
goAMLmapping = {'from_account': t_account_mapping, 'to_account': t_account_mapping, goAMLmapping = {'from_account': t_account_mapping, 'to_account': t_account_mapping, 't_person': t_person_mapping,
'from_person': t_person_mapping, 'to_person': t_person_mapping, 'reporting_person': t_person_mapping, 'from_person': t_person_mapping, 'to_person': t_person_mapping, 'reporting_person': t_person_mapping,
'from_entity': t_entity_mapping, 'to_entity': t_entity_mapping, 'from_entity': t_entity_mapping, 'to_entity': t_entity_mapping,
'location': location_mapping, 'address': location_mapping, 'location': location_mapping, 'address': location_mapping,
'transaction': {'transaction': 'transaction', 'transactionnumber': 'transaction-number', 'date_transaction': 'date', 'transaction': {'misp_name': 'transaction', 'transactionnumber': 'transaction-number', 'date_transaction': 'date',
'transaction_location': 'location', 'transmode_code': 'transmode-code', 'amount_local': 'amount', 'transaction_location': 'location', 'transmode_code': 'transmode-code', 'amount_local': 'amount',
'transmode_comment': 'transmode-comment', 'date_posting': 'date-posting', 'teller': 'teller', 'transmode_comment': 'transmode-comment', 'date_posting': 'date-posting', 'teller': 'teller',
'authorized': 'authorized', 'transaction_description': 'text'}} 'authorized': 'authorized', 'transaction_description': 'text'}}
@ -74,43 +74,64 @@ nodes_to_ignore = ['addresses', 'signatory']
class GoAmlParser(): class GoAmlParser():
def __init__(self): def __init__(self):
self.dict = {}
self.misp_event = MISPEvent() self.misp_event = MISPEvent()
def readFile(self, filename): def readFile(self, filename):
self.tree = ET.parse(filename).getroot() self.tree = ET.parse(filename).getroot()
def parse_xml(self): def parse_xml(self):
self.dict = self.itterate(self.tree, 'report') self.first_itteration()
self.dict['transaction'] = []
for t in self.tree.findall('transaction'): for t in self.tree.findall('transaction'):
self.dict['transaction'].append(self.itterate(t, 'transaction')) self.itterate(t, 'transaction')
self.misp_event.timestamp = self.dict.get('submission_date')
def first_itteration(self):
self.misp_event.timestamp = self.tree.find('submission_date').text
for node in goAMLobjects['report']['nodes']:
element = self.tree.find(node)
if element is not None:
self.itterate(element, element.tag)
def itterate(self, tree, aml_type): def itterate(self, tree, aml_type):
element_dict = {} objects = goAMLobjects[aml_type]
for element in tree: if aml_type not in nodes_to_ignore:
tag = element.tag try:
mapping = goAMLobjects.get(aml_type) mapping = goAMLmapping[aml_type]
if tag in mapping.get('nodes'): misp_object = MISPObject(name=mapping['misp_name'])
for leaf in objects['leaves']:
element = tree.find(leaf)
if element is not None:
object_relation = mapping[element.tag]
attribute = {'object_relation': object_relation, 'value': element.text}
misp_object.add_attribute(**attribute)
if aml_type == 'transaction': if aml_type == 'transaction':
self.fill_transaction(element, element_dict, tag) for node in objects['nodes']:
element_dict[tag] = self.itterate(element, tag) element = tree.find(node)
elif tag in mapping.get('leaves'): if element is not None:
try: self.fill_transaction(element, element.tag, misp_object)
element_dict[goAMLmapping[aml_type][tag]] = element.text self.misp_event.add_object(misp_object)
except KeyError: except KeyError:
pass pass
return element_dict for node in objects['nodes']:
element = tree.find(node)
if element is not None:
self.itterate(element, element.tag)
@staticmethod @staticmethod
def fill_transaction(element, element_dict, tag): def fill_transaction(element, tag, misp_object):
if 't_from' in tag: if 't_from' in tag:
element_dict['from-funds-code'] = element.find('from_funds_code').text from_funds = element.find('from_funds_code').text
element_dict['from-country'] = element.find('from_country').text from_funds_attribute = {'object_relation': 'from-funds-code', 'value': from_funds}
misp_object.add_attribute(**from_funds_attribute)
from_country = element.find('from_country').text
from_country_attribute = {'object_relation': 'from-country', 'value': from_country}
misp_object.add_attribute(**from_country_attribute)
if 't_to' in tag: if 't_to' in tag:
element_dict['to-funds-code'] = element.find('to_funds_code').text to_funds = element.find('to_funds_code').text
element_dict['to-country'] = element.find('to_country').text to_funds_attribute = {'object_relation': 'to-funds-code', 'value': to_funds}
misp_object.add_attribute(**to_funds_attribute)
to_country = element.find('to_country').text
to_country_attribute = {'object_relation': 'to-country', 'value': to_country}
misp_object.add_attribute(**to_country_attribute)
def handler(q=False): def handler(q=False):
if q is False: if q is False:
@ -128,7 +149,7 @@ def handler(q=False):
misperrors['error'] = "Impossible to read the file" misperrors['error'] = "Impossible to read the file"
return misperrors return misperrors
aml_parser.parse_xml() aml_parser.parse_xml()
return aml_parser.dict return aml_parser.misp_event.to_json()
def introspection(): def introspection():
return mispattributes return mispattributes