class PingOfDeath(object): """PingOfDeath class.""" def __init__(self, debug=False): """ Initialize PingOfDeath. Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = logger.SecureTeaLogger(__name__, debug=debug) # Initialize threshold self._THRESHOLD = 60000 # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def detect(self, pkt): """ Detect ping of death attack by calculating load threshold. Args: pkt (scapy_object): Packet to dissect and observe Raises: None Returns: None """ if (pkt.haslayer(scapy.IP) and pkt.haslayer(scapy.ICMP)): # If packet has load if pkt.haslayer(scapy.Raw): load_len = len(pkt[scapy.Raw].load) if (load_len >= self._THRESHOLD): source_ip = pkt[scapy.IP].src msg = "Possible ping of death attack detected " \ "from: {}".format(source_ip) self.logger.log(msg, logtype="warning") # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(source_ip.strip(" ")) # Write malicious IP to file write_mal_ip(str(source_ip).strip(" "))
class SSHLogin(object): """SSHLogin Class.""" def __init__(self, debug=False): """ Initialize SSHLogin. Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = logger.SecureTeaLogger( __name__, debug=debug ) # OS name to SSH-log path map self.system_log_map = { "debian": "/var/log/auth.log" } os_name = utils.categorize_os() self.log_file = None if os_name: try: self.log_file = self.system_log_map[os_name] except KeyError: self.logger.log( "Could not find path for the SSH-log file", logtype="error" ) return else: return # Salt to generate hashed username self.SALT = "<!@?>" # Regex to extract invalid SSH login details self.INVALID_USER = r'^([a-zA-Z]+\s[0-9]+)\s([0-9]+:[0-9]+:[0-9]+).*' \ r'Invalid\suser\s([a-zA-Z0-9_-]+)\sfrom\s([0-9]+\.' \ r'[0-9]+\.[0-9]+\.[0-9]+)' # Initialize username to IP dict self.username_dict = dict() # Set threshold to 5 attempts per second to detect brute-force self.THRESHOLD = 5 # inter = 0.2 # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def parse_log_file(self): """ Parse log file to extract invalid SSH user / their authentication failure / login attempts. Args: None Raises: None Returns: None """ # Open the log file log_file_data = utils.open_file(self.log_file) for line in log_file_data: found = re.findall(self.INVALID_USER, line) if (found is not None and found != []): date = found[0][0] month = date.split(" ")[0] day = date.split(" ")[1] last_time = found[0][1] username = found[0][2] ip = found[0][3] # convert date, time to epoch time epoch_time = utils.get_epoch_time(month, day, last_time) self.update_username_dict(username, ip, date, epoch_time) def update_username_dict(self, username, ip, date, epoch_time): """ Update username to IP dict with the new set of IP & failure attempts on a given day for a particular user. Args: username (str): Name of the account being tried to access ip (str): IP address of the source date (str): Date of action (eg. Jun 1) epoch_time (int): Time during the attempt in epoch format Raises: None Returns: None """ # Generate a hashed username using salt hashed_username = username + self.SALT + date if self.username_dict.get(hashed_username) is None: # if user not in dict, add to dict self.username_dict[hashed_username] = { "ip": [ip], "last_time": epoch_time, "count": 1 } else: # if user in dict, update user IP address & count if ip not in self.username_dict[hashed_username]["ip"]: self.username_dict[hashed_username]["ip"].append(ip) prev_count = self.username_dict[hashed_username]["count"] new_count = prev_count + 1 self.username_dict[hashed_username]["count"] = new_count def check_ssh_bruteforce(self): """ Check for SSH brute-force by comparing the calculated ratio with the set threshold. Args: None Raises: None Returns: None """ for user in self.username_dict.keys(): no_of_ip = len(self.username_dict[user]["ip"]) count = self.username_dict[user]["count"] last_time = self.username_dict[user]["last_time"] current_time = time.time() try: delta_time = int(current_time - last_time) calc_threshold_ip = no_of_ip / delta_time calc_threshold_count = count / delta_time except ZeroDivisionError: calc_threshold_ip = int(no_of_ip) calc_threshold_count = int(count) if (calc_threshold_ip > self.THRESHOLD or calc_threshold_count > self.THRESHOLD): if no_of_ip == 1: # if a single IP in user list msg = "Possible SSH brute force detected for the user: "******" from: " + \ self.username_dict[user]["ip"][0] + " on: " + \ user.split(self.SALT)[1] self.logger.log( msg, logtype="warning" ) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(self.username_dict[user]["ip"][0].strip(" ")) else: for ip in self.username_dict[user]["ip"]: msg = "Possible SSH brute force detected for the user: "******" from: " + ip + " on: " + \ user.split(self.SALT)[1] self.logger.log( msg, logtype="warning" ) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(ip.strip(" ")) def run(self): """ Start monitoring the SSH log file for login attempts & possible password brute-force. Args: None Raises: None Returns: None """ if self.log_file: # if path of SSH-log file is valid # Rotate & parse the log file self.parse_log_file() # Analyze the log for brute-force self.check_ssh_bruteforce() # Empty the dict to rotate the log-file self.username_dict.clear()
class WebShell(object): """WebShell Class.""" def __init__(self, debug=False, test=False): """ Initialize WebShell. Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = ServerLogger(__name__, debug=debug) if test: # Path of file containing web_shell payloads self.PAYLOAD_FILE = "securetea/lib/log_monitor/server_log/rules/payloads/web_shell.txt" else: # Path of file containing web_shell payloads self.PAYLOAD_FILE = "/etc/securetea/log_monitor/server_log/payloads/web_shell.txt" # Load web_shell payloads self.payloads = utils.open_file(self.PAYLOAD_FILE) # Logged IP list self.logged_IP = list() # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def detect_web_shell(self, data): """ Detect possible Web Shell attacks. Use string comparison to scan GET request with the list of possible web shell payloads. Args: data (dict): Parsed log file data Raises: None Returns: None """ for ip in data.keys(): get_req = data[ip]["get"] if (self.payload_match(get_req)): if ip not in self.logged_IP: # if not logged earlier self.logged_IP.append(ip) last_time = data[ip]["ep_time"][0] msg = "Possible web shell detected from: " + str(ip) + \ " on: " + str(utils.epoch_to_date(last_time)) self.logger.log(msg, logtype="warning") utils.write_ip(str(ip)) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(ip.strip(" ")) # Write malicious IP to file, to teach Firewall about the IP write_mal_ip(ip.strip(" ")) def payload_match(self, get_req): """ Match parsed GET request for a possible web shell payload. Args: get_req (str): GET request on which to perform payload string matching Raises: None Returns: TYPE: bool """ for req in get_req: for payload in self.payloads: payload = payload.strip(" ").strip("\n") if (payload in req or utils.uri_encode(payload) in req): return True
class DDoS(object): """DDoS Class.""" def __init__(self, debug=False): """ Initialize DDoS. Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = ServerLogger(__name__, debug=debug) # Initialize threshold to 1000 packets per second self._SISP_THRESHOLD = 1000 # inter = 0.001 self._SIMP_THRESHOLD = 100 # 100 different IPs that trigger SISP DoS # List of IPs self.SISP_LIST = list() # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def detect_ddos(self, data): """ Detect DoS attack. Classify DoS attack into two categories: - Single IP Single Port DoS Attack - Single IP Multiple Port DoS Attack Look for IP addresses having high number of GET request and a small time difference to predict SISP DoS attack. High number of alarms triggered for SISP DoS attack indicates MISP DoS attack. Args: data (dict): Parsed log file data Raises: None Returns: None """ for ip in data.keys(): count = data[ip]["count"] last_time = data[ip]["ep_time"][0] initial_time = data[ip]["ep_time"][int( len(data[ip]["ep_time"]) - 1)] delta = abs(int(last_time - initial_time)) try: calc_count_thresh = int(count / delta) except ZeroDivisionError: calc_count_thresh = int(count) if calc_count_thresh > self._SISP_THRESHOLD: # if crosses threshold, trigger alarm msg = "Possible Single IP DoS Attack Detected from: " + \ str(ip) + " on: " + utils.epoch_to_date(last_time) self.logger.log(msg, logtype="warning") if ip not in self.SISP_LIST: self.SISP_LIST.append(ip) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(ip.strip(" ")) # Write malicious IP to file, to teach Firewall about the IP write_mal_ip(ip.strip(" ")) if len(self.SISP_LIST ) > self._SIMP_THRESHOLD: # if no. of SISP is huge for ip in self.SISP_LIST: self.logger.log( "Possible Multiple IP DoS Attack Detected from: " + str(ip), logtype="warning")
class PortScan(object): """PortScan Class.""" def __init__(self, debug=False, test=False): """ Initialize PortScan. Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = ServerLogger(__name__, debug=debug) if test: # Path of file containing port_scan payloads self.PAYLOAD_FILE = "securetea/lib/log_monitor/server_log/rules/payloads/port_scan_ua.txt" else: # Path of file containing port_scan payloads self.PAYLOAD_FILE = "/etc/securetea/log_monitor/server_log/payloads/port_scan_ua.txt" # Load port_scan payloads self.payloads = utils.open_file(self.PAYLOAD_FILE) # List of IPs self.logged_IP = list() # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def detect_port_scan(self, data): """ Detect possible Port Scan recon attacks. Look for a possible port scan user agent payload in the user agent field. Args: data (dict): Parsed log file data Raises: None Returns: None """ for ip in data.keys(): user_agent = data[ip]["ua"] if (self.payload_match(user_agent)): if ip not in self.logged_IP: self.logged_IP.append(ip) last_time = data[ip]["ep_time"][0] msg = "Possible port scan detected from: " + str(ip) + \ " on: " + utils.epoch_to_date(last_time) self.logger.log(msg, logtype="warning") utils.write_ip(str(ip)) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(ip.strip(" ")) # Write malicious IP to file, to teach Firewall about the IP write_mal_ip(ip.strip(" ")) def payload_match(self, user_agent): """ Match parsed user agent for a possible port scan user agent payload. Args: user_agent (str): User agent on which to perform payload string matching Raises: None Returns: TYPE: bool """ for agent in user_agent: for payload in self.payloads: payload = payload.strip(" ").strip("\n") if payload in agent: return True
class DetectRecon(object): """Class for DetectRecon.""" def __init__(self, threshold=None, debug=False): """Initialize DetectRecon class. Args: threshold (integer): Threshold ratio limit debug (bool): Log on terminal or not Raises: None Returns: None Working: Detect the following possible probe (reconnaissance) attacks (performed for information gathering): - TCP ACK / Window Scan - UDP Scan - ICMP Scan - FIN Scan - NULL Scan - XMAS Scan - OS fingerprinting Scan """ # Initialize logger self.logger = logger.SecureTeaLogger(__name__, debug) # Set threshold if not threshold: self._THRESHOLD = 100 else: try: self._THRESHOLD = int(threshold) except ValueError: self.logger.log("Incorrent threshold, need an integer value.", logtype="error") sys.exit(0) # Set count threshold self._COUNT = self._THRESHOLD * 1000 # Initialize empty dicts to store IPs self.tcp_ack = dict() self.icmp_scan = dict() self.udp_scan = dict() self.fin_scan = dict() self.xmas_scan = dict() self.null_scan = dict() self.os_scan = dict() # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def detect_tcp_ack(self, packet=None): """ Detect possible TCP ACK / Window scan. Args: packet (scapy_object): Packet to dissect and observe Raises: None Returns: None """ if packet is not None: if packet.haslayer(scapy.TCP): flag = str(packet[scapy.TCP].flags) if (flag == "A"): packet_ip = None try: packet_ip = str(packet[scapy.IP].src) except Exception as e: # If IP layer is missing self.logger.log("Error occurred: " + str(e), logtype="error") if packet_ip: try: # Check if the IP exists in the dict or not count = self.tcp_ack[packet_ip]["count"] new_port = int(packet[scapy.TCP].dport) if (new_port not in self.tcp_ack[packet_ip]["ports"]): self.tcp_ack[packet_ip]["ports"].append( new_port) self.tcp_ack[packet_ip]["count"] = count + 1 except KeyError: # Packet from a new IP address self.tcp_ack[packet_ip] = { "start_time": time.time(), "count": 1, "ports": [int(packet[scapy.TCP].dport)] } except Exception as e: self.logger.log("Error occurred: " + str(e), logtype="error") # Check if there has been an intrusion attack self.calc_intrusion(scan_dict=self.tcp_ack, msg="TCP ACK / Window Scan detected") def detect_udp(self, packet=None): """ Detect possible UDP scan. Args: packet (scapy_object): Packet to dissect and observe Raises: None Returns: None """ if packet is not None: if packet.haslayer(scapy.UDP): packet_ip = None try: packet_ip = str(packet[scapy.IP].src) except Exception as e: # If IP layer is missing self.logger.log("Error occurred: " + str(e), logtype="error") if packet_ip: try: # Check if the IP exists in the dict or not count = self.udp_scan[packet_ip]["count"] new_port = int(packet[scapy.UDP].dport) if (new_port not in self.udp_scan[packet_ip]["ports"]): self.udp_scan[packet_ip]["ports"].append(new_port) self.udp_scan[packet_ip]["count"] = count + 1 except KeyError: # Packet from a new IP address self.udp_scan[packet_ip] = { "start_time": time.time(), "count": 1, "ports": [int(packet[scapy.UDP].dport)] } except Exception as e: self.logger.log("Error occurred: " + str(e), logtype="error") # Check if there has been an intrusion attack self.calc_intrusion(scan_dict=self.udp_scan, msg="UDP Scan detected") def detect_icmp(self, packet=None): """ Detect possible ICMP scan. Args: packet (scapy_object): Packet to dissect and observe Raises: None Returns: None """ if packet is not None: if (packet.haslayer(scapy.ICMP) and packet.haslayer(scapy.Ether)): dst = str(packet[scapy.Ether].dst) if (dst == "ff:ff:ff:ff:ff:ff" and (int(packet[scapy.ICMP].type) == 8)): packet_ip = None try: packet_ip = str(packet[scapy.IP].src) except Exception as e: # If IP layer is missing self.logger.log("Error occurred: " + str(e), logtype="error") if packet_ip: try: # Check if the IP exists in the dict ot not count = self.icmp_scan[packet_ip]["count"] sellf.icmp_scan[packet_ip]["count"] = count + 1 except KeyError: # Packet from a new IP address self.icmp_scan[packet_ip] = { "start_time": time.time(), "count": 1 } except Exception as e: self.logger.log("Error occurred: " + str(e), logtype="error") # Check if there has been an intrusion attack for key in self.icmp_scan.keys(): current_time = time.time() start_time = self.icmp_scan[key]["start_time"] delta_time = int(current_time - start_time) count = int(self.icmp_scan[key]["count"]) try: calc_threshold = int(count / delta_time) except ZeroDivisionError: calc_threshold = int(count) if (calc_threshold > self._THRESHOLD): self.logger.log("ICMP Scan detected from: " + str(key), logtype="warning") def detect_os_scan(self, packet): """ Detect possible OS fingerprinting scan. Args: packet (scapy_object): Packet to dissect and observe Raises: None Returns: None """ if packet is not None: if packet.haslayer(scapy.TCP): flag = str(packet[scapy.TCP].flags) if ("SF" in flag or "FS" in flag): packet_ip = None try: packet_ip = str(packet[scapy.IP].src) except Exception as e: # If IP layer is missing self.logger.log("Error occurred: " + str(e), logtype="error") if packet_ip: try: # Check if the IP exists in the dict or not count = self.os_scan[packet_ip]["count"] new_port = int(packet[scapy.TCP].dport) if (new_port not in self.os_scan[packet_ip]["ports"]): self.os_scan[packet_ip]["ports"].append( new_port) self.os_scan[packet_ip]["count"] = count + 1 except KeyError: # Packet from a new IP address self.os_scan[packet_ip] = { "start_time": time.time(), "count": 1, "ports": [int(packet[scapy.TCP].dport)] } except Exception as e: self.logger.log("Error occurred: " + str(e), logtype="error") # Check if there has been an intrusion attack self.calc_intrusion(scan_dict=self.os_scan, msg="OS Fingerprinting Scan detected") def detect_fin_scan(self, packet): """ Detect possible FIN scan. Args: packet (scapy_object): Packet to dissect and observe Raises: None Returns: None """ if packet is not None: if packet.haslayer(scapy.TCP): flag = str(packet[scapy.TCP].flags) if (flag == "F"): packet_ip = None try: packet_ip = str(packet[scapy.IP].src) except Exception as e: # If IP layer is missing self.logger.log("Error occurred: " + str(e), logtype="error") if packet_ip: try: # Check if the IP exists in the dict or not count = self.fin_scan[packet_ip]["count"] new_port = int(packet[scapy.TCP].dport) if (new_port not in self.fin_scan[packet_ip]["ports"]): self.fin_scan[packet_ip]["ports"].append( new_port) self.fin_scan[packet_ip]["count"] = count + 1 except KeyError: # Packet from a new IP address self.fin_scan[packet_ip] = { "start_time": time.time(), "count": 1, "ports": [int(packet[scapy.TCP].dport)] } except Exception as e: self.logger.log("Error occurred: " + str(e), logtype="error") # Check if there has been an intrusion attack self.calc_intrusion(scan_dict=self.fin_scan, msg="FIN Scan detected") def detect_xmas_scan(self, packet=None): """ Detect possible XMAS scan. Args: packet (scapy_object): Packet to dissect and observe Raises: None Returns: None """ if packet is not None: if packet.haslayer(scapy.TCP): flag = str(packet[scapy.TCP].flags) if (flag == "FPU"): packet_ip = None try: packet_ip = str(packet[scapy.IP].src) except Exception as e: # If IP layer is missing self.logger.log("Error occurred: " + str(e), logtype="error") if packet_ip: try: # Check if the IP exists in the dict or not count = self.xmas_scan[packet_ip]["count"] new_port = int(packet[scapy.TCP].dport) if (new_port not in self.xmas_scan[packet_ip]["ports"]): self.xmas_scan[packet_ip]["ports"].append( new_port) self.xmas_scan[packet_ip]["count"] = count + 1 except KeyError: # Packet from a new IP address self.xmas_scan[packet_ip] = { "start_time": time.time(), "count": 1, "ports": [int(packet[scapy.TCP].dport)] } except Exception as e: self.logger.log("Error occurred: " + str(e), logtype="error") # Check if there has been an intrusion attack self.calc_intrusion(scan_dict=self.xmas_scan, msg="XMAS Scan detected") def detect_null_scan(self, packet): """ Detect possible NULL scan. Args: packet (scapy_object): Packet to dissect and observe Raises: None Returns: None """ if packet is not None: if packet.haslayer(scapy.TCP): flag = packet[scapy.TCP].flags if flag is None: packet_ip = None try: packet_ip = str(packet[scapy.IP].src) except Exception as e: # If IP layer is missing self.logger.log("Error occurred: " + str(e), logtype="error") if packet_ip: try: # Check if the IP exists in the dict or not count = self.null_scan[packet_ip]["count"] new_port = int(packet[scapy.TCP].dport) if (new_port not in self.null_scan[packet_ip]["ports"]): self.null_scan[packet_ip]["ports"].append( new_port) self.null_scan[packet_ip]["count"] = count + 1 except KeyError: # Packet from a new IP address self.null_scan[packet_ip] = { "start_time": time.time(), "count": 1, "ports": [int(packet[scapy.TCP].dport)] } except Exception as e: self.logger.log("Error occurred: " + str(e), logtype="error") # Check if there has been an intrusion attack self.calc_intrusion(scan_dict=self.null_scan, msg="NULL Scan detected") def calc_intrusion(self, scan_dict, msg): """ Detect intrusion by comparing observed and expected threshold ratio. Args: scan_dict (dict): IP dictionary msg (str): Message to display when intrusion is detected Raises: None Returns: None """ for key in scan_dict.keys(): current_time = time.time() start_time = scan_dict[key]["start_time"] port_len = len(scan_dict[key]["ports"]) count = scan_dict[key]["count"] delta_time = int(current_time - start_time) try: calc_threshold = int(port_len / delta_time) except ZeroDivisionError: calc_threshold = int(port_len) if (calc_threshold >= self._THRESHOLD or count >= self._COUNT): # Intrusion detected new_msg = msg + " from IP: " + str(key) self.logger.log(new_msg, logtype="warning") # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(str(key).strip(" ")) # Write malicious IP to file write_mal_ip(str(key).strip(" ")) def run(self, packet): """ Start to detect reconnaissance attacks. Args: packet (scapy_object): Packet to dissect and observe Raises: None Returns: None """ # Detect general scans self.detect_tcp_ack(packet) self.detect_udp(packet) self.detect_icmp(packet) # Detect stealth scans self.detect_fin_scan(packet) self.detect_xmas_scan(packet) self.detect_null_scan(packet) # Detect OS fingerprinting scans self.detect_os_scan(packet)
class PacketFilter(object): """Class for PacketFilter.""" def __init__(self, interface=None, debug=False, ip_inbound=None, ip_outbound=None, protocols=None, dns=None, dports=None, sports=None, extensions=None, action_inbound_IPRule=0, action_outbound_IPRule=0, action_DNSRule=0, action_source_portRule=0, action_dest_portRule=0, action_HTTPResponse=1, action_HTTPRequest=1, action_protocolRule=0, action_scanLoad=0, test=False): """Initilize PacketFilter class.""" self.logger = logger.SecureTeaLogger(__name__, debug) # Initialize with empty list if ip_inbound is None: ip_inbound = [] if ip_outbound is None: ip_outbound = [] if protocols is None: protocols = [] if dns is None: dns = [] if sports is None: sports = [] if dports is None: dports = [] if extensions is None: extensions = [] self._action_inbound_IPRule = action_inbound_IPRule self._action_outbound_IPRule = action_outbound_IPRule self._action_protocolRule = action_protocolRule self._action_DNSRule = action_DNSRule self._action_source_portRule = action_source_portRule self._action_dest_portRule = action_dest_portRule self._action_HTTPRequest = action_HTTPRequest self._action_HTTPResponse = action_HTTPResponse self._action_scanLoad = action_scanLoad self._IP_INBOUND = ip_inbound self._IP_OUTBOUND = ip_outbound self._PROTCOLS = protocols self._DNS = dns self._DPORTS = dports self._SPORTS = sports self._EXTENSIONS = extensions if not test: # Avoid generating PCAP file during test run # Initialize PcapWriter for PCAP dumping self.pktdump = PcapWriter("blocked.pcap", append=True, sync=True) # Initialize OSINT object self.osint_obj = OSINT(debug=debug) # Malicious IP file path self._MAL_IP_PATH = "/etc/securetea/mal_ip.txt" @utils.xnor def inbound_IPRule(self, scapy_pkt): """ Filter packet based on the specified inbound IP rules. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: dict: 'action': User specified action 'result': Rule matched or not """ if scapy_pkt.haslayer(scapy.IP): if (str(scapy_pkt[scapy.IP].src) in self._IP_INBOUND): return {'action': self._action_inbound_IPRule, 'result': 1} else: return {'action': self._action_inbound_IPRule, 'result': 0} else: return {'action': self._action_inbound_IPRule, 'result': 0} @utils.xnor def outbound_IPRule(self, scapy_pkt): """ Filter packet based on the specified outbound IP rules. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: dict: 'action': User specified action 'result': Rule matched or not """ if scapy_pkt.haslayer(scapy.IP): if (str(scapy_pkt[scapy.IP].dst) in self._IP_OUTBOUND): return {'action': self._action_outbound_IPRule, 'result': 1} else: return {'action': self._action_outbound_IPRule, 'result': 0} else: return {'action': self._action_outbound_IPRule, 'result': 0} @utils.xnor def protocolRule(self, scapy_pkt): """ Filter packet based on the specified protocols. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: dict: 'action': User specified action 'result': Rule matched or not """ if scapy_pkt.haslayer(scapy.IP): if (str(scapy_pkt[scapy.IP].proto) in self._PROTCOLS): return {'action': self._action_protocolRule, 'result': 1} else: return {'action': self._action_protocolRule, 'result': 0} else: return {'action': self._action_protocolRule, 'result': 0} @utils.xnor def DNSRule(self, scapy_pkt): """ Filter packet based on the specified DNS rules. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: dict: 'action': User specified action 'result': Rule matched or not """ if scapy_pkt.haslayer(scapy.DNSRR): qname = scapy_pkt[scapy.DNSQR].qname.decode('utf-8') if len(self._DNS): for dns in self._DNS: if dns in str(qname.strip()): return {'action': self._action_DNSRule, 'result': 1} else: return {'action': self._action_DNSRule, 'result': 0} else: return {'action': self._action_DNSRule, 'result': 0} else: return {'action': self._action_DNSRule, 'result': 0} @utils.xnor def source_portRule(self, scapy_pkt): """ Filter packet based on the specified source port rules. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: dict: 'action': User specified action 'result': Rule matched or not """ if scapy_pkt.haslayer(scapy.Raw): if str(scapy_pkt[scapy.TCP].sport) in self._SPORTS: return {'action': self._action_source_portRule, 'result': 1} else: return {'action': self._action_source_portRule, 'result': 0} else: return {'action': self._action_source_portRule, 'result': 0} @utils.xnor def dest_portRule(self, scapy_pkt): """ Filter packet based on the specified destination port rules. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: dict: 'action': User specified action 'result': Rule matched or not """ if scapy_pkt.haslayer(scapy.Raw): if str(scapy_pkt[scapy.TCP].dport) in self._DPORTS: return {'action': self._action_dest_portRule, 'result': 1} else: return {'action': self._action_dest_portRule, 'result': 0} else: return {'action': self._action_dest_portRule, 'result': 0} def HTTPRequest(self, scapy_pkt): """ Filter packet based on the specified HTTPRequest rules. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: dict: 'action': User specified action 'result': Rule matched or not """ try: if scapy_pkt.haslayer(scapy.Raw): if scapy_pkt[scapy.TCP].dport == 80: # User defined action return self._action_HTTPRequest else: # Allow if not found return 1 else: # Allow if not found return 1 except Exception as e: self.logger.log(str(e), logtype="error") return 1 def HTTPResponse(self, scapy_pkt): """ Filter packet based on the specified HTTP Response rules. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: dict: 'action': User specified action 'result': Rule matched or not """ try: if scapy_pkt.haslayer(scapy.Raw): if scapy_pkt[scapy.TCP].sport == 80: # User defined action return self._action_HTTPResponse else: # Allow if not found return 1 else: # Allow if not found return 1 except Exception as e: self.logger.log(str(e), logtype="error") return 1 @utils.xnor def scanLoad(self, scapy_pkt): """ Filter packet based on the specified scan load rules i.e. scan for the extensions. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: dict: 'action': User specified action 'result': Rule matched or not """ if scapy_pkt.haslayer(scapy.Raw): if scapy_pkt[scapy.TCP].dport == 80: for extension in self.extensions: if extension in scapy_pkt[scapy.Raw].load: return {'action': self._action_scanLoad, 'result': 1} else: return {'action': self._action_scanLoad, 'result': 0} else: return {'action': self._action_scanLoad, 'result': 0} else: return {'action': self._action_scanLoad, 'result': 0} @staticmethod def check_first_fragment(pkt): """ Check first fragment. Drop a packet if flag is "MF", offset value = 0 & total length < 120. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if (pkt.haslayer(scapy.IP)): if ((str(pkt[scapy.IP].flags) == "MF") and int(pkt[scapy.IP].frag) == 0 and int(pkt[scapy.IP].len) < 120): return 0 else: return 1 else: return 1 @staticmethod def check_ip_version(pkt): """ Check for unknown IP version Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if (pkt.haslayer(scapy.IP)): version = int(pkt[scapy.IP].version) if (version == 4 or version == 6): return 1 else: return 0 else: return 1 @staticmethod def check_ip_fragment_boundary(pkt): """ Check IP fragment boundary. Drop a packet if packet length + fragmentation offset > 65355 Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if (pkt.haslayer(scapy.IP)): if ((int(pkt[scapy.IP].len) + int(pkt[scapy.IP].frag)) > 65355): return 0 else: return 1 else: return 1 @staticmethod def check_ip_fragment_offset(pkt): """ Check IP fragment small offset. Drop a packet if 0 < fragmentation offset < 60 Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if (pkt.haslayer(scapy.IP)): frag = int(pkt[scapy.IP].frag) if (frag < 60 and frag > 0): return 0 else: return 1 else: return 1 @staticmethod def check_invalid_ip(pkt): """ Check invalid IP. Drop a packet if IP is invalid or is 0.0.0.0. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if (pkt.haslayer(scapy.IP)): source_ip = pkt[scapy.IP].src if (utils.check_ip(source_ip) and str(source_ip) != "0.0.0.0"): return 1 else: return 0 else: return 1 @staticmethod def check_ip_header_length(pkt): """ Check invalid IP header length. Drop a packet if length < 20 bytes. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if (pkt.haslayer(scapy.IP)): hlen = pkt[scapy.IP].len if int(hlen) < 20: return 0 else: return 1 else: return 1 @staticmethod def icmp_fragmentation_attack(pkt): """ Check for ICMP fragmentation. Drop a packet if protocol is set to ICMP, and IP flag is set to "MF" or fragment offset > 0. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if pkt.haslayer(scapy.IP): proto = int(pkt[scapy.IP].proto) if proto == 1: flags = str(pkt[scapy.IP].flags) frag = int(pkt[scapy.IP].frag) if (flags == "MF" or frag > 0): return 0 else: return 1 else: return 1 else: return 1 @staticmethod def check_large_icmp(pkt): """ Check for large ICMP. Drop a packet if protocol is set to ICMP, and length > 1024 bytes. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if pkt.haslayer(scapy.IP): proto = int(pkt[scapy.IP].proto) if proto == 1: hlen = int(pkt[scapy.IP].len) if (hlen > 1024): return 0 else: return 1 else: return 1 else: return 1 @staticmethod def syn_fragmentation_attack(pkt): """ Check for SYN fragmentation. Drop a packet if SYN flag is set, and IP flag is set to "MF" or fragment offset > 0. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if (pkt.haslayer(scapy.IP) and pkt.haslayer(scapy.TCP)): tcp_flag = pkt[scapy.TCP].flags if tcp_flag == "S": flags = str(pkt[scapy.IP].flags) frag = int(pkt[scapy.IP].frag) if (flags == "MF" or frag > 0): return 0 else: return 1 else: return 1 else: return 1 @staticmethod def check_fin_ack(pkt): """ Check whether “FIN” flag is set but not “ACK”. TCP segments with the FIN flag set also have the ACK flag set to acknowledge the previous packet received. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if pkt.haslayer(scapy.TCP): flag = str(pkt[scapy.TCP].flags) if "F" in flag: if (flag == "FA" or flag == "AF"): return 1 else: return 0 else: return 1 else: return 1 @staticmethod def check_tcp_flag(pkt): """ Check TCP flag. Drop a packet if TCP flag is None. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if pkt.haslayer(scapy.TCP): flag = pkt[scapy.TCP].flags if flag is None: return 0 else: return 1 else: return 1 @staticmethod def check_network_congestion(pkt): """ Enable network congestion detection by observing “ECE” flag at the TCP layer to reject packets. Args: scapy_pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ if pkt.haslayer(scapy.TCP): flag = str(pkt[scapy.TCP].flags) if (flag == "EC" or flag == "ECE"): return 0 else: return 1 else: return 1 def check_mal_ip(self, pkt): """ Check whether the source IP of the packet arriving is in the malicious IP list. Args: pkt (scapy_object): Packet to filter Raises: None Returns: bool (int): Allow or drop """ ip_list = utils.open_file(self._MAL_IP_PATH) source_ip = pkt[scapy.IP].src source_ip = source_ip.strip(" ") for ip in ip_list: ip = ip.strip(" ").strip("\n") if source_ip == ip: return 0 return 1 def process(self, pkt): """ Check whether the packet passed matches all the rules or not. Args: pkt: Packet Raises: None Returns: int: 1 if to allow, 0 to block """ scapy_pkt = scapy.IP(pkt.get_payload()) if (self.inbound_IPRule(scapy_pkt) and self.outbound_IPRule(scapy_pkt) and self.protocolRule(scapy_pkt) and self.DNSRule(scapy_pkt) and self.source_portRule(scapy_pkt) and self.dest_portRule(scapy_pkt) and self.HTTPResponse(scapy_pkt) and self.HTTPRequest(scapy_pkt) and self.check_first_fragment(scapy_pkt) and self.check_ip_version(scapy_pkt) and self.check_ip_fragment_boundary(scapy_pkt) and self.check_ip_fragment_offset(scapy_pkt) and self.check_invalid_ip(scapy_pkt) and self.check_ip_header_length(scapy_pkt) and self.icmp_fragmentation_attack(scapy_pkt) and self.check_large_icmp(scapy_pkt) and self.syn_fragmentation_attack(scapy_pkt) and self.check_fin_ack(scapy_pkt) and self.check_tcp_flag(scapy_pkt) and self.check_network_congestion(scapy_pkt) and self.check_mal_ip(scapy_pkt)): return 1 else: self.logger.log("Packet blocked.", logtype="info") # PCAP dumping of rejected packets self.pktdump.write(scapy_pkt) # Generate report using OSINT tools src_ip = scapy_pkt[scapy.IP].src src_ip = src_ip.strip(" ") self.osint_obj.perform_osint_scan(src_ip) return 0
class SpiderDetect(object): """SpiderDetect Class.""" def __init__(self, debug=False): """ Initialize SpiderDetect. Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = ServerLogger(__name__, debug=debug) # Path of file containing spider user agents payloads self._PAYLOAD_FILE = "securetea/lib/log_monitor/server_log/rules/payloads/bad_ua.txt" # Load spider user agents payloads self.payloads = utils.open_file(self._PAYLOAD_FILE) # Initialize threshold to 50 request / second self._THRESHOLD = 50 # inter = 0.02 # List of IPs self.logged_IP = list() # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def detect_spider(self, data): """ Detect possible Web Crawler / Spider / Bad user agents. High amount of unique GET request from an IP within a small period of time are likely to indicate a web crawler / spider. Look for bad user agents payload to guess a bad user agent. Args: data (dict): Parsed log file data Raises: None Returns: None """ for ip in data.keys(): count = data[ip]["count"] last_time = data[ip]["ep_time"][0] initial_time = data[ip]["ep_time"][int( len(data[ip]["ep_time"]) - 1)] delta = abs(int(last_time - initial_time)) try: calc_count_thresh = count / delta calc_get_thresh = len(data[ip]["unique_get"]) / delta except ZeroDivisionError: calc_count_thresh = count calc_get_thresh = len(data[ip]["unique_get"]) if (calc_count_thresh > self._THRESHOLD or calc_get_thresh > self._THRESHOLD or self.payload_match(data[ip]["ua"])): if ip not in self.logged_IP: self.logged_IP.append(ip) self.logger.log( "Possible web crawler / spider / bad user agent detected from: " + str(ip), logtype="warning") utils.write_ip(str(ip)) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(ip.strip(" ")) # Write malicious IP to file, to teach Firewall about the IP write_mal_ip(ip.strip(" ")) def payload_match(self, user_agent): """ Match parsed user agent for a possible bad user agent payload. Args: user_agent (str): User agent on which to perform payload string matching Raises: None Returns: TYPE: bool """ for agent in user_agent: for payload in self.payloads: payload = payload.strip(" ").strip("\n") if payload in agent: return True
class PortScan(object): """PortScan Class.""" def __init__(self, debug=False): """ Initialize PortScan. Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = logger.SecureTeaLogger(__name__, debug=debug) # OS name to auth-log path map self.system_log_map = {"debian": "/var/log/auth.log"} os_name = utils.categorize_os() self.log_file = None if os_name: try: self.log_file = self.system_log_map[os_name] except KeyError: self.logger.log("Could not find path for the auth-log file", logtype="error") return else: return # Salt to generate hashed username self.SALT = "<!@?>" # Regex to extract Received disconnect self.RECIEVED_DISCONNECT = r'^([a-zA-Z]+\s[0-9]+)\s([0-9]+:[0-9]+:[0-9]+).' \ r'*Received\sdisconnect\sfrom\s([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' # Initialize IP to count dict self.ip_dict = dict() # Set threshold to 5 attempts per second to detect port scan self.THRESHOLD = 5 # inter = 0.2 # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def parse_log_file(self): """ Parse the log file to extract IP address showing quick Recieved Disconnect. Args: None Raises: None Returns: None """ # Open the log file log_file_data = utils.open_file(self.log_file) for line in log_file_data: found = re.findall(self.RECIEVED_DISCONNECT, line) if (found is not None and found != []): date = found[0][0] month = date.split(" ")[0] day = date.split(" ")[1] last_time = found[0][1] ip = found[0][2] # convert date, time to epoch time epoch_time = utils.get_epoch_time(month, day, last_time) self.update_ip_dict(ip, date, epoch_time) def update_ip_dict(self, ip, date, epoch_time): """ Update IP address to count dict. Args: ip (str): IP address of the source date (str): Date of action (eg. Jun 1) epoch_time (int): Time during the attempt in epoch format Raises: None Returns: None """ # Generate a hashed IP using salt hashed_ip = ip + self.SALT + date if self.ip_dict.get(hashed_ip) is None: # if IP not in dict self.ip_dict[hashed_ip] = {"count": 1, "last_time": epoch_time} else: # update IP count & last time prev_count = self.ip_dict[hashed_ip]["count"] new_count = prev_count + 1 self.ip_dict[hashed_ip]["count"] = new_count self.ip_dict[hashed_ip]["last_time"] = epoch_time def detect_port_scan(self): """ Detect port scan by comparing the calculated ratio with the set threshold. Args: None Raises: None Returns: None """ for ip in self.ip_dict.keys(): count = self.ip_dict[ip]["count"] last_time = self.ip_dict[ip]["last_time"] current_time = time.time() try: delta_time = int(current_time - last_time) calc_threshold = count / delta_time except ZeroDivisionError: calc_threshold = int(count) if calc_threshold > self.THRESHOLD: msg = "Possible port scan detected from: " \ + ip.split(self.SALT)[0] + " on " \ + ip.split(self.SALT)[1] self.logger.log(msg, logtype="warning") # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan( ip.split(self.SALT)[0].strip(" ")) # Write malicious IP to file, to teach Firewall about the IP write_mal_ip(ip.split(self.SALT)[0].strip(" ")) def run(self): """ Start monitoring the log file for possible port scans. Args: None Raises: None Returns: None """ if self.log_file: # if path of log file is valid # Rotate & parse the log file self.parse_log_file() # Analyze the log for port scan self.detect_port_scan() # Empty the dict to rotate the log-file self.ip_dict.clear()
class SQLi(object): """SQLi Class.""" def __init__(self, debug=False): """ Initialize SQLi. Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = ServerLogger(__name__, debug=debug) # Path of file containing sqli payloads self.PAYLOAD_FILE = "securetea/lib/log_monitor/server_log/rules/payloads/sqli.txt" # Path of file containing sqli regex rules self.REGEX_FILE = "securetea/lib/log_monitor/server_log/rules/regex/sqli.txt" # Load sqli payloads self.payloads = utils.open_file(self.PAYLOAD_FILE) # Load sqli regex rules self.regex = utils.open_file(self.REGEX_FILE) # Logged IP list self.logged_IP = list() # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def detect_sqli(self, data): """ Detect possible SQL Injection (sqli) attacks. Use regex rules and string matching to detect SQLi attacks. 4 Level rules: - Simple regex - Hex regex - Payload string matching - URI encoded string matching Args: data (dict): Parsed log file data Raises: None Returns: None """ for ip in data.keys(): get_req = data[ip]["get"] last_time = data[ip]["ep_time"][0] if (self.payload_match(get_req) or self.regex_check(get_req)): if ip not in self.logged_IP: # if not logged earlier self.logged_IP.append(ip) msg = "Possible SQL injection (sqli) detected from: " + str(ip) + \ " on: " + str(utils.epoch_to_date(last_time)) self.logger.log(msg, logtype="warning") utils.write_ip(str(ip)) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(ip.strip(" ")) # Write malicious IP to file, to teach Firewall about the IP write_mal_ip(ip.strip(" ")) def payload_match(self, get_req): """ Match parsed GET request for a possible sqli payload. Args: get_req (str): GET request on which to perform payload string matching Raises: None Returns: TYPE: bool """ for req in get_req: for payload in self.payloads: payload = payload.strip(" ").strip("\n") if (payload in req or utils.uri_encode(payload) in req): return True def regex_check(self, get_req): """ Match parsed GET request with a sqli regex rules. Args: get_req (str): GET request on which to perform regex matching Raises: None Returns: TYPE: bool """ for req in get_req: for reg in self.regex: reg = reg.strip(" ").strip("\n") if re.findall(reg, req) != []: return True
class FuzzerDetect(object): """FuzzerDetect Class.""" def __init__(self, debug=False): """ Initialize FuzzerDetect. Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = ServerLogger(__name__, debug=debug) # Set threshold to 25 failure attempts / second self._THRESHOLD = 25 # inter = 0.04 # List of IPs self.logged_IP = list() # Initialize OSINT object self.osint_obj = OSINT(debug=debug) @staticmethod def count_failure(status_code): """ Counts the number of failure status code. Args: status_code (list): List of status codes Raises: None Returns: failure_count (int): Count of failure code """ failure_count = 0 for code in status_code: if (400 <= code < 500): # if failure code failure_count = failure_count + 1 return failure_count def detect_fuzzer(self, data): """ Detect possible URL fuzzing attacks. High number of failure codes (400-500) range from an IP within a small period of time indicates a possible fuzzing attack. Args: data (dict): Parsed log file data Raises: None Returns: None """ for ip in data.keys(): status_code = data[ip]["status_code"] # Count failure attempts for that IP failure_count = self.count_failure(status_code) last_time = data[ip]["ep_time"][0] initial_time = data[ip]["ep_time"][int( len(data[ip]["ep_time"]) - 1)] delta = abs(int(last_time - initial_time)) try: calc_count_thresh = failure_count / delta calc_get_thresh = len(data[ip]["get"]) / delta except ZeroDivisionError: calc_count_thresh = failure_count calc_get_thresh = len(data[ip]["get"]) if (calc_count_thresh > self._THRESHOLD or calc_get_thresh > self._THRESHOLD): if ip not in self.logged_IP: self.logged_IP.append(ip) msg = "Possible URL fuzzing detected from: " + str(ip) + \ " on: " + utils.epoch_to_date(data[ip]["ep_time"][0]) self.logger.log(msg, logtype="warning") utils.write_ip(str(ip)) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(ip.strip(" ")) # Write malicious IP to file, to teach Firewall about the IP write_mal_ip(ip.strip(" "))
class Ssrf (object): def __init__(self,test=False,debug=False): """ Initialize Ssrf Args: debug (bool): Log on terminal or not Raises: None Returns: None """ # Initialize logger self.logger = ServerLogger( __name__, debug=debug ) if test: # Path of file containing SSRF payloads self.PAYLOAD_FILE = "securetea/lib/log_monitor/server_log/rules/payloads/ssrf.txt" # Path of file containing SSRF regex rules self.REGEX_FILE = "securetea/lib/log_monitor/server_log/rules/regex/ssrf.txt" # Path of the IP Rules self.IP_FILE = "securetea/lib/log_monitor/server_log/rules/payloads/ips.txt" else: # Path of file containing SSRF payloads self.PAYLOAD_FILE = "/etc/securetea/log_monitor/server_log/payloads/ssrf.txt" # Path of file containing SSRF regex rules self.REGEX_FILE = "/etc/securetea/log_monitor/server_log/regex/ssrf.txt" # Path of the IP Rules self.IP_FILE = "/etc/securetea/log_monitor/server_log/payloads/ips.txt" # Load SSRF payloads self.payloads = utils.open_file(self.PAYLOAD_FILE) # Load SSRF regex rules self.regex = utils.open_file(self.REGEX_FILE) # IPs self.ips = utils.open_file(self.IP_FILE) # Logged IP list self.logged_IP = list() # Initialize OSINT object self.osint_obj = OSINT(debug=debug) def detect_ssrf(self , data): """ Detects SSRF Args: data (dict): Parsed Log File Raises: None Returns: None """ for ip in data.keys(): get_req = data[ip]["get"] last_time = data[ip]["ep_time"][0] # extracting all the urls in path urls=re.findall(r"https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+", get_req[0]) for url in urls: resolved_ip=utils.resolver(url) if resolved_ip: if (self.rmatch(resolved_ip)): if ip not in self.logged_IP: # if not logged earlier self.logged_IP.append(ip) msg = "Possible SSRF detected From: " + str(ip) + \ " on: " + str(utils.epoch_to_date(last_time)) self.logger.log( msg, logtype="warning" ) utils.write_ip(str(ip)) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(ip.strip(" ")) # Write malicious IP to file, to teach Firewall about the IP write_mal_ip(ip.strip(" ")) if(self.payload_match(url) or self.regex_match(get_req)): if ip not in self.logged_IP: self.logged_IP.append(ip) msg = "Possible SSRF detected From " + str(ip) + \ " on: " + str(utils.epoch_to_date(last_time)) self.logger.log(msg,logtype="warning") utils.write_ip(str(ip)) # Generate CSV report using OSINT tools self.osint_obj.perform_osint_scan(ip.strip(" ")) # Write malicious IP to file, to teach Firewall about the IP write_mal_ip(ip.strip(" ")) def payload_match(self,url): """ Match parsed URL from a GET Request to possible SSRF payload. Args: url (str): url on which to perform payload string matching Raises: None Returns: TYPE: bool """ for payloads in self.payloads: payload=payloads.strip(" ").strip("\n") if (payload in url or utils.uri_encode(payload) in url): return True def regex_match(self,req): """ Match parsed GET request for a possible SSRF regex Args: get_req (str): GET request on which to perform regex string matching Raises: None Returns: TYPE: bool """ for req in get_req: for reg in self.regex: reg = reg.strip(" ").strip("\n") if re.findall(reg, req) != []: return True def rmatch(self,ip): """ Match resolved IP for a possible SSRF in IP List. Args: ip (str): IP on which to perform payload string matching Raises: None Returns: TYPE: bool """ for payload_ip in self.ips: payload_ip=payload_ip.strip(" ").strip("\n") if payload_ip in ip: return True