def test_multiple_qualifiers(): exp_and = stix2.AndBooleanExpression([stix2.EqualityComparisonExpression("network-traffic:dst_ref.type", "domain-name"), stix2.EqualityComparisonExpression("network-traffic:dst_ref.value", "example.com")]) exp_ob = stix2.ObservationExpression(exp_and) qual_rep = stix2.RepeatQualifier(5) qual_within = stix2.WithinQualifier(stix2.IntegerConstant(1800)) exp = stix2.QualifiedObservationExpression(stix2.QualifiedObservationExpression(exp_ob, qual_rep), qual_within) assert str(exp) == "[network-traffic:dst_ref.type = 'domain-name' AND network-traffic:dst_ref.value = 'example.com'] REPEATS 5 TIMES WITHIN 1800 SECONDS" # noqa
def test_hash_followed_by_registryKey_expression(): hash_exp = stix2.EqualityComparisonExpression("file:hashes.MD5", stix2.HashConstant("79054025255fb1a26e4bc422aef54eb4", "MD5")) o_exp1 = stix2.ObservationExpression(hash_exp) reg_exp = stix2.EqualityComparisonExpression(stix2.ObjectPath("windows-registry-key", ["key"]), stix2.StringConstant("HKEY_LOCAL_MACHINE\\foo\\bar")) o_exp2 = stix2.ObservationExpression(reg_exp) fb_exp = stix2.FollowedByObservationExpression([o_exp1, o_exp2]) para_exp = stix2.ParentheticalExpression(fb_exp) qual_exp = stix2.WithinQualifier(stix2.IntegerConstant(300)) exp = stix2.QualifiedObservationExpression(para_exp, qual_exp) assert str(exp) == "([file:hashes.MD5 = '79054025255fb1a26e4bc422aef54eb4'] FOLLOWEDBY [windows-registry-key:key = 'HKEY_LOCAL_MACHINE\\\\foo\\\\bar']) WITHIN 300 SECONDS" # noqa
def visitWithinQualifier(self, ctx): children = self.visitChildren(ctx) return stix2.WithinQualifier(children[1])
def test_invalid_within_qualifier(): with pytest.raises(ValueError): stix2.WithinQualifier('foo')
def test_invalid_within_qualifier(): with pytest.raises(ValueError) as excinfo: stix2.WithinQualifier('foo') assert 'is not a valid argument for a Within Qualifier' in str(excinfo)
def __generate_random_qualifier(self): """ Generate a random qualifier AST object. :return: The qualifier object """ qual_type = random.randrange(3) if qual_type == 0: repeat_count = random.randint(self.__config.min_repeat_count, self.__config.max_repeat_count) qualifier = stix2.RepeatQualifier(repeat_count) elif qual_type == 1: within_count = random.randint(self.__config.min_within_count, self.__config.max_within_count) qualifier = stix2.WithinQualifier(within_count) else: # Let's make the random timestamps near the current time # (within a year). dur1 = datetime.timedelta(microseconds=random.randrange( # 1 year 1000000 * 60 * 60 * 24 * 365)) dur2 = datetime.timedelta(microseconds=random.randrange( # 1 year 1000000 * 60 * 60 * 24 * 365)) if random.random() < 0.5: dur1 = -dur1 if random.random() < 0.5: dur2 = -dur2 now = datetime.datetime.utcnow() dt1 = now + dur1 dt2 = now + dur2 # Order them as start=dt1, stop=dt2 if dt1 > dt2: dt1, dt2 = dt2, dt1 elif dt1 == dt2: # in the remote chance we get the same timestamp for both, # just nudge one ahead... dt2 += datetime.timedelta(seconds=1) # STIX 2.0 requires string constants and millisecond precision # here... if self.__stix_version == "2.0": dt1_str = stix2.utils.format_datetime( stix2.utils.STIXdatetime(dt1, precision="millisecond")) dt1 = stix2.patterns.StringConstant(dt1_str) dt2_str = stix2.utils.format_datetime( stix2.utils.STIXdatetime(dt2, precision="millisecond")) dt2 = stix2.patterns.StringConstant(dt2_str) qualifier = stix2.StartStopQualifier(dt1, dt2) return qualifier