Skip to content

[Discuss] Elastic Security Indicator Match Rule tuning and optimizations #64746

@spong

Description

@spong

In Elastic Security 7.10 we're introducing a new Detection Engine Rule type called Indicator/Threat Matching (elastic/kibana#77395, elastic/kibana#78955), which will allow users to use the results from querying one index (threat index) to filter/query data in a second index (source index). This feature is being released as beta, and can be quite resource intensive, so the hope here is to get a better understanding of what we can do to optimize and tune our current algorithm/search strategy for optimal performance on the Elasticsearch side.

I'll try to keep the detections/security language to a minimum, but gist here is that every 5 minutes a search will be performed against the previous 5 minutes to see if a combination of fields from one index (threat index) exists in a second index (source index).

Input

The user configuration is essentially as follows:

Where users have the ability to specify any number of Source Indices, a Source Query, any number of Threat Indices, a Threat Query, and a Threat Mapping object, specifying the field mapping between the source and threat indices.

A sample configuration would look like the following:

{
  "concurrent_searches": 10,
  "items_per_search": 10,
  "index": ["auditbeat-*", "endgame-*", "filebeat-*", "logs-*", "packetbeat-*", "winlogbeat-*"],
  "name": "Indicator Match Concurrent Searches",
  "description": "Does 100 Concurrent searches with 10 items per search",
  "rule_id": "indicator_concurrent_search",
  "risk_score": 1,
  "severity": "high",
  "type": "threat_match",
  "query": "*:*",
  "tags": ["concurrent_searches_test", "from_script"],
  "threat_index": ["mock-threat-list-1"],
  "threat_language": "kuery",
  "threat_query": "*:*",
  "threat_mapping": [
    {
      "entries": [
        {
          "field": "source.port",
          "type": "mapping",
          "value": "source.port"
        },
        {
          "field": "source.ip",
          "type": "mapping",
          "value": "source.ip"
        },
        {
          "field": "host.name",
          "type": "mapping",
          "value": "host.name"
        },
      ]
    }
  ]
}

Search Strategy

We begin by querying the threat index and storing the results in memory within Kibana as we work our way through the list. Lists are batched into memory in buckets of 9000 documents at a time (a large threat list could be ~400k-600k documents).

Once the list is in memory, we use the above items_per_search and concurrent_searches settings to chunk the processing. For the above configuration, we'll create 10 queries, each with 10 threat items as filters, and then execute them all at once. Once all requests have returned, we check for results (which for the majority of the time will be 0), and continue searching through the next block of 100 items (10x10), pulling more into memory as needed, until we've searched for all items.

Sample query with `items_per_search:10`

{
  "bool": {
    "must": [],
    "filter": [
      {
        "match_all": {}
      },
      {
        "bool": {
          "should": [
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "host.name": "siem-windows"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.port": "443"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "host.name": "siem-kibana"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.port": "1"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  },
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.ip": "127.0.0.1"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.port": "2"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  },
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.ip": "127.0.0.1"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.port": "3"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  },
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.ip": "127.0.0.1"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.port": "4"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  },
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.ip": "127.0.0.1"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.port": "5"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  },
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.ip": "127.0.0.1"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.port": "6"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  },
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.ip": "127.0.0.1"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            },
            {
              "bool": {
                "should": [
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.port": "7"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  },
                  {
                    "bool": {
                      "filter": [
                        {
                          "bool": {
                            "should": [
                              {
                                "match": {
                                  "source.ip": "127.0.0.1"
                                }
                              }
                            ],
                            "minimum_should_match": 1
                          }
                        }
                      ]
                    }
                  }
                ],
                "minimum_should_match": 1
              }
            }
    ],
    "should": [],
    "must_not": []
  }
}

Tuning/Optimizations

With the above algorithm, our open questions mostly lie around the usefulness of batching like this, and if smaller batches of filters or one large batch per query would prove optimal (or if it really just depends on the data set, cluster configuration, etc). This feature is intended to be used with CCS.

Also of question is if there is anything we can do to better leverage caching with regards to the time windows we're querying. As it stands, a daterange filter is constructed (below) with to/from being calculated at query-time, so not static between queries (the result of some other upstream logic we'll need to address).

Daterange filter:

{
  "bool": {
    "filter": [
      {
        "bool": {
          "should": [
            {
              "range": {
                "@timestamp": {
                  "gte": from,
                  "format": "strict_date_optional_time"
                }
              }
            }
          ],
          "minimum_should_match": 1
        }
      },
      {
        "bool": {
          "should": [
            {
              "range": {
                "@timestamp": {
                  "lte": to,
                  "format": "strict_date_optional_time"
                }
              }
            }
          ],
          "minimum_should_match": 1
        }
      }
    ]
  }
}

Hopefully this is enough information to provide an idea of what we're doing here, and please do let me know if I can clarify any aspect of the above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    :Search/SearchSearch-related issues that do not fall into other categoriesTeam:SearchMeta label for search team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions