def filter_user_criteria(self, data): """ Filter / grab data as per user rules from the log file on the basis of IP & status code. Args: data (dict): Parsed log file data Raises: None Returns: None """ for ip in data.keys(): if (ip in self.ip): # Look for IP match # User rule matched if ip not in self.logged_IP: # Logged earlier or not self.logged_IP.append(ip) self.generate_log_report(ip, data) for ip in data.keys(): # Look for status code match status_code = data[ip]["status_code"] for index, code in enumerate(status_code): if code in self.status_code: # User rule matched if ip not in self.logged_IP: # Logged earlier or not self.logged_IP.append(ip) msg = "IP: " + str(ip) + " GET: " + str(data[ip]["get"][index]) + \ " " + "Status code: " + str(code) + \ " on: " + utils.epoch_to_date(data[ip]["ep_time"][index]) self.logger.log(msg, logtype="info")
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))
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))
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))
def test_epoch_to_date(self, mck_dt): """ Test epoch_to_date. """ # Return a random date mck_dt.datetime.fromtimestamp.return_value = "random_date" res = utils.epoch_to_date(150000) # Assert datetime module is called with the epoch time mck_dt.datetime.fromtimestamp.assert_called_with(150000) # Check whether it is running as needed self.assertEqual(res, "random_date")
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) 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")
def generate_log_report(self, ip, data): """ Log the filtered data in the following format. IP: <ip> GET: <get_request> Status Code: <status_code> on: <date> Args: ip (str): IP address filtered data (dict): Log file parsed data Raises: None Returns: None """ for index, req in enumerate(data[ip]["get"]): msg = "IP: " + str(ip) + " GET: " + str(req) + \ " " + "Status Code: " + str(data[ip]["status_code"][index]) + \ " on: " + utils.epoch_to_date(data[ip]["ep_time"][index]) # Log the message self.logger.log(msg, logtype="info")
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))
def detect_lfi(self, data): """ Detect possible Local File Inclusion (lfi) attacks. Use string comparison to scan GET request with the list of possible LFI 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 IP not logged earlier self.logged_IP.append(ip) msg = "Possible LFI injection 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))