def test_fetch_values_by_datatype(): """Helpers - Fetch values from a record by normalized type""" rec = { 'account': 12345, 'region': '123456123456', 'detail': { 'eventVersion': '...', 'eventID': '...', 'eventTime': '...', 'additionalEventData': { 'MFAUsed': 'Yes', 'LoginTo': '...', 'MobileVersion': 'No' }, 'requestParameters': None, 'eventType': 'AwsConsoleSignIn', 'responseElements': { 'ConsoleLogin': '******' }, 'awsRegion': '...', 'eventName': 'ConsoleLogin', 'userIdentity': { 'userName': '******', 'type': 'Root', 'principalId': '12345', 'arn': 'arn:aws:iam::12345:root', 'accountId': '12345' }, 'eventSource': '...', 'userAgent': '...', 'sourceIPAddress': '1.1.1.2', 'recipientAccountId': '12345' }, 'detail-type': '...', 'source': '1.1.1.2', 'version': '1.05', 'streamalert:normalization': { 'ipv4': [['detail', 'sourceIPAddress'], ['source']], 'username': [['detail', 'userIdentity', 'userName']] }, 'time': '...', 'id': '12345', 'resources': { 'test': '...' } } assert_equal(len(base.fetch_values_by_datatype(rec, 'ipv4')), 2) assert_equal(len(base.fetch_values_by_datatype(rec, 'cmd')), 0) assert_equal(base.fetch_values_by_datatype(rec, 'username'), ['alice'])
def has_logs_datatypes(rec): # pylint: disable=unused-variable """Testing rule when logs is present, datatypes is""" results = fetch_values_by_datatype(rec, 'sourceAddress') for result in results: if result == '1.1.1.2': return True return False
def test_01_matching_sourceaddress_datatypes(rec): # pylint: disable=unused-variable """Testing rule to alert on matching sourceAddress""" results = fetch_values_by_datatype(rec, 'sourceAddress') for result in results: if result == '1.1.1.2': return True return False
def match_ipaddress(rec): # pylint: disable=unused-variable """Testing rule to detect matching IP address""" results = fetch_values_by_datatype(rec, 'sourceAddress') for result in results: if result == '1.1.1.2': return True return False
def match_ipaddress(rec): # pylint: disable=unused-variable """Testing rule to detect matching IP address Datatype 'sourceAddress' is defined in tests/unit/conf/types.json for cloudwatch logs. This rule should be trigger by testing event. """ results = fetch_values_by_datatype(rec, 'sourceAddress') return any(result == '1.1.1.2' for result in results)
def mismatch_types(rec): # pylint: disable=unused-variable """Testing rule with non-existing normalized type in the record. It should not trigger alert. """ results = fetch_values_by_datatype(rec, 'sourceAddress') for result in results: if result == '2.2.2.2': return True return False
def mismatch_types(rec): # pylint: disable=unused-variable """Testing rule with non-existing normalized type in the record. Datatype 'sourceAddress' is defined in tests/unit/conf/types.json for cloudwatch logs, but 'command' is not. This rule should be triggered by testing event since we change rule parameter 'datatypes' to OR operation among CEF types. See the discussion at https://github.com/airbnb/streamalert/issues/365 """ results = fetch_values_by_datatype(rec, 'sourceAddress') return any(result == '2.2.2.2' for result in results)
def right_to_left_character(rec): """ author: @javutin description: Malicious files can be disguised by using a encoding trick that uses the unicode character U+202E, also known as right-to-left-override (RLO). The trick hides a potentially malicious extension and makes them appear harmless. reference: https://krebsonsecurity.com/2011/09/right-to-left-override-aids-email-attacks playbook: (a) verify the file has an RTLO character and that the file is malicious ATT&CK Tactic: Defense Evasion ATT&CK Technique: Obfuscated Files or Information ATT&CK URL: https://attack.mitre.org/wiki/Technique/T1027 """ # Unicode character U+202E, right-to-left-override (RLO) rlo = u'\u202e' commands = fetch_values_by_datatype(rec, 'command') for command in commands: if isinstance(command, unicode) and rlo in command: return True file_paths = fetch_values_by_datatype(rec, 'filePath') for file_path in file_paths: if isinstance(file_path, unicode) and rlo in file_path: return True process_paths = fetch_values_by_datatype(rec, 'processPath') for process_path in process_paths: if isinstance(process_path, unicode) and rlo in process_path: return True file_names = fetch_values_by_datatype(rec, 'fileName') for file_name in file_names: if isinstance(file_name, unicode) and rlo in file_name: return True return False