def _inspect_open_ports(self, ip, mac, results, port_type, ports_allow, ports_severe_alert): """ This method inspects the open ports for the given port_type and Alerts if any suspicious open ports are found. A severe Alert is generated if any ports in ports_info_severe_alert are found. :param ip: The IP being scanned :param mac: The MAC corresponding to the IP :param results: The ports nmap scan results :param port_type: The port type to inspect, either "tcp" or "udp" :param ports_allow: The list of allowed ports for this port type :param ports_severe_alert: Generates a severe Alert if any of these ports are found open :return: Whether the packet came from a spoofed MAC Address """ if port_type in results[ip]: for port in results[ip][port_type]: if port not in ports_allow: alert_obj = Alert( None, f'Suspicious open {port_type.upper()} port found: {str(port)}. ' f'Further investigation recommended.', AlertType.PRIVACY, Severity.INFO) alert_obj.device_mac = mac alert_obj.device_ip = ip alert_obj.alert() if port in ports_severe_alert: alert_obj = Alert( None, f'Very suspicious open {port_type.upper()} port found: {str(port)}. ' f'Further investigation required.', AlertType.PRIVACY, Severity.ALERT) alert_obj.device_mac = mac alert_obj.device_ip = ip alert_obj.alert()
def packet_parse(packet: Packet): """ Runs privacy analysis rules and checks packet against IDS signatures :param packet: packet to analyze :return: nothing """ for rule in rules_packet_privacy: try: rule(packet) except Exception as e: run_config.log_event.info( 'Exception raised in a privacy rule check: ' + str(e)) # For each triggered signature generate an alert for the user try: triggered_rules = signature_detector.check_signatures(packet) if len(triggered_rules) > 0: for triggered_rule in triggered_rules: is_dst = packet[ Ether].src in DeviceInformation.get_mac_addresses() alert_object = Alert(packet, triggered_rule.msg, AlertType.IDS, Severity.ALERT, is_dst) alert_object.alert() except Exception as e: run_config.log_event.info('Exception raised in an IDS rule check: ' + str(e)) # For each packet, pass through frequency detection engine try: anomaly_engine.check_signatures(packet) except Exception as e: run_config.log_event.info( 'Exception raised in an Anomaly Engine check: ' + str(e))
def __call__(self, packet: Packet): is_TCP = packet.haslayer(TCP) is_UDP = packet.haslayer(UDP) # Perform TCP and UDP checks if is_TCP or is_UDP: proto_type = TCP if is_TCP else UDP # Scan for using port 80 and the plaintext for privacy leaks if (packet[proto_type].dport == 80) or (packet[proto_type].sport == 80): alert_port_80 = Alert(None, "Sending data over unencrypted port.", ALERT_TYPE.PRIVACY, SEVERITY.ALERT) alert_port_80.alert() self.__scan_plaintext(packet, proto_type) # Monitor suspicious ports print("Monitoring suspicious ports") if packet[proto_type].dport in suspicious_ports: alert_suspicious_ports = Alert( None, "Suspicious destination port used: " + packet[proto_type].dport, ALERT_TYPE.PRIVACY, SEVERITY.WARN) alert_suspicious_ports.alert() print("Alert on bad port")
def __call__(self): # Get the data from the file with the password hashes data = get_file_contents("/etc/shadow") # Alert if there is no password hash for the root user if (data is not None) and ("root::" in data): alert_obj = Alert( None, "No password is set for the root user, which should be done immediately.", AlertType.PRIVACY, Severity.ALERT) alert_obj.alert()
def __regex_alert(self, regex_string, alert_string, vuln_target): """ Scan the payload with the given regex string and alert if necessary :param regex_string: The regex string to scan the paylaod with :param alert_string: The string to pass into the Alert object as the description for the event :param vuln_target: Either "src" or "dst", depending on where the plaintext vulnerability originiated from """ if re.search(regex_string, self.payload): alert_regex = Alert(None, alert_string, AlertType.PRIVACY, Severity.ALERT) alert_regex.device_mac = self.packet[Ether][vuln_target] alert_regex.device_ip = self.packet[IP][vuln_target] alert_regex.alert()
def __call__(self): weak_encryption_modes = [ "none'", "wep", "owe'", "psk'", "psk+", "psk-", "wpa'", "wpa+", "wpa-" ] data = get_file_contents("/etc/config/wireless") if data is None: return for mode in weak_encryption_modes: if ("encryption '" + mode) in data: alert_obj = Alert( None, "Weak encryption is in use. Switch to WPA2 from " + mode + ".", ALERT_TYPE.PRIVACY, SEVERITY.ALERT) alert_obj.alert()
def __call__(self): data = get_file_contents("/etc/config/dropbear") if (data is not None) and ("RootPasswordAuth 'on'" in data): alert_root_login = Alert( None, "Root user can login via ssh. Consider disabling this for security purposes.", ALERT_TYPE.PRIVACY, SEVERITY.INFO) alert_root_login.alert() if "PasswordAuth 'on'" in data: alert_general_login = Alert( None, "Password login via ssh is allowed. Consider only allowing keypair login via ssh.", ALERT_TYPE.PRIVACY, SEVERITY.INFO) alert_general_login.alert()
def __call__(self): # Get the data from the file with the dropbear configuration data = get_file_contents("/etc/config/dropbear") # Alert if root login is allowed if (data is not None) and ("option RootPasswordAuth 'on'" in data): alert_root_login = Alert(None, "Root user can login via ssh. Consider disabling this for security purposes.", AlertType.PRIVACY, Severity.INFO) alert_root_login.alert() # Alert if password login is allowed if (data is not None) and ("option PasswordAuth 'on'" in data): alert_general_login = Alert(None, "Password login via ssh is allowed. Consider only allowing keypair login via " "ssh.", AlertType.PRIVACY, Severity.INFO) alert_general_login.alert()
def __scan_plaintext(self, proto_type, vuln_target): """ Scan plaintext for privacy leaks and alert on findings: credit cards, social security numbers, emails, and suspicious keywords. Note that there is a chance for false positives with credit cards and SSNs, because they're just numbers :param proto_type: Either TCP or UDP :param vuln_target: Either "src" or "dst", depending on where the plaintext vulnerability originiated from """ # Try to get the payload try: self.payload = str(self.packet[proto_type].payload) except Exception as e: run_config.log_event.info('Exception raised: ' + str(e)) return # Use a regex to look for credit cards, needs a non-number before and after the numbers self.__regex_alert( "[\D](?:[0-9]{4}-){3}[0-9]{4}[\D]|[\D][0-9]{16}[\D]", "Credit card information found in a " "plaintext packet.", vuln_target) # Use a regex to look for SSNs, needs a non-number before and after the numbers self.__regex_alert( "[\D][0-9]{9}[\D]|[\D][0-9]{3}-[0-9]{2}-[0-9]{4}[\D]", "SSN information found in a " "plaintext packet.", vuln_target) # Use a regex to look for emails - this is not a huge privacy leak, but still mentionable # The email will not be included in the alert for privacy reasons self.__regex_alert("[^@]+@[^@]+\.[^@]+", "Email information found in a plaintext packet.", vuln_target) # Search for specific words to alert on for keyword in suspicious_strings: if keyword in self.payload: alert_keyword = Alert( None, f'Suspicious keyword found in a plaintext packet: {keyword}', AlertType.PRIVACY, Severity.ALERT) alert_keyword.device_mac = self.packet[Ether][vuln_target] alert_keyword.device_ip = self.packet[IP][vuln_target] alert_keyword.alert()
def __call__(self): # Define the weak encryption modes to alert on weak_encryption_modes = [ "none'", "wep", "owe'", "psk'", "psk+", "psk-", "wpa'", "wpa+", "wpa-" ] # Get the data from the file with the encryption information data = get_file_contents("/etc/config/wireless") if data is None: return # Check if any weak encryption modes are used on router for mode in weak_encryption_modes: if ("encryption '" + mode) in data: alert_obj = Alert( None, f"Weak encryption is in use. Switch to WPA2 from {mode}.", AlertType.PRIVACY, Severity.ALERT) alert_obj.alert()
def packet_parse(packet: Packet): """ Runs privacy analysis rules and checks packet against IDS signatures :param packet: packet to analyze :return: nothing """ for rule in rules_packet_privacy: try: rule(packet) except Exception as e: # TODO: refine so a specific error message can be logged run_config.log_event.info('Exception raised: ' + str(e)) # For each triggered signature generate an alert for the user try: triggered_rules = signature_detector.check_signatures(packet) if len(triggered_rules) > 0: for triggered_rule in triggered_rules: is_dst = packet[Ether].src in mac_addrs alert_object = Alert(packet, triggered_rule.msg, ALERT_TYPE.IDS, SEVERITY.ALERT, is_dst) alert_object.alert() except Exception as e: # TODO: refine so a specific error message can be logged run_config.log_event.info('Exception raised: ' + str(e))
def __call__(self, packet_input: Packet): """ Handles the privacy detection process and alerting :param packet_input: The current packet to analyze """ self.packet = packet_input is_TCP = self.packet.haslayer(TCP) is_UDP = self.packet.haslayer(UDP) # Perform TCP and UDP checks if is_TCP or is_UDP: proto_type = TCP if is_TCP else UDP # Scan for using port 80 and the plaintext for privacy leaks if (self.packet[proto_type].dport == 80) or (self.packet[proto_type].sport == 80): alert_port_80 = Alert(None, "Sending data over unencrypted port.", AlertType.PRIVACY, Severity.ALERT) if self.packet[proto_type].dport == 80: vuln_target = "dst" else: vuln_target = "src" alert_port_80.device_mac = self.packet[Ether][vuln_target] alert_port_80.device_ip = self.packet[IP][vuln_target] alert_port_80.alert() self.__scan_plaintext(proto_type, vuln_target) # Monitor suspicious ports if self.packet[proto_type].dport in suspicious_ports: alert_suspicious_ports = Alert( None, "Suspicious destination port used: " + str(self.packet[proto_type].dport), AlertType.PRIVACY, Severity.WARN) alert_suspicious_ports.device_mac = self.packet[Ether].dst alert_suspicious_ports.device_ip = self.packet[IP].dst alert_suspicious_ports.alert()
def __call__(self): data = get_file_contents("/etc/shadow") if (data is not None) and ("root::" in data): alert_obj = Alert(None, "No root password set. Set a root password.", ALERT_TYPE.PRIVACY, SEVERITY.ALERT) alert_obj.alert()
def __call__(self): upgradable = os.popen("opkg list-upgradable").read() if upgradable != "": alert_obj = Alert(None, "Packages are available for an update.", ALERT_TYPE.PRIVACY, SEVERITY.INFO) alert_obj.alert()