in aristotle/aristotle.py [0:0]
def get_sids(self, kvpair, negate=False):
"""Get a list of all SIDs for passed in key-value pair.
:param kvpair: key-value pair
:type kvpair: string, required
:param negate: returns the inverse of the result (i.e. all SIDs not matching the ``kvpair``), defaults to `False`
:type negate: bool, optional
:returns: list of matching SIDs
:rtype: list
:raises: `AristotleException`
"""
k, v = [e.strip() for e in kvpair.split(' ', 1)]
retarray = []
# these keys support '>', '<', '>=', and '<='
rangekeys = ['sid',
'cve',
'cvss_v2_base',
'cvss_v2_temporal',
'cvss_v3_base',
'cvss_v3_temporal',
'created_at',
'updated_at',
'risk_score']
if k in rangekeys and (v.startswith('<') or v.startswith('>')) and v not in ["<all>", "<any>"]:
if len(v) < 2:
print_error("Invalid value '{}' for key '{}'.".format(v, k), fatal=True)
if k == "cve":
# handle cve ranges; format is YYYY-<sequence_number>
try:
offset = 1
if v[1] == '=':
offset += 1
cmp_operator = v[:offset]
cve_val = v[offset:].strip()
print_debug("cmp_operator: {}, cve_val: {}".format(cmp_operator, cve_val))
retarray = [s for s in [s2 for s2 in self.metadata_dict.keys() if k in self.metadata_dict[s2]["metadata"].keys()]
for val in self.metadata_dict[s]["metadata"][k]
if self.cve_compare(left_val=val, right_val=cve_val, cmp_operator=cmp_operator)]
except Exception as e:
print_error("Unable to process key '{}' value '{}' (as CVE number):\n{}".format(k, v, e), fatal=True)
elif k in ["created_at", "updated_at"]:
# parse/treat as datetime objects
try:
lbound = datetime.datetime.min
ubound = datetime.datetime.max
offset = 1
if v.startswith('<'):
if v[offset] == '=':
offset += 1
ubound = dateparse(v[offset:].strip())
ubound += datetime.timedelta(microseconds=(offset - 1))
else: # v.startswith('>'):
if v[offset] == '=':
offset += 1
lbound = dateparse(v[offset:].strip())
lbound -= datetime.timedelta(microseconds=(offset - 1))
print_debug("lbound: {}\nubound: {}".format(lbound, ubound))
retarray = [s for s in [s2 for s2 in self.metadata_dict.keys() if k in self.metadata_dict[s2]["metadata"].keys()]
for val in self.metadata_dict[s]["metadata"][k]
if (dateparse(val) < ubound and dateparse(val) > lbound)]
except Exception as e:
print_error("Unable to process '{}' value '{}' (as datetime):\n{}".format(k, v, e), fatal=True)
else:
# handle everything else as a float
try:
lbound = float('-inf')
ubound = float('inf')
offset = 1
if v.startswith('<'):
if v[offset] == '=':
offset += 1
ubound = float(v[offset:].strip())
ubound += (float(offset) - 1.0)
else: # v.startswith('>'):
if v[offset] == '=':
offset += 1
lbound = float(v[offset:].strip())
lbound -= (float(offset) - 1.0)
print_debug("lbound: {}\nubound: {}".format(lbound, ubound))
retarray = [s for s in [s2 for s2 in self.metadata_dict.keys() if k in self.metadata_dict[s2]["metadata"].keys()]
for val in self.metadata_dict[s]["metadata"][k]
if (float(val) < float(ubound) and float(val) > float(lbound))]
except Exception as e:
print_error("Unable to process '{}' value '{}' (as float):\n{}".format(k, v, e), fatal=True)
elif k in ["msg_regex", "rule_regex"]:
# apply regex pattern to rule msg field
if not (v.startswith('/') or v.endswith('.') or v.endswith("/i")):
print_error("Bad {} pattern '{}' in filter string. Pattern must start with '/' and end with '/' or '/i'.".format(k, v), fatal=True)
re_flag = 0
re_v = v
if v.endswith('i'):
re_flag = re.I
re_v = v[:-1]
re_v = re_v.strip('/')
try:
pattern_re = re.compile(r"{}".format(re_v), flags=re_flag)
except Exception as e:
print_error("Unable to compile RegEx pattern '{}': {}".format(v, e), fatal=True)
try:
if k == "msg_regex":
retarray = [s for s in self.metadata_dict.keys() if pattern_re.search(self.metadata_dict[s]['msg'])]
else:
# match against raw rule
retarray = [s for s in self.metadata_dict.keys() if pattern_re.search(self.metadata_dict[s]['raw_rule'])]
except Exception as e:
print_error("Problem matching RegEx pattern '{}': {}".format(v, e), fatal=True)
else:
if k not in self.keys_dict.keys():
print_warning("metadata key '{}' not found in ruleset".format(k))
else:
# special keyword '<all>' means all values for that key
if v in ["<all>", "<any>"]:
retarray = [s for val in self.keys_dict[k].keys() for s in self.keys_dict[k][val]]
elif v not in self.keys_dict[k]:
print_warning("metadata key-value pair '{}' not found in ruleset".format(kvpair))
# retarray should stil be empty but in case not:
retarray = []
else:
retarray = [s for s in self.keys_dict[k][v]]
if negate:
# if key or value not found, this will be all rules
retarray = list(frozenset(self.get_all_sids()) - frozenset(retarray))
return list(set(retarray))