def updateLocation(gateway, packet): # This value can be changed for more/less accuracy location_accuracy = 20.0 if packet.latitude is None or packet.longitude is None: return gateway else: lati = packet.latitude long = packet.longitude if gateway.location_latitude is None or gateway.location_longitude is None: gateway.location_latitude = lati gateway.location_longitude = long else: if measure(gateway.location_latitude, gateway.location_longitude, lati, long) > location_accuracy: parameters = {} parameters["gateway"] = gateway.gw_hex_id parameters["location_latitude"] = gateway.location_latitude parameters["location_longitude"] = gateway.location_longitude parameters["lati"] = lati parameters["long"] = long parameters['packet_date'] = packet.date.strftime( '%Y-%m-%d %H:%M:%S') try: alert = Alert(type="LAF-010", created_at=datetime.datetime.now(), packet_id=packet.id, gateway_id=gateway.id, parameters=json.dumps(parameters), data_collector_id=packet.data_collector_id) alert.save() ReportAlert.print_alert(alert) except Exception as exc: logging.error( "Error trying to save Alert LAF-010: {0}".format(exc)) gateway.location_latitude = lati gateway.location_longitude = long return gateway
def updateLocation(gateway, packet): if packet.latitude is None or packet.longitude is None: pass else: lati = packet.latitude long = packet.longitude if gateway.location_latitude is not None or gateway.location_longitude is not None: # A fourth decimal's precision (0,0001) is near 11.132 m if abs(gateway.location_latitude - lati) > 0.0001 or abs(gateway.location_longitude - long) > 0.001: parameters = {} parameters["gw_hex_id"] = gateway.gw_hex_id parameters["location_latitude"] = gateway.location_latitude parameters["location_longitude"] = gateway.location_longitude parameters["new_location_latitude"] = lati parameters["new_location_longitude"] = long try: alert = Alert(type="LAF-010", created_at=datetime.datetime.now(), packet_id=packet.id, gateway_id=gateway.id, parameters=json.dumps(parameters), data_collector_id=packet.data_collector_id) alert.save() except Exception as exc: logging.error( "Error trying to save Alert LAF-010: {0}".format(exc)) ReportAlert.print_alert(alert) gateway.location_latitude = lati gateway.location_longitude = long return gateway
def processPacket(packet): gw_obj = None if packet.gateway is not None: gw_obj = Gateway.find_one_by_gw_hex_id_and_organization_id( packet.gateway, packet.organization_id) if gw_obj is None: try: gw_obj = Gateway(gw_hex_id=packet.gateway, location_latitude=packet.latitude, location_longitude=packet.longitude, data_collector_id=packet.data_collector_id, organization_id=packet.organization_id) gw_obj.save() except Exception as exc: logging.error("Error trying to save Gateway: {0}".format(exc)) gw_obj = updateLocation(gw_obj, packet) if packet.m_type == "JoinRequest": device_obj = Device.find_one_by_dev_eui_and_join_eui_and_datacollector_id( packet.dev_eui, packet.join_eui, packet.data_collector_id) if device_obj is None: device_obj = Device.find_one_by_dev_eui_and_join_eui_and_datacollector_id( packet.dev_eui, None, packet.data_collector_id) if device_obj is None: try: device_obj = Device( dev_eui=packet.dev_eui, join_eui=packet.join_eui, organization_id=packet.organization_id, ) device_obj.save() except Exception as exc: logging.error( "Error trying to save Gateway: {0}".format(exc)) else: # Add the JoinEUI device_obj.join_eui = packet.join_eui # Associate Device with a Gateway if gw_obj is not None: try: gateway_device_obj = GatewayToDevice.find_one_by_gateway_id_and_device_id( gw_obj.id, device_obj.id) if gateway_device_obj is None: gateway_device_obj = GatewayToDevice( gateway_id=gw_obj.id, device_id=device_obj.id) gateway_device_obj.save() except Exception as exc: logging.error( "Error trying to save GatewayToDevice: {0}".format(exc)) else: # If we don't receive the gateway in the packet, # get the hex ID of the gateway associated to the device if any. # If we have more than 1 gateway associated to the device, this method returns None gw_obj = Gateway.find_only_one_gateway_by_device_id(device_obj.id) # Associate Device with the DataCollector if not previously existing device_data_collector_obj = DataCollectorToDevice.find_one_by_data_collector_id_and_device_id( packet.data_collector_id, device_obj.id) if device_data_collector_obj is None: try: device_data_collector_obj = DataCollectorToDevice( data_collector_id=packet.data_collector_id, device_id=device_obj.id) device_data_collector_obj.save() except Exception as exc: logging.error( "Error trying to save DataCollectorToDevice from a JoinRequest: {0}" .format(exc)) # Check if DevNonce is repeated and save it prev_packet_id = DevNonce.saveIfNotExists(packet.dev_nonce, device_obj.id, packet.id) if prev_packet_id and (device_obj.has_joined or device_obj.join_inferred): device_obj.repeated_dev_nonce = True parameters = {} parameters["dev_eui"] = device_obj.dev_eui parameters["dev_nonce"] = packet.dev_nonce parameters["prev_packet_id"] = prev_packet_id parameters['packet_date'] = packet.date.strftime( '%Y-%m-%d %H:%M:%S') if gw_obj: parameters["gateway"] = gw_obj.gw_hex_id else: parameters["gateway"] = "Unkwown" try: alert = Alert(type="LAF-001", created_at=datetime.datetime.now(), packet_id=packet.id, device_id=device_obj.id, parameters=json.dumps(parameters), data_collector_id=packet.data_collector_id) alert.save() ReportAlert.print_alert(alert) except Exception as exc: logging.error( "Error trying to save Alert LAF-001: {0}".format(exc)) elif not (prev_packet_id): device_obj.has_joined = False device_obj.join_inferred = False device_obj.join_request_counter += 1 device_obj.is_otaa = True # Save the first time it was seen if device_obj.first_up_timestamp is None: device_obj.first_up_timestamp = packet.date # Save the last time it was seen device_obj.last_up_timestamp = packet.date device_obj.last_packet_id = packet.id elif packet.m_type == "JoinAccept": # If the packet has a devEUI, increment the JoinAccept Counter in Device if packet.dev_eui is not None: devices = Device.find(packet.dev_eui, packet.data_collector_id) # Device with dev_eui exists an it's unique if len(devices) == 1: devices[0].join_accept_counter += 1 devices[0].has_joined = True # Device with dev_eui doesn't exists. We must create the object (although we haven't the join_eui) elif len(devices) == 0: try: device_obj = Device(dev_eui=packet.dev_eui, organization_id=packet.organization_id, has_joined=True, join_accept_counter=1) device_obj.save() except Exception as exc: logging.error( "Error trying to save Device from a JoinAccept: {0}". format(exc)) try: # Associate Device with the DataCollector device_data_collector_obj = DataCollectorToDevice( data_collector_id=packet.data_collector_id, device_id=device_obj.id) device_data_collector_obj.save() except Exception as exc: logging.error( "Error trying to save DataCollectorToDevice from a JoinAccept: {0}" .format(exc)) # We have more than one device. If the last packet received in that datacollector is a JoinReq, get the Device elif len(devices) > 1: last_packet = Packet.find_previous_by_data_collector_and_dev_eui( packet.date, packet.data_collector_id, packet.dev_eui) if last_packet is not None and last_packet.m_type == "JoinRequest": device_obj = Device.find_one_by_dev_eui_and_join_eui_and_datacollector_id( last_packet.dev_eui, last_packet.join_eui, packet.data_collector_id) if device_obj is not None: device_obj.join_accept_counter += 1 device_obj.has_joined = True else: logging.warning( "Warning! Received a JoinAccept for a dev_eui shared by at least two devices" ) # If we don't know the deveui, check if the last packet received in that datacollector is a JoinReq else: last_packet = Packet.find_previous_by_data_collector_and_dev_eui( packet.date, packet.data_collector_id, None) if last_packet is not None and last_packet.m_type == "JoinRequest": device_obj = Device.find_one_by_dev_eui_and_join_eui_and_datacollector_id( last_packet.dev_eui, last_packet.join_eui, packet.data_collector_id) if device_obj is not None: device_obj.join_accept_counter += 1 device_obj.join_inferred = True # Case DataPacket elif packet.m_type == "UnconfirmedDataUp" or packet.m_type == "UnconfirmedDataDown" or packet.m_type == "ConfirmedDataUp" or packet.m_type == "ConfirmedDataDown": dev_ses_obj = DeviceSession.find_one_by_dev_addr_and_datacollector_id( packet.dev_addr, packet.data_collector_id) if dev_ses_obj is None: try: dev_ses_obj = DeviceSession( dev_addr=packet.dev_addr, organization_id=packet.organization_id, is_confirmed=(packet.m_type == "ConfirmedDataUp" or packet.m_type == "ConfirmedDataDown")) dev_ses_obj.save() except Exception as exc: logging.error( "Error trying to save DeviceSession: {0}".format(exc)) # In case we received the dev_eui, check if we have the Device in the database device_obj = None if packet.dev_eui is not None: devices = Device.find(packet.dev_eui, packet.data_collector_id) # Device with dev_eui exists an it's unique if len(devices) == 1: device_obj = devices[0] # Device with dev_eui doesn't exists. We must create the object (although we haven't the join_eui) elif len(devices) == 0: try: device_obj = Device(dev_eui=packet.dev_eui, organization_id=packet.organization_id) device_obj.save() except Exception as exc: logging.error( "Error trying to save Device from a Data packet: {0}". format(exc)) # Associate Device with the DataCollector try: device_data_collector_obj = DataCollectorToDevice( data_collector_id=packet.data_collector_id, device_id=device_obj.id) device_data_collector_obj.save() except Exception as exc: logging.error( "Error trying to save DataCollectorToDevice from a Data packet: {0}" .format(exc)) # We have more than one device. We can't do anything. elif len(devices) > 1: logging.warning( "Warning! Received a DataPacket for a dev_eui shared by at least two devices" ) # Associate DeviceSession with a Gateway if gw_obj is not None: gateway_device_session_obj = GatewayToDeviceSession.find_one_by_gateway_id_and_device_session_id( gw_obj.id, dev_ses_obj.id) if gateway_device_session_obj is None: try: gateway_device_session_obj = GatewayToDeviceSession( gateway_id=gw_obj.id, device_session_id=dev_ses_obj.id) gateway_device_session_obj.save() except Exception as exc: logging.error( "Error trying to save GatewayToDeviceSession: {0}". format(exc)) else: # If we don't receive the gateway in the packet, # get the hex ID of the gateway associated to the device_session if any. # If we have more than 1 gateway associated to the device_session, this method returns None gw_obj = Gateway.find_only_one_gateway_by_device_session_id( dev_ses_obj.id) # Associate DeviceSession with the DataCollector device_session_data_collector_obj = DataCollectorToDeviceSession.find_one_by_data_collector_id_and_device_session_id( packet.data_collector_id, dev_ses_obj.id) if device_session_data_collector_obj is None: try: device_session_data_collector_obj = DataCollectorToDeviceSession( data_collector_id=packet.data_collector_id, device_session_id=dev_ses_obj.id) device_session_data_collector_obj.save() except Exception as exc: logging.error( "Error trying to save DataCollectorToDeviceSession: {0}". format(exc)) is_uplink_packet = (packet.m_type == "UnconfirmedDataUp" or packet.m_type == "ConfirmedDataUp") if is_uplink_packet: # Check counter if packet.f_count == 0: if dev_ses_obj.id in last_uplink_mic: # Make sure we have processed at least one packet for this device in this run before firing the alarm # Skip if received the same counter as previous packet and mics are equal if not (packet.f_count == dev_ses_obj.getCounter(is_uplink_packet) and last_uplink_mic[dev_ses_obj.id] == packet.mic): if device_obj is not None and device_obj.has_joined: # The counter = 0 is valid, then change the has_joined flag device_obj.has_joined = False elif device_obj is not None and device_obj.join_inferred: # The counter = 0 is valid, then change the join_inferred flag device_obj.join_inferred = False else: parameters = {} parameters["dev_addr"] = dev_ses_obj.dev_addr parameters["counter"] = dev_ses_obj.getCounter( is_uplink_packet) parameters["new_counter"] = packet.f_count parameters[ "prev_packet_id"] = dev_ses_obj.last_packet_id parameters['packet_date'] = packet.date.strftime( '%Y-%m-%d %H:%M:%S') if device_obj: parameters['dev_eui'] = device_obj.dev_eui else: parameters['dev_eui'] = 'Unkwown' if gw_obj: parameters["gateway"] = gw_obj.gw_hex_id else: parameters["gateway"] = "Unkwown" try: alert = Alert( type="LAF-006", created_at=datetime.datetime.now(), packet_id=packet.id, device_session_id=dev_ses_obj.id, parameters=json.dumps(parameters), data_collector_id=packet.data_collector_id) alert.save() ReportAlert.print_alert(alert) except Exception as exc: logging.error( "Error trying to save Alert LAF-006: {0}". format(exc)) if device_obj is not None: if not device_obj.is_otaa: dev_ses_obj.may_be_abp = True else: logging.warning( "Warning! The device is marked as OTAA but reset counter without having joined. Packet id %d" % (packet.id)) dev_ses_obj.reset_counter += 1 elif packet.f_count <= dev_ses_obj.getCounter(is_uplink_packet): if dev_ses_obj.id in last_uplink_mic: # Make sure we have processed at least one packet for this device in this run before firing the alarm # Skip if received the same counter as previous packet and mics are equal if not (packet.f_count == dev_ses_obj.getCounter(is_uplink_packet) and last_uplink_mic[dev_ses_obj.id] == packet.mic): parameters = {} parameters["dev_addr"] = dev_ses_obj.dev_addr parameters["counter"] = dev_ses_obj.getCounter( is_uplink_packet) parameters["new_counter"] = packet.f_count parameters[ "prev_packet_id"] = dev_ses_obj.last_packet_id parameters['packet_date'] = packet.date.strftime( '%Y-%m-%d %H:%M:%S') if device_obj: parameters['dev_eui'] = device_obj.dev_eui else: parameters['dev_eui'] = 'Unkwown' if gw_obj: parameters["gateway"] = gw_obj.gw_hex_id else: parameters["gateway"] = "Unkwown" try: alert = Alert( type="LAF-007", created_at=datetime.datetime.now(), packet_id=packet.id, device_session_id=dev_ses_obj.id, parameters=json.dumps(parameters), data_collector_id=packet.data_collector_id) alert.save() ReportAlert.print_alert(alert) except Exception as exc: logging.error( "Error trying to save Alert LAF-007: {0}". format(exc)) # Update the counter dev_ses_obj.setCounter(packet.f_count, is_uplink_packet) # Update total packet count dev_ses_obj.incrementPacketCounter(is_uplink_packet) # Keep track of the window time the DevAddr was on dev_ses_obj.updateUptime(packet.date, is_uplink_packet) if is_uplink_packet: # Save uplink MIC last_uplink_mic[dev_ses_obj.id] = packet.mic if device_obj is not None: # Check if this DeviceSession hadn't previously a Device if dev_ses_obj.device_id is not None and device_obj.id != dev_ses_obj.device_id: conflict_device_obj = Device.find_one(dev_ses_obj.device_id) parameters = {} parameters["dev_eui"] = conflict_device_obj.dev_eui, parameters["new_dev_eui"] = device_obj.dev_eui, parameters["dev_addr"] = dev_ses_obj.dev_addr parameters["prev_packet_id"] = dev_ses_obj.last_packet_id parameters['packet_date'] = packet.date.strftime( '%Y-%m-%d %H:%M:%S') if gw_obj: parameters["gateway"] = gw_obj.gw_hex_id else: parameters["gateway"] = "Unkwown" try: alert = Alert(type="LAF-002", created_at=datetime.datetime.now(), packet_id=packet.id, device_id=device_obj.id, device_session_id=dev_ses_obj.id, parameters=json.dumps(parameters), data_collector_id=packet.data_collector_id) alert.save() ReportAlert.print_alert(alert) except Exception as exc: logging.error( "Error trying to save Alert LAF-002: {0}".format(exc)) # device_obj.has_joined = False # Associate Device with DeviceSession dev_ses_obj.device_id = device_obj.id # Set the last packet id received for this device dev_ses_obj.setLastPacketId(is_uplink_packet, packet.id)
def bruteForce(packet): result = "" global device_auth_obj global dontGenerateKeys global keys global hours_betweeen_bruteforce_trials device_auth_obj = None if packet.m_type == "JoinRequest": # Check if Device exists. Otherwise, create it device_obj = Device.find_one_by_dev_eui_and_join_eui_and_datacollector_id( packet.dev_eui, packet.join_eui, packet.data_collector_id) if device_obj is None: try: device_obj = Device( dev_eui=packet.dev_eui, join_eui=packet.join_eui, organization_id=packet.organization_id, ) device_obj.save() except Exception as exc: logging.error("Error trying to save Device: {0}".format(exc)) # Associate Device with the DataCollector try: device_data_collector_obj = DataCollectorToDevice( data_collector_id=packet.data_collector_id, device_id=device_obj.id) device_data_collector_obj.save() except Exception as exc: logging.error( "Error trying to save DataCollectorToDevice: {0}".format( exc)) # Before cracking with many different keys, try with a PotentialAppKey previously found. In case this key is valid, we are pretty sure that is the correct AppKey device_auth_obj = DeviceAuthData.find_one_by_device_id(device_obj.id) if device_auth_obj and extractMIC( device_auth_obj.join_request) != packet.mic: pot_app_keys = PotentialAppKey.find_all_by_device_auth_id( device_auth_obj.id) if len(pot_app_keys) > 0: keys_to_test = list() for pot_app_key in pot_app_keys: keys_to_test.append( bytes(pot_app_key.app_key_hex.rstrip().upper(), encoding='utf-8')) keys_to_test = list(dict.fromkeys(keys_to_test)) correct_app_keys = LorawanWrapper.testAppKeysWithJoinRequest( keys_to_test, packet.data, True).split() if len(correct_app_keys) > 1: logging.warning( "Found more than one possible keys for the device {0}. One of them should be the correct. Check it manually. Keys: {1}" .format(packet.dev_eui, correct_app_keys)) elif len(correct_app_keys) == 1: # AppKey found!! device_auth_obj.second_join_request_packet_id = packet.id device_auth_obj.second_join_request = packet.data device_auth_obj.app_key_hex = correct_app_keys[0] parameters = {} parameters["dev_addr"] = "Unkwown" parameters["dev_eui"] = LorawanWrapper.getDevEUI( device_auth_obj.join_request) parameters["app_key"] = correct_app_keys[0] parameters[ "packet_id_1"] = device_auth_obj.join_request_packet_id parameters["packet_type_1"] = "JoinRequest" parameters["packet_type_2"] = "JoinRequest" parameters['packet_date'] = packet.date.strftime( '%Y-%m-%d %H:%M:%S') # Try to get the gateway from the packet, or retrieve it from DB if possible if packet.gateway: parameters["gateway"] = packet.gateway else: # If we don't receive the gateway in the packet, # get the hex ID of the gateway associated to the device if any. # If we have more than 1 gateway associated to the device, this method returns None gw_obj = Gateway.find_only_one_gateway_by_device_id( device_obj.id) if gw_obj: parameters["gateway"] = gw_obj.gw_hex_id else: parameters["gateway"] = 'Unkwown' try: alert = Alert( type="LAF-009", created_at=datetime.datetime.now(), packet_id=packet.id, device_auth_id=device_auth_obj.id, device_id=device_obj.id, parameters=json.dumps(parameters), data_collector_id=packet.data_collector_id) alert.save() ReportAlert.print_alert(alert) except Exception as exc: logging.error( "Error trying to save Alert LAF-009: {0}".format( exc)) return # Check if the DeviceAuthData wasn't already generated never_bruteforced = False if device_auth_obj is None: never_bruteforced = True try: device_auth_obj = DeviceAuthData( device_id=device_obj.id, data_collector_id=packet.data_collector_id, organization_id=packet.organization_id, join_request=packet.data, created_at=datetime.datetime.now(), join_request_packet_id=packet.id) device_auth_obj.save() except Exception as exc: logging.error( "Error trying to save DeviceAuthData at JoinRequest: {0}". format(exc)) # Check when was the last time it was bruteforced and # Try checking with the keys dictionary and the keys generated on the fly today = datetime.datetime.now() device_auth_obj.created_at = device_auth_obj.created_at.replace( tzinfo=None) elapsed = today - device_auth_obj.created_at # Time in seconds if elapsed.seconds > 3600 * hours_betweeen_bruteforce_trials or never_bruteforced: result = LorawanWrapper.testAppKeysWithJoinRequest( keys, packet.data, dontGenerateKeys) # Update the last time it was broteforced device_auth_obj.created_at = datetime.datetime.now() # If potential keys found... if result != "": device_auth_obj.join_request_packet_id = packet.id device_auth_obj.join_request = packet.data # Split string possibly containing keys separated by spaces candidate_keys_array = result.split() for hex_key in candidate_keys_array: try: potential_key_obj = PotentialAppKey( app_key_hex=hex_key.upper(), organization_id=packet.organization_id, last_seen=packet.date, packet_id=packet.id, device_auth_data_id=device_auth_obj.id) potential_key_obj.save() except Exception as exc: logging.error( "Error trying to save PotentialAppKey at JoinRequest: {0}" .format(exc)) elif packet.m_type == "JoinAccept" and packet.data is not None: last_seconds_date = packet.date - datetime.timedelta(seconds=5) try: organization_keys = PotentialAppKey.find_all_by_organization_id_after_datetime( packet.organization_id, last_seconds_date) # Return if no JR keys were found if len(organization_keys) == 0: return keys_array = list() for pk in organization_keys: # Fetch keys in byte format. Needed by ctypes keys_array.append( bytes(pk.app_key_hex.rstrip().upper(), encoding='utf-8')) # Remove possible duplicates in array keys_array = list(dict.fromkeys(keys_array)) result = LorawanWrapper.testAppKeysWithJoinAccept( keys_array, packet.data, True) except Exception as es: logging.error("Error trying to bforce JA: {0}".format(es)) if result != "": # Clean the key string result = result.rstrip().upper() for potential_key_obj in organization_keys: if potential_key_obj.app_key_hex.upper() == result: device_auth_obj = DeviceAuthData.find_one_by_id( potential_key_obj.device_auth_data_id) break if device_auth_obj is None: logging.error( "Cracked a JoinAccept but no device_auth object found") return # Get DevAddr from JA packet dev_addr = LorawanWrapper.getDevAddr(result, packet.data) # Check if DeviceSession exists. Otherwise, create it dev_ses_obj = DeviceSession.find_one_by_dev_addr_and_datacollector_id( dev_addr, packet.data_collector_id) if dev_ses_obj is None: try: dev_ses_obj = DeviceSession( dev_addr=dev_addr, organization_id=packet.organization_id, ) dev_ses_obj.save() except Exception as exc: logging.error( "Error trying to save DeviceSession: {0}".format(exc)) try: device_session_data_collector_obj = DataCollectorToDeviceSession( data_collector_id=packet.data_collector_id, device_session_id=dev_ses_obj.id) device_session_data_collector_obj.save() except Exception as exc: logging.error( "Error trying to save DataCollectorToDeviceSession: {0}" .format(exc)) #Add missing data device_auth_obj.device_session_id = dev_ses_obj.id device_auth_obj.join_accept = packet.data device_auth_obj.join_accept_packet_id = packet.id device_auth_obj.app_key_hex = result # Add session keys device_auth_obj = deriveSessionKeys(device_auth_obj, result) # Get the device to get dev_eui device_obj = Device.find_one(device_auth_obj.device_id) parameters = {} parameters["dev_addr"] = dev_ses_obj.dev_addr parameters["dev_eui"] = LorawanWrapper.getDevEUI( device_auth_obj.join_request) parameters["app_key"] = result parameters["packet_id_1"] = device_auth_obj.join_request_packet_id parameters["packet_type_1"] = "JoinRequest" parameters["packet_type_2"] = "JoinAccept" parameters['packet_date'] = packet.date.strftime( '%Y-%m-%d %H:%M:%S') if packet.gateway: parameters["gateway"] = packet.gateway else: # If we don't receive the gateway in the packet, # get the hex ID of the gateway associated to the device if any. # If we have more than 1 gateway associated to the device, this method returns None gw_obj = Gateway.find_only_one_gateway_by_device_id( device_obj.id) if gw_obj: parameters["gateway"] = gw_obj.gw_hex_id else: parameters["gateway"] = 'Unkwown' try: alert = Alert(type="LAF-009", created_at=datetime.datetime.now(), packet_id=packet.id, device_session_id=dev_ses_obj.id, device_id=device_obj.id, device_auth_id=device_auth_obj.id, parameters=json.dumps(parameters), data_collector_id=packet.data_collector_id) alert.save() ReportAlert.print_alert(alert) except Exception as exc: logging.error( "Error trying to save Alert LAF-009: {0}".format(exc))
def bruteForce(packet): result = "" global device_auth_obj global dontGenerateKeys global keys device_auth_obj = None if packet.m_type == "JoinRequest": result = LorawanWrapper.testAppKeysWithJoinRequest( keys, packet.data, dontGenerateKeys) if result != "": # Check if Device exists. Otherwise, create it device_obj = Device.find_one_by_dev_eui_and_join_eui_and_datacollector_id( packet.dev_eui, packet.join_eui, packet.data_collector_id) if device_obj is None: try: device_obj = Device( dev_eui=packet.dev_eui, join_eui=packet.join_eui, organization_id=packet.organization_id, ) device_obj.save() except Exception as exc: logging.error( "Error trying to save Device: {0}".format(exc)) # Associate Device with the DataCollector try: device_data_collector_obj = DataCollectorToDevice( data_collector_id=packet.data_collector_id, device_id=device_obj.id) device_data_collector_obj.save() except Exception as exc: logging.error( "Error trying to save DataCollectorToDevice: {0}". format(exc)) # Check if the DeviceAuthData wasn't already generated device_auth_obj = DeviceAuthData.find_one_by_device_id( device_obj.id) if device_auth_obj is None: try: device_auth_obj = DeviceAuthData( device_id=device_obj.id, data_collector_id=packet.data_collector_id, organization_id=packet.organization_id, join_request=packet.data, created_at=datetime.datetime.now(), join_request_packet_id=packet.id) device_auth_obj.save() except Exception as exc: logging.error( "Error trying to save DeviceAuthData at JoinRequest: {0}" .format(exc)) else: device_auth_obj.join_request_packet_id = packet.id device_auth_obj.join_request = packet.data # Split string possibly containing keys separated by spaces candidate_keys_array = result.split() for hex_key in candidate_keys_array: try: potential_key_obj = PotentialAppKey( app_key_hex=hex_key, organization_id=packet.organization_id, last_seen=packet.date, packet_id=packet.id, device_auth_data_id=device_auth_obj.id) potential_key_obj.save() except Exception as exc: logging.error( "Error trying to save PotentialAppKey at JoinRequest: {0}" .format(exc)) elif packet.m_type == "JoinAccept" and packet.data is not None: last_seconds_date = packet.date - datetime.timedelta(seconds=5) try: organization_keys = PotentialAppKey.find_all_by_organization_id_after_datetime( packet.organization_id, last_seconds_date) keys_array = list() for pk in organization_keys: # Fetch keys in byte format. Needed by ctypes keys_array.append( bytes(pk.app_key_hex.rstrip().upper(), encoding='utf-8')) # Remove possible duplicates in array keys_array = list(dict.fromkeys(keys_array)) result = LorawanWrapper.testAppKeysWithJoinAccept( keys_array, packet.data, True) except Exception as es: logging.error("Error trying to bforce JA: {0}".format(es)) if result != "": # Clean the key string result = result.rstrip().upper() for potential_key_obj in organization_keys: if potential_key_obj.app_key_hex == result: device_auth_obj = DeviceAuthData.find_one_by_id( potential_key_obj.device_auth_data_id) break # Get DevAddr from JA packet dev_addr = LorawanWrapper.getDevAddr(result, packet.data) # Check if DeviceSession exists. Otherwise, create it dev_ses_obj = DeviceSession.find_one_by_dev_addr_and_datacollector_id( dev_addr, packet.data_collector_id) if dev_ses_obj is None: try: dev_ses_obj = DeviceSession( dev_addr=dev_addr, organization_id=packet.organization_id, ) dev_ses_obj.save() except Exception as exc: logging.error( "Error trying to save DeviceSession: {0}".format(exc)) try: device_session_data_collector_obj = DataCollectorToDeviceSession( data_collector_id=packet.data_collector_id, device_session_id=dev_ses_obj.id) device_session_data_collector_obj.save() except Exception as exc: logging.error( "Error trying to save DataCollectorToDeviceSession: {0}" .format(exc)) #Add missing data device_auth_obj.device_session_id = dev_ses_obj.id device_auth_obj.join_accept = packet.data device_auth_obj.join_accept_packet_id = packet.id device_auth_obj.app_key_hex = result # Add session keys device_auth_obj = deriveSessionKeys(device_auth_obj, result) # Get the device to get dev_eui device_obj = Device.find_one(device_auth_obj.device_id) parameters = {} parameters["dev_addr"] = dev_ses_obj.dev_addr parameters["dev_eui"] = LorawanWrapper.getDevEUI( device_auth_obj.join_request) parameters["app_key"] = result parameters[ "join_request_packet_id"] = device_auth_obj.join_request_packet_id try: alert = Alert(type="LAF-009", created_at=datetime.datetime.now(), packet_id=packet.id, device_session_id=dev_ses_obj.id, device_auth_id=device_auth_obj.id, parameters=json.dumps(parameters), data_collector_id=packet.data_collector_id) alert.save() except Exception as exc: logging.error( "Error trying to save Alert LAF-009: {0}".format(exc)) ReportAlert.print_alert(alert)