def doAction(self, action_id): src_hostname = self.getHostnameFromIP(self.__request.get('src_ip', '')) dst_hostname = self.getHostnameFromIP(self.__request.get('dst_ip', '')) protocol = Util.getProtoByNumber(self.__request.get('protocol', '')) self.__request['protocol'] = protocol replaces = { 'DATE': self.__request.get('date', ''), 'PLUGIN_ID': self.__request.get('plugin_id', ''), 'PLUGIN_SID': self.__request.get('plugin_sid', ''), 'RISK': self.__request.get('risk', ''), 'PRIORITY': self.__request.get('priority', ''), 'RELIABILITY': self.__request.get('reliability', ''), 'SRC_IP': self.__request.get('src_ip', ''), 'SRC_PORT': self.__request.get('src_port', ''), 'DST_IP': self.__request.get('dst_ip', ''), 'DST_PORT': self.__request.get('dst_port', ''), 'PROTOCOL': self.__request.get('protocol', ''), 'SENSOR': self.__request.get('sensor', ''), 'PLUGIN_NAME': self.__request.get('plugin_id', ''), 'SID_NAME': self.__request.get('plugin_sid', ''), 'USERDATA1': self.__request.get('userdata1', ''), 'USERDATA2': self.__request.get('userdata2', ''), 'USERDATA3': self.__request.get('userdata3', ''), 'USERDATA4': self.__request.get('userdata4', ''), 'USERDATA5': self.__request.get('userdata5', ''), 'USERDATA6': self.__request.get('userdata6', ''), 'USERDATA7': self.__request.get('userdata7', ''), 'USERDATA8': self.__request.get('userdata8', ''), 'USERDATA9': self.__request.get('userdata9', ''), 'FILENAME': self.__request.get('filename', ''), 'USERNAME': self.__request.get('username', ''), 'PASSWORD': self.__request.get('password', ''), 'BACKLOG_ID': self.__request.get('backlog_id', ''), 'EVENT_ID': self.__request.get('event_id', ''), 'SRC_IP_HOSTNAME':src_hostname, 'DST_IP_HOSTNAME':dst_hostname, } # Fields with integer values int_fields = ["PLUGIN_ID", "PLUGIN_SID", "RISK", "PRIORITY", "RELIABILITY", "SRC_PORT", "DST_PORT"] query = "SELECT * FROM plugin WHERE id = %d" % int(self.__request['plugin_id']) for plugin in self.__db.exec_query(query): # should only yield one result anyway replaces["PLUGIN_NAME"] = plugin['name'] query = "SELECT * FROM plugin_sid WHERE plugin_id = %d AND sid = %d" % \ (int(self.__request['plugin_id']), int(self.__request['plugin_sid'])) for plugin_sid in self.__db.exec_query(query): # should only yield one result anyway replaces["SID_NAME"] = plugin_sid['name'] query = "SELECT a.id as id,a.ctx as ctx,a.action_type as action_type ,\ a.cond as cond,a.on_risk as on_risk,a.descr as descr,\ at.name as name FROM action a, action_type at \ WHERE id = unhex('%s') and a.action_type = at.type" % (action_id) for action in self.__db.exec_query(query): #################################################################### # Condition #################################################################### # get the condition expression condition = action['cond'] # authorized operators operators = [ "+", "-", "*", "/", "%", "==", "<=", "<", ">=", ">", " and ", " or ", "(", ")", " True ", "False", "!=", ] # only operators and characters in [A-Z0-9_ ] # condition = '"' + condition +'"' condition_tmp = " %s " % condition for operator in operators: condition_tmp = condition_tmp.replace(operator, " ") logger.debug ("Condiction after op %s before op %s " % (condition_tmp, condition)) if not re.match("^[A-Za-z0-9_\'\" ]+$", condition_tmp): logger.warning(": Illegal character in condition: %s - Allowed characters (A-Za-z0-9_ ' \")" % condition) condition = "False" # no function call if re.search("[A-Za-z0-9_]+\s*\(", condition): logger.warning(": Illegal function call in condition: %s" % condition) condition = "False" # replacements for key in replaces: if key in int_fields: condition = condition.replace(key, replaces[key]) else: condition = condition.replace(key, "'" + replaces[key] + "'") # condition evaluation try: logger.debug(": condition = '%s'" % condition) condition = eval(condition) except Exception, e: logger.debug(": Condition evaluation failed: %s --> %s" % (condition, str(e))) condition = False logger.debug(": eval(condition) = %s" % condition) # is the condition True? if not condition: continue # is the action based on risk increase? if int(action['on_risk']) == 1: backlog_id = self.__request.get('backlog_id', '') risk_old = 0 risk_new = int(self.__request.get('risk', '')) # get the old risk value query = "SELECT * FROM action_risk WHERE action_id = unhex('%s') AND backlog_id = unhex('%s')" % (action_id, backlog_id) for action_risk in self.__db.exec_query(query): # should only yield one result anyway risk_old = int(action_risk['risk']) break else: query = "INSERT INTO action_risk VALUES (%d, %d, %d)" % ( int(action_id), int(backlog_id), int(risk_new)) logger.debug(": %s" % query) self.__db.exec_query(query) # is there a risk increase? logger.debug(": risk_new > risk_old = %s" % (risk_new > risk_old)) if risk_new <= risk_old: continue # save the new risk value query = "UPDATE action_risk SET risk = %d WHERE action_id = unhex('%s') AND backlog_id = unhex('%s')" % ( int(risk_new), action_id, backlog_id) logger.debug(": %s" % query) self.__db.exec_query(query) # cleanup the action_risk table query = "DELETE FROM action_risk WHERE backlog_id NOT IN (SELECT id FROM backlog)" logger.debug(": %s" % query) self.__db.exec_query(query) #################################################################### # email notification logger.info("Successful Response with action: %s" % action['descr']) if action['name'] == 'email': self.get_mail_server_data() if not self.__email_server_relay_enabled: logger.warning("Email server relay not enabled. Using local postfix..") query = "SELECT * FROM action_email WHERE action_id = unhex('%s')" % \ (action_id) for action_email in self.__db.exec_query(query): email_from = action_email['_from'] email_to = action_email['_to'].split(',') if len(email_to) == 1: email_to = action_email['_to'].split(';') email_subject = action_email['subject'] email_message = action_email['message'] for replace in replaces: if replaces[replace]: email_from = email_from.replace(replace, replaces[replace]) for to_mail in email_to: to_mail = to_mail.strip() to_mail = to_mail.replace(replace, \ replaces[replace]) replace_variable = r'\b%s\b' % replace value_to_replace = replaces[replace].encode('string_escape') email_subject = re.sub(replace_variable,value_to_replace , email_subject) # email_subject= email_subject.replace(replace, replaces[replace]) if replace == 'DATE': value_to_replace += " (UTC time)" email_message = re.sub(replace_variable, value_to_replace, email_message) use_local_server = not self.__email_server_relay_enabled m = ActionMail(self.__email_server,self.__email_server_port,self.__email_server_user, self.__email_server_passwd, use_local_server) for mail in email_to: m.sendmail(email_from, mail, email_subject, email_message + \ "\n\n" + self.requestRepr(self.__request, mail)) del(m) # execute external command elif action['name'] == 'exec': query = "SELECT * FROM action_exec WHERE action_id = unhex('%s')" % \ (action_id) for action_exec in self.__db.exec_query(query): action = action_exec['command'] for replace in replaces: replace_variable = r'\b%s\b' % replace action = re.sub(replace_variable, replaces[replace].encode('string_escape'), action) # action = action.replace(replace, replaces[replace]) c = ActionExec() c.execCommand(action) del(c) elif action['name'] == 'ticket': descr = action['descr'] plugin_id = int(self.__request.get('plugin_id', '')) plugin_sid = int(self.__request.get('plugin_sid', '')) title = 'Automatic Incident Ticket' namequery = "select if((select name from plugin_sid where plugin_id='%s' and sid='%s')!='',(select name from plugin_sid where plugin_id='%s' and sid='%s') , 'Automatic Incident Ticket') as name;" % (plugin_id, plugin_sid, plugin_id, plugin_sid) data = self.__db.exec_query(namequery) if data != []: title = data[0]['name'] regexp = re.compile('(?P<data>.*)##@##(?P<username>.*)') matches = regexp.search(descr) in_charge = 'admin' if matches: in_charge = matches.group('username') descr = matches.group('data') priority = int(self.__request.get('priority', '')) * 2 incident_uuid = "%s" % uuid.uuid4() incident_uuid = incident_uuid.replace('-', '') ctx = self.__request.get('context_id', '') for replace in replaces: if replaces[replace]: replace_variable = r'\b%s\b' % replace descr = re.sub(replace_variable, replaces[replace].encode('string_escape'), descr) ctx = ctx.replace('-', '') insert_query = """insert into incident (uuid,ctx,title,date,ref,type_id,priority,status,last_update,in_charge,submitter,event_start,event_end) values (unhex('%s'),unhex('%s'),'%s',utc_timestamp(),'Event','Generic','%s','Open',utc_timestamp(),'%s','admin',utc_timestamp(),utc_timestamp()); """ % (incident_uuid, ctx, title, priority, in_charge) self.__db.exec_query(insert_query) logger.debug("Query: %s" % insert_query) src_ip = self.__request.get('src_ip', '') src_port = int(self.__request.get('src_port', '')) dst_ip = self.__request.get('dst_ip', '') dst_port = int(self.__request.get('dst_port', '')) # last_id_ie = data[0]['id'] +1 """ We need the last id from incident in order to insert it. """ get_last_id_query = "select max(id) as id from incident;" data = self.__db.exec_query(get_last_id_query) if data != []: last_id = data[0]['id'] insert_incident_event_query = """ INSERT INTO incident_event (incident_id,src_ips,src_ports,dst_ips,dst_ports) values ('%s','%s','%s','%s','%s'); """ % (last_id, src_ip, src_port, dst_ip, dst_port) insert_subscription_query = "REPLACE INTO incident_subscrip(login, incident_id) VALUES('admin', {0})".format(last_id) self.__db.exec_query(insert_incident_event_query) self.__db.exec_query(insert_subscription_query) data = self.__db.exec_query("select max(id)+1 as id from incident_ticket;") newid = '0' if data != []: newid = data[0]['id'] insert_ticket_query = """ insert into incident_ticket(id,incident_id,date,status,priority,description,in_charge,users) values ('%s','%s',utc_timestamp(),'Open','%s','%s','%s','admin');""" % (newid, last_id, priority, descr, in_charge) self.__db.exec_query(insert_ticket_query) # Check if this context has an IRS webservice linked. ticket_data = {'type': '', 'op': 'INSERT', 'incident_id': last_id, 'date': time.asctime(), 'in_charge': in_charge, 'description': descr, 'status': 'Open'} ws_query = "SELECT id, type FROM webservice WHERE ctx = UNHEX('%s') AND type IN ('%s')" % (ctx, ','.join(IRS_TYPES)) ws_data = self.__db.exec_query(ws_query) for item in ws_data: ticket_data['type'] = ws_data['type'] # Create webservices, if available. handler = WSHandler (self.__conf, item['id']) if handler != None: ret = handler.process_db (ticket_data) else: logger.error("Invalid action_type: '%s'" % action['action_type'])
def doAction(self, action_id): src_hostname = self.getHostnameFromIP(self.__request.get('src_ip', '')) dst_hostname = self.getHostnameFromIP(self.__request.get('dst_ip', '')) plugin_id = int(self.__request['plugin_id']) plugin_sid = int(self.__request['plugin_sid']) protocol = Util.getProtoByNumber(self.__request.get('protocol', '')) self.__request['protocol'] = protocol replaces = { 'DATE': self.__request.get('date', ''), 'PLUGIN_ID': self.__request.get('plugin_id', ''), 'PLUGIN_SID': self.__request.get('plugin_sid', ''), 'RISK': self.__request.get('risk', ''), 'PRIORITY': self.__request.get('priority', ''), 'RELIABILITY': self.__request.get('reliability', ''), 'SRC_IP': self.__request.get('src_ip', ''), 'SRC_PORT': self.__request.get('src_port', ''), 'DST_IP': self.__request.get('dst_ip', ''), 'DST_PORT': self.__request.get('dst_port', ''), 'PROTOCOL': self.__request.get('protocol', ''), 'SENSOR': self.__request.get('sensor', ''), 'PLUGIN_NAME': self.__request.get('plugin_id', ''), 'SID_NAME': self.__request.get('plugin_sid', ''), 'USERDATA1': self.__request.get('userdata1', ''), 'USERDATA2': self.__request.get('userdata2', ''), 'USERDATA3': self.__request.get('userdata3', ''), 'USERDATA4': self.__request.get('userdata4', ''), 'USERDATA5': self.__request.get('userdata5', ''), 'USERDATA6': self.__request.get('userdata6', ''), 'USERDATA7': self.__request.get('userdata7', ''), 'USERDATA8': self.__request.get('userdata8', ''), 'USERDATA9': self.__request.get('userdata9', ''), 'FILENAME': self.__request.get('filename', ''), 'USERNAME': self.__request.get('username', ''), 'PASSWORD': self.__request.get('password', ''), 'BACKLOG_ID': self.__request.get('backlog_id', ''), 'EVENT_ID': self.__request.get('event_id', ''), 'SRC_IP_HOSTNAME':src_hostname, 'DST_IP_HOSTNAME':dst_hostname, } # Fields with integer values int_fields = ["PLUGIN_ID", "PLUGIN_SID", "RISK", "PRIORITY", "RELIABILITY", "SRC_PORT", "DST_PORT"] query = "SELECT * FROM plugin WHERE id = %s" for plugin in self.__db.exec_query(query, (plugin_id,)): # should only yield one result anyway replaces["PLUGIN_NAME"] = plugin['name'] query = "SELECT * FROM plugin_sid WHERE plugin_id = %s AND sid = %s" for plugin_sid in self.__db.exec_query(query, (plugin_id, plugin_sid)): # should only yield one result anyway replaces["SID_NAME"] = plugin_sid['name'] query = "SELECT a.id as id,a.ctx as ctx,a.action_type as action_type ,\ a.cond as cond,a.on_risk as on_risk,a.descr as descr,\ at.name as name FROM action a, action_type at \ WHERE id = unhex(%s) and a.action_type = at.type" for action in self.__db.exec_query(query, (action_id,)): #################################################################### # Condition #################################################################### # get the condition expression condition = action['cond'] # authorized operators operators = [ "+", "-", "*", "/", "%", "==", "<=", "<", ">=", ">", " and ", " or ", "(", ")", " True ", "False", "!=", ] # only operators and characters in [A-Z0-9_ ] # condition = '"' + condition +'"' condition_tmp = " %s " % condition for operator in operators: condition_tmp = condition_tmp.replace(operator, " ") logger.debug ("Condiction after op %s before op %s " % (condition_tmp, condition)) if not re.match("^[A-Za-z0-9_\'\" ]+$", condition_tmp): logger.warning(": Illegal character in condition: %s - Allowed characters (A-Za-z0-9_ ' \")" % condition) condition = "False" # no function call if re.search("[A-Za-z0-9_]+\s*\(", condition): logger.warning(": Illegal function call in condition: %s" % condition) condition = "False" # replacements for key in replaces: if key in int_fields: condition = condition.replace(key, replaces[key]) else: condition = condition.replace(key, "'" + replaces[key] + "'") # condition evaluation try: logger.debug(": condition = '%s'" % condition) condition = eval(condition) except Exception, e: logger.debug(": Condition evaluation failed: %s --> %s" % (condition, str(e))) condition = False logger.debug(": eval(condition) = %s" % condition) # is the condition True? if not condition: continue # is the action based on risk increase? if int(action['on_risk']) == 1: backlog_id = self.__request.get('backlog_id', '') risk_old = 0 risk_new = int(self.__request.get('risk', '')) # get the old risk value query = "SELECT * FROM action_risk WHERE action_id = unhex(%s) AND backlog_id = unhex(%s)" for action_risk in self.__db.exec_query(query, (action_id, backlog_id)): # should only yield one result anyway risk_old = int(action_risk['risk']) break else: query = self.__db.format_query( "INSERT INTO action_risk VALUES (%s, %s, %s)", (int(action_id), int(backlog_id), int(risk_new)) ) logger.debug(": %s" % query) self.__db.exec_query(query) # is there a risk increase? logger.debug(": risk_new > risk_old = %s" % (risk_new > risk_old)) if risk_new <= risk_old: continue # save the new risk value query = self.__db.format_query( "UPDATE action_risk SET risk = %s WHERE action_id = unhex(%s) AND backlog_id = unhex(%s)", (int(risk_new), action_id, backlog_id) ) logger.debug(": %s" % query) self.__db.exec_query(query) # cleanup the action_risk table query = "DELETE FROM action_risk WHERE backlog_id NOT IN (SELECT id FROM backlog)" logger.debug(": %s" % query) self.__db.exec_query(query) #################################################################### # email notification logger.info("Successful Response with action: %s" % action['descr']) if action['name'] == 'email': self.get_mail_server_data() if not self.__email_server_relay_enabled: logger.warning("Email server relay not enabled. Using local postfix..") query = "SELECT * FROM action_email WHERE action_id = unhex(%s)" for action_email in self.__db.exec_query(query, (action_id,)): email_from = action_email['_from'] email_to = action_email['_to'].split(',') if len(email_to) == 1: email_to = action_email['_to'].split(';') email_subject = action_email['subject'] email_message = action_email['message'] for replace in replaces: if replaces[replace]: email_from = email_from.replace(replace, replaces[replace]) for to_mail in email_to: to_mail = to_mail.strip() to_mail = to_mail.replace(replace, \ replaces[replace]) replace_variable = r'\b%s\b' % replace value_to_replace = replaces[replace].encode('string_escape') email_subject = re.sub(replace_variable,value_to_replace , email_subject) # email_subject= email_subject.replace(replace, replaces[replace]) if replace == 'DATE': value_to_replace += " (UTC time)" email_message = re.sub(replace_variable, value_to_replace, email_message) use_local_server = not self.__email_server_relay_enabled m = ActionMail(self.__email_server,self.__email_server_port,self.__email_server_user, self.__email_server_passwd, use_local_server) for mail in email_to: new_email_message = email_message; if action_email['message_suffix'] == 1: new_email_message += "\n\n" + self.requestRepr(self.__request, mail) m.sendmail(email_from, mail, email_subject, new_email_message) del(m) # execute external command elif action['name'] == 'exec': query = "SELECT * FROM action_exec WHERE action_id = unhex(%s)" for action_exec in self.__db.exec_query(query, (action_id,)): action = action_exec['command'] for replace in replaces: replace_variable = r'\b%s\b' % replace action = re.sub(replace_variable, replaces[replace].encode('string_escape'), action) # action = action.replace(replace, replaces[replace]) c = ActionExec() c.execCommand(action) del(c) elif action['name'] == 'ticket': descr = action['descr'] title = 'Automatic Incident Ticket' namequery = "SELECT name FROM action WHERE id = unhex(%s);" data = self.__db.exec_query(namequery, {action_id}) if data != []: title = data[0]['name'] regexp = re.compile('(?P<data>.*)##@##(?P<username>.*)') matches = regexp.search(descr) in_charge = 'admin' if matches: in_charge = matches.group('username') descr = matches.group('data') priority = int(self.__request.get('priority', '')) * 2 incident_uuid = "%s" % uuid.uuid4() incident_uuid = incident_uuid.replace('-', '') ctx = self.__request.get('context_id', '') for replace in replaces: if replaces[replace]: replace_variable = r'\b%s\b' % replace descr = re.sub(replace_variable, replaces[replace].encode('string_escape'), descr) ctx = ctx.replace('-', '') insert_query = "insert into incident (uuid,ctx,title,date,ref,type_id,priority,status,last_update," \ "in_charge,submitter,event_start,event_end) values (unhex(%(uuid)s)," \ "unhex(%(ctx)s),%(title)s,utc_timestamp(),'Event','Generic',%(priority)s," \ "'Open',utc_timestamp(),%(in_charge)s,'admin',utc_timestamp(),utc_timestamp());" params = { "uuid": incident_uuid, "ctx": ctx, "title": title, "priority": priority, "in_charge": in_charge } insert_query = self.__db.format_query(insert_query, params) self.__db.exec_query(insert_query) logger.debug("Query: %s" % insert_query) src_ip = self.__request.get('src_ip', '') src_port = int(self.__request.get('src_port', '')) dst_ip = self.__request.get('dst_ip', '') dst_port = int(self.__request.get('dst_port', '')) # last_id_ie = data[0]['id'] +1 """ We need the last id from incident in order to insert it. """ get_last_id_query = "select max(id) as id from incident;" data = self.__db.exec_query(get_last_id_query) if data != []: last_id = data[0]['id'] insert_incident_event_query = "INSERT INTO incident_event (incident_id,src_ips,src_ports,dst_ips,dst_ports) values (%s,%s,%s,%s,%s);" insert_subscription_query = "REPLACE INTO incident_subscrip(login, incident_id) VALUES('admin', %s)" self.__db.exec_query(insert_incident_event_query, (last_id, src_ip, src_port, dst_ip, dst_port)) self.__db.exec_query(insert_subscription_query, (last_id,)) data = self.__db.exec_query("select max(id)+1 as id from incident_ticket;") newid = '0' if data != []: newid = data[0]['id'] risk = int(self.__request.get('risk', '')) #Tickets from vulnerabilities come from a trigger, so we should only deal with events/alarms here if risk >= 0: alarm_url = "<a target=\"_blank\" href=\"/ossim/alarm/alarm_detail.php?event=%s\">Link to Alarm</a>" % (self.__request.get('event_id', '').upper().replace('-','')) descr = descr + "<br>" + alarm_url elif risk == 0: pass # #This is an event # #There appears to be no easy way to link to an event so this is shelved # #https://192.168.200.90/ossim/forensics/base_qry_alert.php?noheader=true&pag=&submit=#0-29482C89670511E59BF8000CD1ADBA0E&m_opt=analysis&sm_opt=security_events&h_opt=security_events # event_id = self.__request.get('event_id', '').upper().replace('-','') # event_url = "<a target=\"_blank\" href=\"https://%s/ossim/forensics/base_qry_alert.php?noheader=true&pag=&submit=#0-%s&m_opt=analysis&sm_opt=security_events&h_opt=security_events\">Link to Event</a>" % (ossim_setup['framework_ip'], event_id) # descr = descr + "<br>" + event_url insert_ticket_query = "insert into incident_ticket(id,incident_id,date,status,priority,description," \ "in_charge,users) values (%(id)s,%(incident_id)s,utc_timestamp(),'Open'," \ "%(priority)s,%(description)s,%(in_charge)s,'admin');" insert_ticket_params = { "id": newid, "incident_id": last_id, "priority": priority, "description": descr, "in_charge": in_charge } self.__db.exec_query(insert_ticket_query, insert_ticket_params) # Check if this context has an IRS webservice linked. ticket_data = {'type': '', 'op': 'INSERT', 'incident_id': last_id, 'date': time.asctime(), 'in_charge': in_charge, 'description': descr, 'status': 'Open'} type_params = ["%s" for _ in xrange(len(IRS_TYPES))] ws_query = "SELECT id, type FROM webservice WHERE ctx = UNHEX(%s) AND type IN (" + \ ",".join(type_params) + ")" ws_data = self.__db.exec_query(ws_query, tuple([ctx] + IRS_TYPES)) for item in ws_data: ticket_data['type'] = ws_data['type'] # Create webservices, if available. handler = WSHandler (self.__conf, item['id']) if handler is not None: ret = handler.process_db (ticket_data) else: logger.error("Invalid action_type: '%s'" % action['action_type'])
def doAction(self, action_id): src_hostname = self.getHostnameFromIP(self.__request.get('src_ip', '')) dst_hostname = self.getHostnameFromIP(self.__request.get('dst_ip', '')) plugin_id = int(self.__request['plugin_id']) plugin_sid = int(self.__request['plugin_sid']) protocol = Util.getProtoByNumber(self.__request.get('protocol', '')) self.__request['protocol'] = protocol replaces = { 'DATE': self.__request.get('date', ''), 'PLUGIN_ID': self.__request.get('plugin_id', ''), 'PLUGIN_SID': self.__request.get('plugin_sid', ''), 'RISK': self.__request.get('risk', ''), 'PRIORITY': self.__request.get('priority', ''), 'RELIABILITY': self.__request.get('reliability', ''), 'SRC_IP': self.__request.get('src_ip', ''), 'SRC_PORT': self.__request.get('src_port', ''), 'DST_IP': self.__request.get('dst_ip', ''), 'DST_PORT': self.__request.get('dst_port', ''), 'PROTOCOL': self.__request.get('protocol', ''), 'SENSOR': self.__request.get('sensor', ''), 'PLUGIN_NAME': self.__request.get('plugin_id', ''), 'SID_NAME': self.__request.get('plugin_sid', ''), 'USERDATA1': self.__request.get('userdata1', ''), 'USERDATA2': self.__request.get('userdata2', ''), 'USERDATA3': self.__request.get('userdata3', ''), 'USERDATA4': self.__request.get('userdata4', ''), 'USERDATA5': self.__request.get('userdata5', ''), 'USERDATA6': self.__request.get('userdata6', ''), 'USERDATA7': self.__request.get('userdata7', ''), 'USERDATA8': self.__request.get('userdata8', ''), 'USERDATA9': self.__request.get('userdata9', ''), 'FILENAME': self.__request.get('filename', ''), 'USERNAME': self.__request.get('username', ''), 'PASSWORD': self.__request.get('password', ''), 'BACKLOG_ID': self.__request.get('backlog_id', ''), 'EVENT_ID': self.__request.get('event_id', ''), 'SRC_IP_HOSTNAME': src_hostname, 'DST_IP_HOSTNAME': dst_hostname, } # Fields with integer values int_fields = [ "PLUGIN_ID", "PLUGIN_SID", "RISK", "PRIORITY", "RELIABILITY", "SRC_PORT", "DST_PORT" ] query = "SELECT * FROM plugin WHERE id = %s" for plugin in self.__db.exec_query(query, (plugin_id, )): # should only yield one result anyway replaces["PLUGIN_NAME"] = plugin['name'] query = "SELECT * FROM plugin_sid WHERE plugin_id = %s AND sid = %s" for plugin_sid in self.__db.exec_query(query, (plugin_id, plugin_sid)): # should only yield one result anyway replaces["SID_NAME"] = plugin_sid['name'] query = "SELECT a.id as id,a.ctx as ctx,a.action_type as action_type ,\ a.cond as cond,a.on_risk as on_risk,a.descr as descr,\ at.name as name FROM action a, action_type at \ WHERE id = unhex(%s) and a.action_type = at.type" for action in self.__db.exec_query(query, (action_id, )): #################################################################### # Condition #################################################################### # get the condition expression condition = action['cond'] # authorized operators operators = [ "+", "-", "*", "/", "%", "==", "<=", "<", ">=", ">", " and ", " or ", "(", ")", " True ", "False", "!=", ] # only operators and characters in [A-Z0-9_ ] # condition = '"' + condition +'"' condition_tmp = " %s " % condition for operator in operators: condition_tmp = condition_tmp.replace(operator, " ") logger.debug("Condiction after op %s before op %s " % (condition_tmp, condition)) if not re.match("^[A-Za-z0-9_\'\" ]+$", condition_tmp): logger.warning( ": Illegal character in condition: %s - Allowed characters (A-Za-z0-9_ ' \")" % condition) condition = "False" # no function call if re.search("[A-Za-z0-9_]+\s*\(", condition): logger.warning(": Illegal function call in condition: %s" % condition) condition = "False" # replacements for key in replaces: if key in int_fields: condition = condition.replace(key, replaces[key]) else: condition = condition.replace(key, "'" + replaces[key] + "'") # condition evaluation try: logger.debug(": condition = '%s'" % condition) condition = eval(condition) except Exception, e: logger.debug(": Condition evaluation failed: %s --> %s" % (condition, str(e))) condition = False logger.debug(": eval(condition) = %s" % condition) # is the condition True? if not condition: continue # is the action based on risk increase? if int(action['on_risk']) == 1: backlog_id = self.__request.get('backlog_id', '') risk_old = 0 risk_new = int(self.__request.get('risk', '')) # get the old risk value query = "SELECT * FROM action_risk WHERE action_id = unhex(%s) AND backlog_id = unhex(%s)" for action_risk in self.__db.exec_query( query, (action_id, backlog_id)): # should only yield one result anyway risk_old = int(action_risk['risk']) break else: query = self.__db.format_query( "INSERT INTO action_risk VALUES (%s, %s, %s)", (int(action_id), int(backlog_id), int(risk_new))) logger.debug(": %s" % query) self.__db.exec_query(query) # is there a risk increase? logger.debug(": risk_new > risk_old = %s" % (risk_new > risk_old)) if risk_new <= risk_old: continue # save the new risk value query = self.__db.format_query( "UPDATE action_risk SET risk = %s WHERE action_id = unhex(%s) AND backlog_id = unhex(%s)", (int(risk_new), action_id, backlog_id)) logger.debug(": %s" % query) self.__db.exec_query(query) # cleanup the action_risk table query = "DELETE FROM action_risk WHERE backlog_id NOT IN (SELECT id FROM backlog)" logger.debug(": %s" % query) self.__db.exec_query(query) #################################################################### # email notification logger.info("Successful Response with action: %s" % action['descr']) if action['name'] == 'email': self.get_mail_server_data() if not self.__email_server_relay_enabled: logger.warning( "Email server relay not enabled. Using local postfix.." ) query = "SELECT * FROM action_email WHERE action_id = unhex(%s)" for action_email in self.__db.exec_query(query, (action_id, )): email_from = action_email['_from'] email_to = action_email['_to'].split(',') if len(email_to) == 1: email_to = action_email['_to'].split(';') email_subject = action_email['subject'] email_message = action_email['message'] for replace in replaces: if replaces[replace]: email_from = email_from.replace( replace, replaces[replace]) for to_mail in email_to: to_mail = to_mail.strip() to_mail = to_mail.replace(replace, \ replaces[replace]) replace_variable = r'\b%s\b' % replace value_to_replace = replaces[replace].encode( 'string_escape') email_subject = re.sub(replace_variable, value_to_replace, email_subject) # email_subject= email_subject.replace(replace, replaces[replace]) if replace == 'DATE': value_to_replace += " (UTC time)" email_message = re.sub(replace_variable, value_to_replace, email_message) use_local_server = not self.__email_server_relay_enabled m = ActionMail(self.__email_server, self.__email_server_port, self.__email_server_user, self.__email_server_passwd, use_local_server) for mail in email_to: new_email_message = email_message if action_email['message_suffix'] == 1: new_email_message += "\n\n" + self.requestRepr( self.__request, mail) m.sendmail(email_from, mail, email_subject, new_email_message) del (m) # execute external command elif action['name'] == 'exec': query = "SELECT * FROM action_exec WHERE action_id = unhex(%s)" for action_exec in self.__db.exec_query(query, (action_id, )): action = action_exec['command'] for replace in replaces: replace_variable = r'\b%s\b' % replace action = re.sub( replace_variable, replaces[replace].encode('string_escape'), action) # action = action.replace(replace, replaces[replace]) c = ActionExec() c.execCommand(action) del (c) elif action['name'] == 'ticket': descr = action['descr'] title = 'Automatic Incident Ticket' namequery = "SELECT name FROM action WHERE id = unhex(%s);" data = self.__db.exec_query(namequery, {action_id}) if data != []: title = data[0]['name'] regexp = re.compile('(?P<data>.*)##@##(?P<username>.*)') matches = regexp.search(descr) in_charge = 'admin' if matches: in_charge = matches.group('username') descr = matches.group('data') priority = int(self.__request.get('priority', '')) * 2 incident_uuid = "%s" % uuid.uuid4() incident_uuid = incident_uuid.replace('-', '') ctx = self.__request.get('context_id', '') for replace in replaces: if replaces[replace]: replace_variable = r'\b%s\b' % replace descr = re.sub( replace_variable, replaces[replace].encode('string_escape'), descr) ctx = ctx.replace('-', '') insert_query = "insert into incident (uuid,ctx,title,date,ref,type_id,priority,status,last_update," \ "in_charge,submitter,event_start,event_end) values (unhex(%(uuid)s)," \ "unhex(%(ctx)s),%(title)s,utc_timestamp(),'Event','Generic',%(priority)s," \ "'Open',utc_timestamp(),%(in_charge)s,'admin',utc_timestamp(),utc_timestamp());" params = { "uuid": incident_uuid, "ctx": ctx, "title": title, "priority": priority, "in_charge": in_charge } insert_query = self.__db.format_query(insert_query, params) self.__db.exec_query(insert_query) logger.debug("Query: %s" % insert_query) src_ip = self.__request.get('src_ip', '') src_port = int(self.__request.get('src_port', '')) dst_ip = self.__request.get('dst_ip', '') dst_port = int(self.__request.get('dst_port', '')) # last_id_ie = data[0]['id'] +1 """ We need the last id from incident in order to insert it. """ get_last_id_query = "select max(id) as id from incident;" data = self.__db.exec_query(get_last_id_query) if data != []: last_id = data[0]['id'] insert_incident_event_query = "INSERT INTO incident_event (incident_id,src_ips,src_ports,dst_ips,dst_ports) values (%s,%s,%s,%s,%s);" insert_subscription_query = "REPLACE INTO incident_subscrip(login, incident_id) VALUES('admin', %s)" self.__db.exec_query( insert_incident_event_query, (last_id, src_ip, src_port, dst_ip, dst_port)) self.__db.exec_query(insert_subscription_query, (last_id, )) data = self.__db.exec_query( "select max(id)+1 as id from incident_ticket;") newid = '0' if data != []: newid = data[0]['id'] risk = int(self.__request.get('risk', '')) #Tickets from vulnerabilities come from a trigger, so we should only deal with events/alarms here if risk >= 0: alarm_url = "<a target=\"_blank\" href=\"/ossim/alarm/alarm_detail.php?event=%s\">Link to Alarm</a>" % ( self.__request.get('event_id', '').upper().replace( '-', '')) descr = descr + "<br>" + alarm_url elif risk == 0: pass # #This is an event # #There appears to be no easy way to link to an event so this is shelved # #https://192.168.200.90/ossim/forensics/base_qry_alert.php?noheader=true&pag=&submit=#0-29482C89670511E59BF8000CD1ADBA0E&m_opt=analysis&sm_opt=security_events&h_opt=security_events # event_id = self.__request.get('event_id', '').upper().replace('-','') # event_url = "<a target=\"_blank\" href=\"https://%s/ossim/forensics/base_qry_alert.php?noheader=true&pag=&submit=#0-%s&m_opt=analysis&sm_opt=security_events&h_opt=security_events\">Link to Event</a>" % (ossim_setup['framework_ip'], event_id) # descr = descr + "<br>" + event_url insert_ticket_query = "insert into incident_ticket(id,incident_id,date,status,priority,description," \ "in_charge,users) values (%(id)s,%(incident_id)s,utc_timestamp(),'Open'," \ "%(priority)s,%(description)s,%(in_charge)s,'admin');" insert_ticket_params = { "id": newid, "incident_id": last_id, "priority": priority, "description": descr, "in_charge": in_charge } self.__db.exec_query(insert_ticket_query, insert_ticket_params) # Check if this context has an IRS webservice linked. ticket_data = { 'type': '', 'op': 'INSERT', 'incident_id': last_id, 'date': time.asctime(), 'in_charge': in_charge, 'description': descr, 'status': 'Open' } type_params = ["%s" for _ in xrange(len(IRS_TYPES))] ws_query = "SELECT id, type FROM webservice WHERE ctx = UNHEX(%s) AND type IN (" + \ ",".join(type_params) + ")" ws_data = self.__db.exec_query(ws_query, tuple([ctx] + IRS_TYPES)) for item in ws_data: ticket_data['type'] = ws_data['type'] # Create webservices, if available. handler = WSHandler(self.__conf, item['id']) if handler is not None: ret = handler.process_db(ticket_data) else: logger.error("Invalid action_type: '%s'" % action['action_type'])
def doAction(self, action_id): replaces = { 'DATE': self.__request.get('date', ''), 'PLUGIN_ID': self.__request.get('plugin_id', ''), 'PLUGIN_SID': self.__request.get('plugin_sid', ''), 'RISK': self.__request.get('risk', ''), 'PRIORITY': self.__request.get('priority', ''), 'RELIABILITY': self.__request.get('reliability', ''), 'SRC_IP': self.__request.get('src_ip', ''), 'SRC_PORT': self.__request.get('src_port', ''), 'DST_IP': self.__request.get('dst_ip', ''), 'DST_PORT': self.__request.get('dst_port', ''), 'PROTOCOL': self.__request.get('protocol', ''), 'SENSOR': self.__request.get('sensor', ''), 'PLUGIN_NAME': self.__request.get('plugin_id', ''), 'SID_NAME': self.__request.get('plugin_sid', ''), 'USERDATA1': self.__request.get('userdata1', ''), 'USERDATA2': self.__request.get('userdata2', ''), 'USERDATA3': self.__request.get('userdata3', ''), 'USERDATA4': self.__request.get('userdata4', ''), 'USERDATA5': self.__request.get('userdata5', ''), 'USERDATA6': self.__request.get('userdata6', ''), 'USERDATA7': self.__request.get('userdata7', ''), 'USERDATA8': self.__request.get('userdata8', ''), 'USERDATA9': self.__request.get('userdata9', ''), 'FILENAME': self.__request.get('filename', ''), 'USERNAME': self.__request.get('username', ''), 'PASSWORD': self.__request.get('password', ''), 'BACKLOG_ID': self.__request.get('backlog_id', ''), 'EVENT_ID': self.__request.get('event_id', ''), } query = "SELECT * FROM plugin WHERE id = %d" % int( self.__request['plugin_id']) for plugin in self.__db.exec_query(query): # should only yield one result anyway replaces["PLUGIN_NAME"] = plugin['name'] query = "SELECT * FROM plugin_sid WHERE plugin_id = %d AND sid = %d" %\ (int(self.__request['plugin_id']), int(self.__request['plugin_sid'])) for plugin_sid in self.__db.exec_query(query): # should only yield one result anyway replaces["SID_NAME"] = plugin_sid['name'] query = "SELECT * FROM action WHERE id = %d" % (action_id) for action in self.__db.exec_query(query): logger.info("Successful Response with action: %s" % action['descr']) # TODO: Remove when confirmed # print __name__, ": Successful Response with action: ", action['descr'] #################################################################### # Condition #################################################################### # get the condition expression condition = action['cond'] # authorized operators operators = [ "+", "-", "*", "/", "%", "==", "<=", "<", ">=", ">", " and ", " or ", "(", ")", " True ", "False" ] # only operators and characters in [A-Z0-9_ ] condition_tmp = " %s " % condition for operator in operators: condition_tmp = condition_tmp.replace(operator, " ") if not re.match("^[A-Z0-9_ ]+$", condition_tmp): print __name__, ": Illegal character in condition: %s" % condition condition = "False" # no function call if re.search("[A-Z0-9_]+\s*\(", condition): print __name__, ": Illegal function call in condition: %s" % condition condition = "False" # replacements for key in replaces: condition = condition.replace(key, replaces[key]) # condition evaluation try: print __name__, ": condition = '%s'" % condition condition = eval(condition) except Exception, e: print __name__, ": Condition evaluation failed: %s" % condition condition = False print __name__, ": eval(condition) = %s" % condition # is the condition True? if not condition: continue # is the action based on risk increase? if int(action['on_risk']) == 1: backlog_id = int(self.__request.get('backlog_id', '')) risk_old = 0 risk_new = int(self.__request.get('risk', '')) # get the old risk value query = "SELECT * FROM action_risk WHERE action_id = %d AND backlog_id = %d" % ( int(action_id), int(backlog_id)) for action_risk in self.__db.exec_query(query): # should only yield one result anyway risk_old = int(action_risk['risk']) break else: query = "INSERT INTO action_risk VALUES (%d, %d, %d)" % ( int(action_id), int(backlog_id), int(risk_new)) print __name__, ": %s" % query self.__db.exec_query(query) # is there a risk increase? print __name__, ": risk_new > risk_old = %s" % (risk_new > risk_old) if risk_new <= risk_old: continue # save the new risk value query = "UPDATE action_risk SET risk = %d WHERE action_id = %d AND backlog_id = %d" % ( int(risk_new), int(action_id), int(backlog_id)) print __name__, ": %s" % query self.__db.exec_query(query) # cleanup the action_risk table query = "DELETE FROM action_risk WHERE backlog_id NOT IN (SELECT id FROM backlog)" print __name__, ": %s" % query self.__db.exec_query(query) #################################################################### # email notification if action['action_type'] == 'email': query = "SELECT * FROM action_email WHERE action_id = %d" %\ (action_id) for action_email in self.__db.exec_query(query): email_from = action_email['_from'] email_to = action_email['_to'].split(',') email_subject = action_email['subject'] email_message = action_email['message'] for replace in replaces: if replaces[replace]: email_from = email_from.replace( replace, replaces[replace]) for to_mail in email_to: to_mail = to_mail.strip() to_mail = to_mail.replace(replace,\ replaces[replace]) email_subject = email_subject.replace( replace, replaces[replace]) email_message = email_message.replace( replace, replaces[replace]) m = ActionMail() m.sendmail(email_from, email_to, email_subject, email_message +\ "\n\n" + self.requestRepr(self.__request)) del (m) # execute external command elif action['action_type'] == 'exec': query = "SELECT * FROM action_exec WHERE action_id = %d" %\ (action_id) for action_exec in self.__db.exec_query(query): action = action_exec['command'] for replace in replaces: action = action.replace(replace, replaces[replace]) c = ActionExec() c.execCommand(action) del (c) elif action['action_type'] == 'syslog': syslog(request)
def doAction(self, action_id): replaces = { 'DATE': self.__request.get('date', ''), 'PLUGIN_ID': self.__request.get('plugin_id', ''), 'PLUGIN_SID': self.__request.get('plugin_sid', ''), 'RISK': self.__request.get('risk', ''), 'PRIORITY': self.__request.get('priority', ''), 'RELIABILITY': self.__request.get('reliability', ''), 'SRC_IP': self.__request.get('src_ip', ''), 'SRC_PORT': self.__request.get('src_port', ''), 'DST_IP': self.__request.get('dst_ip', ''), 'DST_PORT': self.__request.get('dst_port', ''), 'PROTOCOL': self.__request.get('protocol', ''), 'SENSOR': self.__request.get('sensor', ''), 'PLUGIN_NAME': self.__request.get('plugin_id', ''), 'SID_NAME': self.__request.get('plugin_sid', ''), 'USERDATA1': self.__request.get('userdata1', ''), 'USERDATA2': self.__request.get('userdata2', ''), 'USERDATA3': self.__request.get('userdata3', ''), 'USERDATA4': self.__request.get('userdata4', ''), 'USERDATA5': self.__request.get('userdata5', ''), 'USERDATA6': self.__request.get('userdata6', ''), 'USERDATA7': self.__request.get('userdata7', ''), 'USERDATA8': self.__request.get('userdata8', ''), 'USERDATA9': self.__request.get('userdata9', ''), 'FILENAME': self.__request.get('filename', ''), 'USERNAME': self.__request.get('username', ''), 'PASSWORD': self.__request.get('password', ''), 'BACKLOG_ID': self.__request.get('backlog_id', ''), 'EVENT_ID': self.__request.get('event_id', ''), } query = "SELECT * FROM plugin WHERE id = %d" % int(self.__request['plugin_id']) for plugin in self.__db.exec_query(query): # should only yield one result anyway replaces["PLUGIN_NAME"] = plugin['name'] query = "SELECT * FROM plugin_sid WHERE plugin_id = %d AND sid = %d" %\ (int(self.__request['plugin_id']), int(self.__request['plugin_sid'])) for plugin_sid in self.__db.exec_query(query): # should only yield one result anyway replaces["SID_NAME"] = plugin_sid['name'] query = "SELECT * FROM action WHERE id = %d" % (action_id) for action in self.__db.exec_query(query): logger.info("Successful Response with action: %s" % action['descr']) #################################################################### # Condition #################################################################### # get the condition expression condition = action['cond'] # authorized operators operators = [ "+", "-", "*", "/", "%", "==", "<=", "<", ">=", ">", " and ", " or ", "(", ")", " True ", "False" ] # only operators and characters in [A-Z0-9_ ] condition_tmp = " %s " % condition for operator in operators: condition_tmp = condition_tmp.replace(operator, " ") if not re.match("^[A-Z0-9_ ]+$", condition_tmp): logger.warning( ": Illegal character in condition: %s" % condition) condition = "False" # no function call if re.search("[A-Z0-9_]+\s*\(", condition): logger.warning(": Illegal function call in condition: %s" % condition) condition = "False" # replacements for key in replaces: condition = condition.replace(key, replaces[key]) # condition evaluation try: logger.debug(": condition = '%s'" % condition) condition = eval(condition) except Exception, e: logger.debug( ": Condition evaluation failed: %s --> %s" % (condition,str(e))) condition = False logger.debug( ": eval(condition) = %s" % condition) # is the condition True? if not condition: continue # is the action based on risk increase? if int(action['on_risk']) == 1: backlog_id = int(self.__request.get('backlog_id', '')) risk_old = 0 risk_new = int(self.__request.get('risk', '')) # get the old risk value query = "SELECT * FROM action_risk WHERE action_id = %d AND backlog_id = %d" % (int(action_id), int(backlog_id)) for action_risk in self.__db.exec_query(query): # should only yield one result anyway risk_old = int(action_risk['risk']) break else: query = "INSERT INTO action_risk VALUES (%d, %d, %d)" % ( int(action_id), int(backlog_id), int(risk_new)) logger.debug( ": %s" % query) self.__db.exec_query(query) # is there a risk increase? logger.debug( ": risk_new > risk_old = %s" % (risk_new > risk_old)) if risk_new <= risk_old: continue # save the new risk value query = "UPDATE action_risk SET risk = %d WHERE action_id = %d AND backlog_id = %d" % ( int(risk_new), int(action_id), int(backlog_id)) logger.debug( ": %s" % query) self.__db.exec_query(query) # cleanup the action_risk table query = "DELETE FROM action_risk WHERE backlog_id NOT IN (SELECT id FROM backlog)" logger.debug(": %s" % query) self.__db.exec_query(query) #################################################################### # email notification if action['action_type'] == 'email': query = "SELECT * FROM action_email WHERE action_id = %d" %\ (action_id) for action_email in self.__db.exec_query(query): email_from = action_email['_from'] email_to = action_email['_to'].split(',') email_subject = action_email['subject'] email_message = action_email['message'] for replace in replaces: if replaces[replace]: email_from = email_from.replace(replace, replaces[replace]) for to_mail in email_to: to_mail = to_mail.strip() to_mail = to_mail.replace(replace,\ replaces[replace]) replace_variable=r'\b%s\b'%replace email_subject = re.sub(replace_variable,replaces[replace],email_subject) #email_subject= email_subject.replace(replace, replaces[replace]) email_message = re.sub(replace_variable,replaces[replace],email_message) #email_message = email_message.replace(replace, replaces[replace]) m = ActionMail() m.sendmail(email_from, email_to, email_subject, email_message +\ "\n\n" + self.requestRepr(self.__request)) del(m) # execute external command elif action['action_type'] == 'exec': query = "SELECT * FROM action_exec WHERE action_id = %d" %\ (action_id) for action_exec in self.__db.exec_query(query): action = action_exec['command'] for replace in replaces: action = action.replace(replace, replaces[replace]) c = ActionExec() c.execCommand(action) del(c) elif action['action_type'] == 'syslog': syslog(self.__request) elif action['action_type'] == 'ticket': descr = action['descr'] plugin_id = int(self.__request.get('plugin_id', '')) plugin_sid = int(self.__request.get('plugin_sid', '')) title = 'Automatic Incident Ticket' namequery ="select if((select name from plugin_sid where plugin_id='%s' and sid='%s')!='',(select name from plugin_sid where plugin_id='%s' and sid='%s') , 'Automatic Incident Ticket') as name;" % (plugin_id,plugin_sid,plugin_id,plugin_sid) data = self.__db.exec_query(namequery) if data !=[]: title = data[0]['name'] regexp = re.compile('(?P<data>.*)##@##(?P<username>.*)') matches = regexp.search(descr) in_charge = 'admin' descr='' if matches: in_charge = matches.group('username') descr = matches.group('data') get_last_id_query = "select max(id) as id from incident;" data = self.__db.exec_query(get_last_id_query) if data != []: last_id = data[0]['id'] +1 priority = int(self.__request.get('priority', '')) *2 insert_query = """insert into incident (id,title,date,ref,type_id,priority,status,last_update,in_charge,submitter,event_start,event_end) values ('%s','%s',now(),'Event','Generic','%s','Open',now(),'%s','admin',now(),now()); """ % (last_id,title,priority,in_charge) self.__db.exec_query(insert_query) logger.debug("Query: %s" % insert_query) get_last_id_query = "select max(id) as id from incident_event;" data = self.__db.exec_query(get_last_id_query) if data != []: src_ip = self.__request.get('src_ip', '') src_port = int(self.__request.get('src_port', '')) dst_ip = self.__request.get('dst_ip', '') dst_port = int(self.__request.get('dst_port', '')) last_id_ie = data[0]['id'] +1 insert_incident_event_query = """ insert into incident_event (id,incident_id,src_ips,src_ports,dst_ips,dst_ports) values ('%s','%s','%s','%s','%s','%s'); """ % (last_id_ie,last_id,src_ip,src_port,dst_ip,dst_port) self.__db.exec_query(insert_incident_event_query) logger.debug("Query2:_ %s" % insert_incident_event_query) else: logger.error("Can't insert incident because it can't be retrieved the max id.") else: logger.error("Invalid action_type: '%s'" % action['action_type'])
def doAction(self, action_id): replaces = { 'DATE': self.__request.get('date', ''), 'PLUGIN_ID': self.__request.get('plugin_id', ''), 'PLUGIN_SID': self.__request.get('plugin_sid', ''), 'RISK': self.__request.get('risk', ''), 'PRIORITY': self.__request.get('priority', ''), 'RELIABILITY': self.__request.get('reliability', ''), 'SRC_IP': self.__request.get('src_ip', ''), 'SRC_PORT': self.__request.get('src_port', ''), 'DST_IP': self.__request.get('dst_ip', ''), 'DST_PORT': self.__request.get('dst_port', ''), 'PROTOCOL': self.__request.get('protocol', ''), 'SENSOR': self.__request.get('sensor', ''), 'PLUGIN_NAME': self.__request.get('plugin_id', ''), 'SID_NAME': self.__request.get('plugin_sid', ''), 'USERDATA1': self.__request.get('userdata1', ''), 'USERDATA2': self.__request.get('userdata2', ''), 'USERDATA3': self.__request.get('userdata3', ''), 'USERDATA4': self.__request.get('userdata4', ''), 'USERDATA5': self.__request.get('userdata5', ''), 'USERDATA6': self.__request.get('userdata6', ''), 'USERDATA7': self.__request.get('userdata7', ''), 'USERDATA8': self.__request.get('userdata8', ''), 'USERDATA9': self.__request.get('userdata9', ''), 'FILENAME': self.__request.get('filename', ''), 'USERNAME': self.__request.get('username', ''), 'PASSWORD': self.__request.get('password', ''), 'BACKLOG_ID': self.__request.get('backlog_id', ''), 'EVENT_ID': self.__request.get('event_id', ''), } query = "SELECT * FROM plugin WHERE id = %d" % int(self.__request['plugin_id']) for plugin in self.__db.exec_query(query): # should only yield one result anyway replaces["PLUGIN_NAME"] = plugin['name'] query = "SELECT * FROM plugin_sid WHERE plugin_id = %d AND sid = %d" %\ (int(self.__request['plugin_id']), int(self.__request['plugin_sid'])) for plugin_sid in self.__db.exec_query(query): # should only yield one result anyway replaces["SID_NAME"] = plugin_sid['name'] query = "SELECT * FROM action WHERE id = %d" % (action_id) for action in self.__db.exec_query(query): logger.info("Successful Response with action: %s" % action['descr']) # TODO: Remove when confirmed # print __name__, ": Successful Response with action: ", action['descr'] #################################################################### # Condition #################################################################### # get the condition expression condition = action['cond'] # authorized operators operators = [ "+", "-", "*", "/", "%", "==", "<=", "<", ">=", ">", " and ", " or ", "(", ")", " True ", "False" ] # only operators and characters in [A-Z0-9_ ] condition_tmp = " %s " % condition for operator in operators: condition_tmp = condition_tmp.replace(operator, " ") if not re.match("^[A-Z0-9_ ]+$", condition_tmp): print __name__, ": Illegal character in condition: %s" % condition condition = "False" # no function call if re.search("[A-Z0-9_]+\s*\(", condition): print __name__, ": Illegal function call in condition: %s" % condition condition = "False" # replacements for key in replaces: condition = condition.replace(key, replaces[key]) # condition evaluation try: print __name__, ": condition = '%s'" % condition condition = eval(condition) except Exception, e: print __name__, ": Condition evaluation failed: %s" % condition condition = False print __name__, ": eval(condition) = %s" % condition # is the condition True? if not condition: continue # is the action based on risk increase? if int(action['on_risk']) == 1: backlog_id = int(self.__request.get('backlog_id', '')) risk_old = 0 risk_new = int(self.__request.get('risk', '')) # get the old risk value query = "SELECT * FROM action_risk WHERE action_id = %d AND backlog_id = %d" % ( int(action_id), int(backlog_id)) for action_risk in self.__db.exec_query(query): # should only yield one result anyway risk_old = int(action_risk['risk']) break else: query = "INSERT INTO action_risk VALUES (%d, %d, %d)" % ( int(action_id), int(backlog_id), int(risk_new)) print __name__, ": %s" % query self.__db.exec_query(query) # is there a risk increase? print __name__, ": risk_new > risk_old = %s" % (risk_new > risk_old) if risk_new <= risk_old: continue # save the new risk value query = "UPDATE action_risk SET risk = %d WHERE action_id = %d AND backlog_id = %d" % ( int(risk_new), int(action_id), int(backlog_id)) print __name__, ": %s" % query self.__db.exec_query(query) # cleanup the action_risk table query = "DELETE FROM action_risk WHERE backlog_id NOT IN (SELECT id FROM backlog)" print __name__, ": %s" % query self.__db.exec_query(query) #################################################################### # email notification if action['action_type'] == 'email': query = "SELECT * FROM action_email WHERE action_id = %d" %\ (action_id) for action_email in self.__db.exec_query(query): email_from = action_email['_from'] email_to = action_email['_to'].split(',') email_subject = action_email['subject'] email_message = action_email['message'] for replace in replaces: if replaces[replace]: email_from = email_from.replace(replace, replaces[replace]) for to_mail in email_to: to_mail = to_mail.strip() to_mail = to_mail.replace(replace,\ replaces[replace]) email_subject= email_subject.replace(replace, replaces[replace]) email_message = email_message.replace(replace, replaces[replace]) m = ActionMail() m.sendmail(email_from, email_to, email_subject, email_message +\ "\n\n" + self.requestRepr(self.__request)) del(m) # execute external command elif action['action_type'] == 'exec': query = "SELECT * FROM action_exec WHERE action_id = %d" %\ (action_id) for action_exec in self.__db.exec_query(query): action = action_exec['command'] for replace in replaces: action = action.replace(replace, replaces[replace]) c = ActionExec() c.execCommand(action) del(c) elif action['action_type'] == 'syslog': syslog(request)
def doAction(self, action_id): src_hostname = self.getHostnameFromIP(self.__request.get('src_ip', '')) dst_hostname = self.getHostnameFromIP(self.__request.get('dst_ip', '')) protocol = Util.getProtoByNumber(self.__request.get('protocol', '')) self.__request['protocol'] = protocol replaces = { 'DATE': self.__request.get('date', ''), 'PLUGIN_ID': self.__request.get('plugin_id', ''), 'PLUGIN_SID': self.__request.get('plugin_sid', ''), 'RISK': self.__request.get('risk', ''), 'PRIORITY': self.__request.get('priority', ''), 'RELIABILITY': self.__request.get('reliability', ''), 'SRC_IP': self.__request.get('src_ip', ''), 'SRC_PORT': self.__request.get('src_port', ''), 'DST_IP': self.__request.get('dst_ip', ''), 'DST_PORT': self.__request.get('dst_port', ''), 'PROTOCOL': self.__request.get('protocol', ''), 'SENSOR': self.__request.get('sensor', ''), 'PLUGIN_NAME': self.__request.get('plugin_id', ''), 'SID_NAME': self.__request.get('plugin_sid', ''), 'USERDATA1': self.__request.get('userdata1', ''), 'USERDATA2': self.__request.get('userdata2', ''), 'USERDATA3': self.__request.get('userdata3', ''), 'USERDATA4': self.__request.get('userdata4', ''), 'USERDATA5': self.__request.get('userdata5', ''), 'USERDATA6': self.__request.get('userdata6', ''), 'USERDATA7': self.__request.get('userdata7', ''), 'USERDATA8': self.__request.get('userdata8', ''), 'USERDATA9': self.__request.get('userdata9', ''), 'FILENAME': self.__request.get('filename', ''), 'USERNAME': self.__request.get('username', ''), 'PASSWORD': self.__request.get('password', ''), 'BACKLOG_ID': self.__request.get('backlog_id', ''), 'EVENT_ID': self.__request.get('event_id', ''), 'SRC_IP_HOSTNAME': src_hostname, 'DST_IP_HOSTNAME': dst_hostname, } # Fields with integer values int_fields = [ "PLUGIN_ID", "PLUGIN_SID", "RISK", "PRIORITY", "RELIABILITY", "SRC_PORT", "DST_PORT" ] query = "SELECT * FROM plugin WHERE id = %d" % int( self.__request['plugin_id']) for plugin in self.__db.exec_query(query): # should only yield one result anyway replaces["PLUGIN_NAME"] = plugin['name'] query = "SELECT * FROM plugin_sid WHERE plugin_id = %d AND sid = %d" % \ (int(self.__request['plugin_id']), int(self.__request['plugin_sid'])) for plugin_sid in self.__db.exec_query(query): # should only yield one result anyway replaces["SID_NAME"] = plugin_sid['name'] query = "SELECT a.id as id,a.ctx as ctx,a.action_type as action_type ,\ a.cond as cond,a.on_risk as on_risk,a.descr as descr,\ at.name as name FROM action a, action_type at \ WHERE id = unhex('%s') and a.action_type = at.type" % ( action_id) for action in self.__db.exec_query(query): #################################################################### # Condition #################################################################### # get the condition expression condition = action['cond'] # authorized operators operators = [ "+", "-", "*", "/", "%", "==", "<=", "<", ">=", ">", " and ", " or ", "(", ")", " True ", "False", "!=", ] # only operators and characters in [A-Z0-9_ ] # condition = '"' + condition +'"' condition_tmp = " %s " % condition for operator in operators: condition_tmp = condition_tmp.replace(operator, " ") logger.debug("Condiction after op %s before op %s " % (condition_tmp, condition)) if not re.match("^[A-Za-z0-9_\'\" ]+$", condition_tmp): logger.warning( ": Illegal character in condition: %s - Allowed characters (A-Za-z0-9_ ' \")" % condition) condition = "False" # no function call if re.search("[A-Za-z0-9_]+\s*\(", condition): logger.warning(": Illegal function call in condition: %s" % condition) condition = "False" # replacements for key in replaces: if key in int_fields: condition = condition.replace(key, replaces[key]) else: condition = condition.replace(key, "'" + replaces[key] + "'") # condition evaluation try: logger.debug(": condition = '%s'" % condition) condition = eval(condition) except Exception, e: logger.debug(": Condition evaluation failed: %s --> %s" % (condition, str(e))) condition = False logger.debug(": eval(condition) = %s" % condition) # is the condition True? if not condition: continue # is the action based on risk increase? if int(action['on_risk']) == 1: backlog_id = self.__request.get('backlog_id', '') risk_old = 0 risk_new = int(self.__request.get('risk', '')) # get the old risk value query = "SELECT * FROM action_risk WHERE action_id = unhex('%s') AND backlog_id = unhex('%s')" % ( action_id, backlog_id) for action_risk in self.__db.exec_query(query): # should only yield one result anyway risk_old = int(action_risk['risk']) break else: query = "INSERT INTO action_risk VALUES (%d, %d, %d)" % ( int(action_id), int(backlog_id), int(risk_new)) logger.debug(": %s" % query) self.__db.exec_query(query) # is there a risk increase? logger.debug(": risk_new > risk_old = %s" % (risk_new > risk_old)) if risk_new <= risk_old: continue # save the new risk value query = "UPDATE action_risk SET risk = %d WHERE action_id = unhex('%s') AND backlog_id = unhex('%s')" % ( int(risk_new), action_id, backlog_id) logger.debug(": %s" % query) self.__db.exec_query(query) # cleanup the action_risk table query = "DELETE FROM action_risk WHERE backlog_id NOT IN (SELECT id FROM backlog)" logger.debug(": %s" % query) self.__db.exec_query(query) #################################################################### # email notification logger.info("Successful Response with action: %s" % action['descr']) if action['name'] == 'email': self.get_mail_server_data() if not self.__email_server_relay_enabled: logger.warning( "Email server relay not enabled. Using local postfix.." ) query = "SELECT * FROM action_email WHERE action_id = unhex('%s')" % \ (action_id) for action_email in self.__db.exec_query(query): email_from = action_email['_from'] email_to = action_email['_to'].split(',') if len(email_to) == 1: email_to = action_email['_to'].split(';') email_subject = action_email['subject'] email_message = action_email['message'] for replace in replaces: if replaces[replace]: email_from = email_from.replace( replace, replaces[replace]) for to_mail in email_to: to_mail = to_mail.strip() to_mail = to_mail.replace(replace, \ replaces[replace]) replace_variable = r'\b%s\b' % replace value_to_replace = replaces[replace].encode( 'string_escape') email_subject = re.sub(replace_variable, value_to_replace, email_subject) # email_subject= email_subject.replace(replace, replaces[replace]) if replace == 'DATE': value_to_replace += " (UTC time)" email_message = re.sub(replace_variable, value_to_replace, email_message) # email_message = email_message.replace(replace, replaces[replace]) use_local_server = not self.__email_server_relay_enabled m = ActionMail(self.__email_server, self.__email_server_port, self.__email_server_user, self.__email_server_passwd, use_local_server) # logger.info(email_message) for mail in email_to: m.sendmail(email_from, mail, email_subject, email_message + \ "\n\n" + self.requestRepr(self.__request, mail)) del (m) # execute external command elif action['name'] == 'exec': query = "SELECT * FROM action_exec WHERE action_id = unhex('%s')" % \ (action_id) for action_exec in self.__db.exec_query(query): action = action_exec['command'] for replace in replaces: replace_variable = r'\b%s\b' % replace action = re.sub( replace_variable, replaces[replace].encode('string_escape'), action) # action = action.replace(replace, replaces[replace]) c = ActionExec() c.execCommand(action) del (c) elif action['name'] == 'syslog': pass # syslog(self.__request) elif action['name'] == 'ticket': descr = action['descr'] plugin_id = int(self.__request.get('plugin_id', '')) plugin_sid = int(self.__request.get('plugin_sid', '')) title = 'Automatic Incident Ticket' namequery = "select if((select name from plugin_sid where plugin_id='%s' and sid='%s')!='',(select name from plugin_sid where plugin_id='%s' and sid='%s') , 'Automatic Incident Ticket') as name;" % ( plugin_id, plugin_sid, plugin_id, plugin_sid) data = self.__db.exec_query(namequery) if data != []: title = data[0]['name'] regexp = re.compile('(?P<data>.*)##@##(?P<username>.*)') matches = regexp.search(descr) in_charge = 'admin' if matches: in_charge = matches.group('username') descr = matches.group('data') priority = int(self.__request.get('priority', '')) * 2 incident_uuid = "%s" % uuid.uuid4() incident_uuid = incident_uuid.replace('-', '') ctx = self.__request.get('context_id', '') for replace in replaces: if replaces[replace]: replace_variable = r'\b%s\b' % replace descr = re.sub( replace_variable, replaces[replace].encode('string_escape'), descr) ctx = ctx.replace('-', '') insert_query = """insert into incident (uuid,ctx,title,date,ref,type_id,priority,status,last_update,in_charge,submitter,event_start,event_end) values (unhex('%s'),unhex('%s'),'%s',utc_timestamp(),'Event','Generic','%s','Open',utc_timestamp(),'%s','admin',utc_timestamp(),utc_timestamp()); """ % ( incident_uuid, ctx, title, priority, in_charge) self.__db.exec_query(insert_query) logger.debug("Query: %s" % insert_query) src_ip = self.__request.get('src_ip', '') src_port = int(self.__request.get('src_port', '')) dst_ip = self.__request.get('dst_ip', '') dst_port = int(self.__request.get('dst_port', '')) # last_id_ie = data[0]['id'] +1 """ We need the last id from incident in order to insert it. """ get_last_id_query = "select max(id) as id from incident;" data = self.__db.exec_query(get_last_id_query) if data != []: last_id = data[0]['id'] insert_incident_event_query = """ insert into incident_event (incident_id,src_ips,src_ports,dst_ips,dst_ports) values ('%s','%s','%s','%s','%s'); """ % ( last_id, src_ip, src_port, dst_ip, dst_port) data = self.__db.exec_query( "select max(id)+1 as id from incident_ticket;") newid = '0' if data != []: newid = data[0]['id'] self.__db.exec_query(insert_incident_event_query) insert_ticket_query = """ insert into incident_ticket(id,incident_id,date,status,priority,description,in_charge,users) values ('%s','%s',utc_timestamp(),'Open','%s','%s','%s','');""" % ( newid, last_id, priority, descr, in_charge) self.__db.exec_query(insert_ticket_query) # Check if this context has an IRS webservice linked. ticket_data = { 'type': '', 'op': 'INSERT', 'incident_id': last_id, 'date': time.asctime(), 'in_charge': in_charge, 'description': descr, 'status': 'Open' } ws_query = "SELECT id, type FROM webservice WHERE ctx = UNHEX('%s') AND type IN (%s)" % ( ctx, '(' + ','.join(IRS_TYPES) + ')') ws_data = self.__db.exec_query(ws_query) for item in ws_data: ticket_data['type'] = ws_data['type'] # Create webservices, if available. handler = WSHandler(self.__conf, item['id']) if handler != None: ret = handler.process_db(ticket_data) else: logger.error("Invalid action_type: '%s'" % action['action_type'])