-
Notifications
You must be signed in to change notification settings - Fork 566
[Bug] Query validation failing to capture InSet edge case with ip field types #3540
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
does elasticsearch (or endpoint) support |
@brokensound77 Here's the original thread which I forgot to add. Elasticsearch supports IP_TYPE. Believe the actual is just that the types of the key:value need to match. all IP_TYPE or all keywords etc. |
Speaking with @brokensound77 lets try to create an |
As an alternative to subclassing and overriding all the methods from eql, we could monkey patch the in_set function where the original patch suggestions existed. Here's an example: in_set Patch
diff --git a/detection_rules/rule_validators.py b/detection_rules/rule_validators.py
index 6631db83e..61a785a81 100644
--- a/detection_rules/rule_validators.py
+++ b/detection_rules/rule_validators.py
@@ -4,7 +4,7 @@
# 2.0.
"""Validation logic for rules containing queries."""
-from functools import cached_property
+from functools import cached_property, wraps
from typing import List, Optional, Tuple, Union
import eql
@@ -21,6 +21,9 @@ from .rule import (EQLRuleData, QueryRuleData, QueryValidator, RuleMeta,
TOMLRuleContents, set_eql_config)
from .schemas import get_stack_schemas
+from eql.parser import _parse as base_parse, LarkToEQL, NodeInfo, TypeHint
+from eql import ast
+
EQL_ERROR_TYPES = Union[eql.EqlCompileError,
eql.EqlError,
eql.EqlParseError,
@@ -31,6 +34,42 @@ EQL_ERROR_TYPES = Union[eql.EqlCompileError,
KQL_ERROR_TYPES = Union[kql.KqlCompileError, kql.KqlParseError]
+BaseInSetMethod = LarkToEQL.in_set # preserve the original method for later use
+
+def custom_in_set(self, node):
+ """Override and address the limitations of the eql in_set method."""
+ print("custom_in_set")
+ # return BaseInSetMethod(self, node)
+ outer, container = self.visit(node.child_trees) # type: (NodeInfo, list[NodeInfo])
+
+ if not outer.validate_type(TypeHint.primitives()):
+ # can't compare non-primitives to sets
+ raise self._type_error(outer, TypeHint.primitives())
+
+ # Check that everything inside the container has the same type as outside
+ error_message = "Unable to compare {expected_type} to {actual_type}"
+ for inner in container:
+ if not inner.validate_type(outer):
+ raise self._type_error(inner, outer, error_message)
+
+ # This will always evaluate to true/false, so it should be a boolean
+ term = ast.InSet(outer.node, [c.node for c in container])
+ nullable = outer.nullable or any(c.nullable for c in container)
+ return NodeInfo(term, TypeHint.Boolean, nullable=nullable, source=node)
+
+def custom_base_parse_decorator(func):
+ """Override and address the limitations of the eql in_set method."""
+ @wraps(func)
+ def wrapper(query, start=None, **kwargs):
+ LarkToEQL.in_set = custom_in_set
+ print("custom_base_parse_decorator")
+ result = func(query, start=start, **kwargs)
+ LarkToEQL.in_set = BaseInSetMethod
+ return result
+ return wrapper
+
+eql.parser._parse = custom_base_parse_decorator(base_parse)
+
class KQLValidator(QueryValidator):
"""Specific fields for KQL query event types."""
This is much smaller of a change. Note: There are still other things to do:
|
Uh oh!
There was an error while loading. Please reload this page.
Summary
Related to #3534
When ip fields are used with in_set fields that are type
keyword
, failures occur in elasticsearch.For example:
network where destination.address in ("127.0.0.1", "::1")
Our internal validation does not catch this.
The validation issue is a combination of two things:
ip
fields are internally set toString
here within detection-rulesAfter fixing those two small updates, we then would run into issues where all ip types can not be compared to type string, which should not occur. Rather the edge case is that the combination of the
in
operation with mismatched types needs to be handled, most likely indef in_sets
, which later performs validation in validate_type.The dilemma is that If we set correct the type hint for
ip
fields, the validation we fail as expected forin_set
checks, however by field type hint information is already set and will also fail in other locations where this check is relaxed and allows ip / string type comparisons. On the other hand, if we leave type hints as-is, and try to cover this edge case withinin_set
, the type hint is alreadyNote: ATM, the only occurance of this within our repos was resolved in 3534.
Note: I observed there are some integrations where fields like
destination.ip
are typekeyword
and some are typeip
. Look at the integrations-schemas zip to see examples. They are all typeip
in the network integration.Note: To get the error to finally bubble up, we also need to make sure calls to
elasticsearch_type_family
in integrations doesn't auto convert the type ofip
fields tokeyword
.Additional Details
The proposed solution is to do two things:
ip
's tokeywords
.ip
. Then use the ip type_hint to validate the fields within the in_set.kql_schema
to justschema
I've attached git diff's to help with the implementation.
Detection Rules Git Diff
EQL Git Diff
The text was updated successfully, but these errors were encountered: