Use DEFAULT_VERSION in create_pattern_object()

master
Chris Lenk 2020-04-03 10:45:36 -04:00
parent 1a2b1367cf
commit e730d45d44
3 changed files with 36 additions and 24 deletions

View File

@ -14,6 +14,8 @@ from stix2patterns.v21.grammars.STIXPatternVisitor import \
STIXPatternVisitor as STIXPatternVisitor21 STIXPatternVisitor as STIXPatternVisitor21
from stix2patterns.v21.pattern import Pattern as Pattern21 from stix2patterns.v21.pattern import Pattern as Pattern21
import stix2
from .patterns import * from .patterns import *
from .patterns import _BooleanExpression from .patterns import _BooleanExpression
@ -336,7 +338,7 @@ class STIXPatternVisitorForSTIX21(STIXPatternVisitorForSTIX2, STIXPatternVisitor
super(STIXPatternVisitor21, self).__init__() super(STIXPatternVisitor21, self).__init__()
class STIXPatternVisitorForSTIX20(STIXPatternVisitor20, STIXPatternVisitorForSTIX2): class STIXPatternVisitorForSTIX20(STIXPatternVisitorForSTIX2, STIXPatternVisitor20):
classes = {} classes = {}
def __init__(self, module_suffix, module_name): def __init__(self, module_suffix, module_name):
@ -352,11 +354,18 @@ class STIXPatternVisitorForSTIX20(STIXPatternVisitor20, STIXPatternVisitorForSTI
super(STIXPatternVisitor20, self).__init__() super(STIXPatternVisitor20, self).__init__()
def create_pattern_object(pattern, module_suffix="", module_name="", version="2.1"): def create_pattern_object(pattern, module_suffix="", module_name="", version=stix2.DEFAULT_VERSION):
""" """
Create a STIX pattern AST from a pattern string. Create a STIX pattern AST from a pattern string.
""" """
pattern_obj = Pattern21(pattern) if version == "2.1" else Pattern20(pattern) if version == "2.1":
builder = STIXPatternVisitorForSTIX21(module_suffix, module_name) if version == "2.1" else STIXPatternVisitorForSTIX20(module_suffix, module_name) pattern_class = Pattern21
visitor_class = STIXPatternVisitorForSTIX21
else:
pattern_class = Pattern20
visitor_class = STIXPatternVisitorForSTIX20
pattern_obj = pattern_class(pattern)
builder = visitor_class(module_suffix, module_name)
return pattern_obj.visit(builder) return pattern_obj.visit(builder)

View File

@ -494,13 +494,14 @@ def test_make_constant_already_a_constant():
def test_parsing_comparison_expression(): def test_parsing_comparison_expression():
patt_obj = create_pattern_object("[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']") patt_obj = create_pattern_object("[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']", version="2.0")
assert str(patt_obj) == "[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']" assert str(patt_obj) == "[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']"
def test_parsing_qualified_expression(): def test_parsing_qualified_expression():
patt_obj = create_pattern_object( patt_obj = create_pattern_object(
"[network-traffic:dst_ref.type = 'domain-name' AND network-traffic:dst_ref.value = 'example.com'] REPEATS 5 TIMES WITHIN 1800 SECONDS", "[network-traffic:dst_ref.type = 'domain-name' AND network-traffic:dst_ref.value = 'example.com'] REPEATS 5 TIMES WITHIN 1800 SECONDS",
version="2.0",
) )
assert str( assert str(
patt_obj, patt_obj,
@ -508,5 +509,5 @@ def test_parsing_qualified_expression():
def test_list_constant(): def test_list_constant():
patt_obj = create_pattern_object("[network-traffic:src_ref.value IN ('10.0.0.0', '10.0.0.1', '10.0.0.2')]") patt_obj = create_pattern_object("[network-traffic:src_ref.value IN ('10.0.0.0', '10.0.0.1', '10.0.0.2')]", version="2.0")
assert str(patt_obj) == "[network-traffic:src_ref.value IN ('10.0.0.0', '10.0.0.1', '10.0.0.2')]" assert str(patt_obj) == "[network-traffic:src_ref.value IN ('10.0.0.0', '10.0.0.1', '10.0.0.2')]"

View File

@ -176,7 +176,7 @@ def test_greater_than():
def test_parsing_greater_than(): def test_parsing_greater_than():
patt_obj = create_pattern_object("[file:extensions.'windows-pebinary-ext'.sections[*].entropy > 7.478901]") patt_obj = create_pattern_object("[file:extensions.'windows-pebinary-ext'.sections[*].entropy > 7.478901]", version="2.1")
assert str(patt_obj) == "[file:extensions.'windows-pebinary-ext'.sections[*].entropy > 7.478901]" assert str(patt_obj) == "[file:extensions.'windows-pebinary-ext'.sections[*].entropy > 7.478901]"
@ -186,7 +186,7 @@ def test_less_than():
def test_parsing_less_than(): def test_parsing_less_than():
patt_obj = create_pattern_object("[file:size < 1024]") patt_obj = create_pattern_object("[file:size < 1024]", version="2.1")
assert str(patt_obj) == "[file:size < 1024]" assert str(patt_obj) == "[file:size < 1024]"
@ -199,7 +199,7 @@ def test_greater_than_or_equal():
def test_parsing_greater_than_or_equal(): def test_parsing_greater_than_or_equal():
patt_obj = create_pattern_object("[file:size >= 1024]") patt_obj = create_pattern_object("[file:size >= 1024]", version="2.1")
assert str(patt_obj) == "[file:size >= 1024]" assert str(patt_obj) == "[file:size >= 1024]"
@ -212,32 +212,32 @@ def test_less_than_or_equal():
def test_parsing_less_than_or_equal(): def test_parsing_less_than_or_equal():
patt_obj = create_pattern_object("[file:size <= 1024]") patt_obj = create_pattern_object("[file:size <= 1024]", version="2.1")
assert str(patt_obj) == "[file:size <= 1024]" assert str(patt_obj) == "[file:size <= 1024]"
def test_parsing_issubset(): def test_parsing_issubset():
patt_obj = create_pattern_object("[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']") patt_obj = create_pattern_object("[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']", version="2.1")
assert str(patt_obj) == "[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']" assert str(patt_obj) == "[network-traffic:dst_ref.value ISSUBSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']"
def test_parsing_issuperset(): def test_parsing_issuperset():
patt_obj = create_pattern_object("[network-traffic:dst_ref.value ISSUPERSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']") patt_obj = create_pattern_object("[network-traffic:dst_ref.value ISSUPERSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']", version="2.1")
assert str(patt_obj) == "[network-traffic:dst_ref.value ISSUPERSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']" assert str(patt_obj) == "[network-traffic:dst_ref.value ISSUPERSET '2001:0db8:dead:beef:0000:0000:0000:0000/64']"
def test_parsing_like(): def test_parsing_like():
patt_obj = create_pattern_object("[directory:path LIKE 'C:\\\\Windows\\\\%\\\\foo']") patt_obj = create_pattern_object("[directory:path LIKE 'C:\\\\Windows\\\\%\\\\foo']", version="2.1")
assert str(patt_obj) == "[directory:path LIKE 'C:\\\\Windows\\\\%\\\\foo']" assert str(patt_obj) == "[directory:path LIKE 'C:\\\\Windows\\\\%\\\\foo']"
def test_parsing_match(): def test_parsing_match():
patt_obj = create_pattern_object("[process:command_line MATCHES '^.+>-add GlobalSign.cer -c -s -r localMachine Root$'] FOLLOWEDBY [process:command_line MATCHES '^.+>-add GlobalSign.cer -c -s -r localMachineTrustedPublisher$'] WITHIN 300 SECONDS") # noqa patt_obj = create_pattern_object("[process:command_line MATCHES '^.+>-add GlobalSign.cer -c -s -r localMachine Root$'] FOLLOWEDBY [process:command_line MATCHES '^.+>-add GlobalSign.cer -c -s -r localMachineTrustedPublisher$'] WITHIN 300 SECONDS", version="2.1") # noqa
assert str(patt_obj) == "[process:command_line MATCHES '^.+>-add GlobalSign.cer -c -s -r localMachine Root$'] FOLLOWEDBY [process:command_line MATCHES '^.+>-add GlobalSign.cer -c -s -r localMachineTrustedPublisher$'] WITHIN 300 SECONDS" # noqa assert str(patt_obj) == "[process:command_line MATCHES '^.+>-add GlobalSign.cer -c -s -r localMachine Root$'] FOLLOWEDBY [process:command_line MATCHES '^.+>-add GlobalSign.cer -c -s -r localMachineTrustedPublisher$'] WITHIN 300 SECONDS" # noqa
def test_parsing_followed_by(): def test_parsing_followed_by():
patt_obj = create_pattern_object("([file:hashes.MD5 = '79054025255fb1a26e4bc422aef54eb4'] FOLLOWEDBY [windows-registry-key:key = 'HKEY_LOCAL_MACHINE\\\\foo\\\\bar']) WITHIN 300 SECONDS") # noqa patt_obj = create_pattern_object("([file:hashes.MD5 = '79054025255fb1a26e4bc422aef54eb4'] FOLLOWEDBY [windows-registry-key:key = 'HKEY_LOCAL_MACHINE\\\\foo\\\\bar']) WITHIN 300 SECONDS", version="2.1") # noqa
assert str(patt_obj) == "([file:hashes.MD5 = '79054025255fb1a26e4bc422aef54eb4'] FOLLOWEDBY [windows-registry-key:key = 'HKEY_LOCAL_MACHINE\\\\foo\\\\bar']) WITHIN 300 SECONDS" # noqa assert str(patt_obj) == "([file:hashes.MD5 = '79054025255fb1a26e4bc422aef54eb4'] FOLLOWEDBY [windows-registry-key:key = 'HKEY_LOCAL_MACHINE\\\\foo\\\\bar']) WITHIN 300 SECONDS" # noqa
@ -302,7 +302,7 @@ def test_and_observable_expression():
def test_parsing_and_observable_expression(): def test_parsing_and_observable_expression():
exp = create_pattern_object("[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul']") # noqa exp = create_pattern_object("[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul']", version="2.1") # noqa
assert str(exp) == "[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul']" # noqa assert str(exp) == "[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] AND [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul']" # noqa
@ -358,7 +358,7 @@ def test_or_observable_expression():
def test_parsing_or_observable_expression(): def test_parsing_or_observable_expression():
exp = create_pattern_object("[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] OR [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul']") # noqa exp = create_pattern_object("[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] OR [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul']", version="2.1") # noqa
assert str(exp) == "[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] OR [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul']" # noqa assert str(exp) == "[user-account:account_type = 'unix' AND user-account:user_id = '1007' AND user-account:account_login = 'Peter'] OR [user-account:account_type = 'unix' AND user-account:user_id = '1008' AND user-account:account_login = 'Paul']" # noqa
@ -392,7 +392,7 @@ def test_hex():
def test_parsing_hex(): def test_parsing_hex():
patt_obj = create_pattern_object("[file:magic_number_hex = h'ffd8']") patt_obj = create_pattern_object("[file:magic_number_hex = h'ffd8']", version="2.1")
assert str(patt_obj) == "[file:magic_number_hex = h'ffd8']" assert str(patt_obj) == "[file:magic_number_hex = h'ffd8']"
@ -445,7 +445,7 @@ def test_binary():
def test_parsing_binary(): def test_parsing_binary():
patt_obj = create_pattern_object("[artifact:payload_bin = b'dGhpcyBpcyBhIHRlc3Q=']") patt_obj = create_pattern_object("[artifact:payload_bin = b'dGhpcyBpcyBhIHRlc3Q=']", version="2.1")
assert str(patt_obj) == "[artifact:payload_bin = b'dGhpcyBpcyBhIHRlc3Q=']" assert str(patt_obj) == "[artifact:payload_bin = b'dGhpcyBpcyBhIHRlc3Q=']"
@ -610,13 +610,14 @@ def test_make_constant_already_a_constant():
def test_parsing_comparison_expression(): def test_parsing_comparison_expression():
patt_obj = create_pattern_object("[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']") patt_obj = create_pattern_object("[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']", version="2.1")
assert str(patt_obj) == "[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']" assert str(patt_obj) == "[file:hashes.'SHA-256' = 'aec070645fe53ee3b3763059376134f058cc337247c978add178b6ccdfb0019f']"
def test_parsing_repeat_and_within_qualified_expression(): def test_parsing_repeat_and_within_qualified_expression():
patt_obj = create_pattern_object( patt_obj = create_pattern_object(
"[network-traffic:dst_ref.type = 'domain-name' AND network-traffic:dst_ref.value = 'example.com'] REPEATS 5 TIMES WITHIN 1800 SECONDS", "[network-traffic:dst_ref.type = 'domain-name' AND network-traffic:dst_ref.value = 'example.com'] REPEATS 5 TIMES WITHIN 1800 SECONDS",
version="2.1",
) )
assert str( assert str(
patt_obj, patt_obj,
@ -626,6 +627,7 @@ def test_parsing_repeat_and_within_qualified_expression():
def test_parsing_start_stop_qualified_expression(): def test_parsing_start_stop_qualified_expression():
patt_obj = create_pattern_object( patt_obj = create_pattern_object(
"[network-traffic:dst_ref.type = 'domain-name' AND network-traffic:dst_ref.value = 'example.com'] START t'2016-06-01T00:00:00Z' STOP t'2017-03-12T08:30:00Z'", # noqa "[network-traffic:dst_ref.type = 'domain-name' AND network-traffic:dst_ref.value = 'example.com'] START t'2016-06-01T00:00:00Z' STOP t'2017-03-12T08:30:00Z'", # noqa
version="2.1",
) )
assert str( assert str(
patt_obj, patt_obj,
@ -633,20 +635,20 @@ def test_parsing_start_stop_qualified_expression():
def test_list_constant(): def test_list_constant():
patt_obj = create_pattern_object("[network-traffic:src_ref.value IN ('10.0.0.0', '10.0.0.1', '10.0.0.2')]") patt_obj = create_pattern_object("[network-traffic:src_ref.value IN ('10.0.0.0', '10.0.0.1', '10.0.0.2')]", version="2.1")
assert str(patt_obj) == "[network-traffic:src_ref.value IN ('10.0.0.0', '10.0.0.1', '10.0.0.2')]" assert str(patt_obj) == "[network-traffic:src_ref.value IN ('10.0.0.0', '10.0.0.1', '10.0.0.2')]"
def test_parsing_boolean(): def test_parsing_boolean():
patt_obj = create_pattern_object("[network-traffic:is_active = true]") patt_obj = create_pattern_object("[network-traffic:is_active = true]", version="2.1")
assert str(patt_obj) == "[network-traffic:is_active = true]" assert str(patt_obj) == "[network-traffic:is_active = true]"
def test_parsing_multiple_slashes_quotes(): def test_parsing_multiple_slashes_quotes():
patt_obj = create_pattern_object("[ file:name = 'weird_name\\'' ]") patt_obj = create_pattern_object("[ file:name = 'weird_name\\'' ]", version="2.1")
assert str(patt_obj) == "[file:name = 'weird_name\\'']" assert str(patt_obj) == "[file:name = 'weird_name\\'']"
def test_parse_error(): def test_parse_error():
with pytest.raises(ParseException): with pytest.raises(ParseException):
create_pattern_object("[ file: name = 'weirdname]") create_pattern_object("[ file: name = 'weirdname]", version="2.1")