Aaron Jewitt

Automatización de solicitudes de ajuste de detección con casos Kibana

Aprende cómo automatizar solicitudes de ajuste de reglas de detección en Elastic Security. Esta guía muestra cómo agregar campos personalizados a los Casos, crear una regla para detectar necesidades de ajuste y usar un webhook para crear un bucle de retroalimentación sin fricción entre analistas e ingenieros de detección.

20 min de lecturaHabilitación
Automatización de solicitudes de ajuste de detección con casos Kibana

Automatización de solicitudes de ajuste de detección con seguridad elástica

En Elastic, el equipo de Infosec es el "Cliente Cero". Empleamos extensamente la versión más reciente de los productos de Elastic para proteger nuestra organización, lo que nos ofrece perspectivas únicas sobre cómo resolver los retos reales de seguridad. Una de las formas en que mejoramos la eficiencia del Centro de Operaciones de Seguridad (SOC) es creando un flujo de trabajo automatizado y fluido que permite a nuestros analistas abrir una solicitud de ajuste de detección directamente desde Kibana Cases con un solo clic.

En cualquier SOC, el bucle de retroalimentación entre analistas de seguridad e ingenieros de detección es crucial para mantener una postura de seguridad saludable y eficaz. Los analistas en primera línea son los primeros en ver cómo funcionan las reglas de detección en el mundo real. Saben qué alertas son valiosas, cuáles ruidosas y cuáles podrían mejorar con un poco de ajuste. La fatiga de alertas por alertas ruidosas aumenta el riesgo de pasar por alto una alerta positiva verdadera. Ajustar rápidamente los falsos positivos es fundamental para responder a los positivos verdaderos . Capturar este feedback de alerta de forma eficiente puede ser un desafío: los procesos manuales, como enviar emails, abrir tiquetes o mensajes directos, pueden ser inconsistentes, llevar mucho tiempo y ser difíciles de seguir.

Con Elastic Security, un analista puede anexar alertas a un caso nuevo o existente en Kibana, realizar su investigación y, con algo de personalización y automatización, puede iniciar una solicitud de ajuste con un solo clic directamente desde Kibana Cases. Este artículo te guiará por cómo construimos esta automatización y cómo puedes implementar un sistema similar para cerrar el bucle de retroalimentación y optimizar tu programa de detección y respuesta.

Campos personalizados en los casos Kibana

Los campos personalizados son un componente clave de esta automatización dentro de los Casos Kibana. Empleando estos campos personalizados, podemos capturar la información necesaria directamente de la herramienta que ya están empleando los analistas. Estos campos personalizados aparecerán en todos los casos nuevos y existentes, proporcionando una forma clara y coherente para que los analistas marquen una detección para su revisión.

Nota: La capacidad de agregar campos personalizados a los casos se introdujo en la versión 8.15. Para más detalles, consulte la documentación oficial de los casos.

Cada Caso Kibana es un documento almacenado en un índice dedicado de Elasticsearch: .kibana_alerting_cases. Esto significa que todos tus datos de casos están disponibles para consultas, agregación y automatización, igual que cualquier otra fuente de datos en Elastic. Cada documento de caso contiene una gran cantidad de información, pero algunos campos son especialmente útiles para métricas y automatización. El campo cases.status rastrea si un caso está abierto, en curso o cerrado, mientras que cases.created_at y cases.updated_at proporcionan marcas de tiempo cruciales para calcular métricas como el Tiempo Medio hasta la Resolución (MTTR). Campos como cases.severity y cases.owner te permiten analizar tus métricas para ver cómo está rindiendo el equipo. Lo más importante para este blog es que el objeto cases.custom_fields contiene un array de los campos personalizados que configuraste. Los campos de ejecución pueden usar para analizar el array de campos personalizados, permitiéndote crear consultas, paneles, visualizaciones y reglas de detección que activan flujos de trabajo.

Más allá de las solicitudes de ajuste, los campos personalizados son increíblemente versátiles para rastrear métricas y enriquecer casos. Por ejemplo, tenemos un campo personalizado llamado "Caso Complejo" para marcar casos que tardan más de una hora en resolver, ayudándonos a identificar reglas que pueden necesitar mejores guías de investigación o automatización para reducir el tiempo de investigación. También empleamos campos personalizados como "Detección de reglas válidas" y "Alerta de Verdadero Positivo" para recopilar retroalimentación detallada sobre el rendimiento y la fidelidad de las reglas, lo que nos permite crear paneles poderosos en Kibana para visualizar la efectividad operativa de nuestro SOC.

Si aún no creaste una vista de datos para la información de los casos, tendrás que hacerlo si quieres usar campos de ejecución y visualizaciones de datos con tus casos.

Navegar a patrones de índice: En Kibana, ve a Stack Management > Vistas de datos y haz clic en 'crear nueva vista de datos'.

Configura la vista de datos para que mapee el índice .kibana_alerting_cases sistema. Tendrás que hacer clic en el botón Permitir oculto y en los índices del sistema para permitir esto. Para el campo de marca de tiempo recomiendo usar el campo cases.updated_at para que los casos se muestren con la actividad más reciente.

Creación de campos personalizados

Existen dos tipos de campos personalizados; Text campos para entrada libre, o campos Toggle para retroalimentación simple de sí/no. Para nuestra automatización de Solicitudes de Ajuste, usamos una de cada una. El campo de texto es opcional para capturar cualquier retroalimentación adicional del analista, y el campo de alternancia se emplea para activar la automatización.

En Kibana, ve a Seguridad > Casos y luego haz clic en Configuración en la esquina superior derecha. En la página de configuración verás una sección de Campos Personalizados donde puedes agregar los nuevos campos que quieras. Los campos se muestran en la interfaz de los casos en orden alfabético, así que prefijamos nuestros campos con números para mantenerlos en el orden que queremos.

Puedes crear los nuevos campos personalizados, las etiquetas agregadas en la interfaz son solo para los analistas y no se almacenan en el índice de casos. Pueden tener cualquier valor que quieras.

Agregar campos personalizados: Necesitamos dos campos para este flujo de trabajo.

  • Campo 1: Ajuste necesario
    • Este será el botón que los analistas hagan clic para iniciar una solicitud de ajuste.

      • Etiqueta: Open tuning request?
      • Tipo: Alternar
      • Valor por defecto: Apagado
    • Campo 2: Detalles de la solicitud de afinación

      • Este campo permite al analista proporcionar detalles específicos sobre lo que debe cambiar, como agregar una excepción, reducir la severidad o ajustar la lógica de consulta.
      • Name: Tuning request detail
      • Tipo: Mensaje de texto
    • Valor por defecto: Apagado

Uso de campos de ejecución para mapear los campos personalizados

Un reto al trabajar con campos personalizados en los Casos Kibana es que el campo cases.custom_fields se mapea como un array de objetos, donde cada objeto representa un campo personalizado con su nombre y valor. Esta estructura dificulta consultar campos personalizados específicos directamente en KQL. Por ejemplo, no puedes simplemente usar una consulta como cases.custom_fields.open_tuning_request : "true". Para superar esto, podemos usar campos de ejecución para analizar y consultar los campos personalizados.

Los campos de ejecución son campos que se evalúan en el momento de la consulta. Te permiten crear nuevos campos sobre la marcha sin tener que reindexar tus datos. Podemos definir campos de ejecución en el índice de .kibana_alerting_cases para usar un script sencillo y analizar el cases.custom_fields array y extraer los valores que necesitamos en nuevos campos fácilmente consultables.

Para este flujo de trabajo, crearemos dos campos de ejecución que se asignarán a los campos personalizados creados anteriormente:
* TuningRequired: Un campo booleano que se true si el interruptor "Abrir solicitud de sintonización" está activado.
* TuningDetail: Un campo de texto que contendrá los comentarios del analista desde el campo "Detalle de solicitud de ajuste".

Antes de poder crear los campos de ejecución, primero necesitamos identificar el ID único (key) que Kibana asigna a cada campo personalizado. Actualmente, no hay una forma sencilla de ver este ID en la interfaz. Para encontrarlo, empleamos la siguiente solución alternativa:

  1. Crea los campos. Si usas otros campos personalizados, deberías crear los campos personalizados uno a uno para facilitar la identificación de las nuevas claves de campo. Si solo tienes los dos campos mencionados arriba, puedes distinguirlos usando el valor type , que puede ser texto o alternar.
  2. Crea un caso nuevo. Luego de agregar el campo, creamos un caso de prueba en Kibana y agregamos algunos datos al campo de descripción y cambiamos el campo de ajuste requerido a verdadero con todos los demás campos personalizados en falso o en blanco.
  3. Revisa el documento del caso. Luego navegamos hasta Discover y consultamos el índice de .kibana_alerting_cases para encontrar el documento del nuevo caso. Al inspeccionar el array de cases.customFields en la fuente del documento, pudimos encontrar el key asociado a nuestro nuevo campo personalizado. Almacena los valores de los campos de key que se usarán en los scripts de ejecución.

Los datos cases.customFields están formateados de la siguiente manera:

  [
    {
      "key": "4537b921-3ca4-4ff0-aa39-02dd6a3177bd",
      "type": "text",
      "value": "This alert is too noisy"
    },
    {
      "key": "cdf28896-c793-43d2-9384-99562e23a646",
      "type": "toggle",
      "value": true
    }
  ]

Creación de los campos de ejecución

Puedes agregar campos de ejecución a través de la interfaz de Kibana o usando la API Elasticsearch en la consola Dev Tools. Si aún no creaste una vista de datos para la información de los casos, tendrás que hacerlo primero.

Al ver la nueva vista de datos de Kibana Cases, haz clic en el botón 'Agregar campo' para abrir el menú desplegable y crear un nuevo campo de tiempo de ejecución.

Introduce el nombre del campo, en este ejemplo estamos configurando TuningRequired como un nuevo tipo de campo booleano. Haz clic en el botón 'Establecer valor' para configurarlo como un nuevo campo de Tiempo de Ejecución configurado mediante un script sencillo. Actualiza este script sencillo para reemplazar TUNING_REQUIRED_FIELD_KEY_UUID por el valor key del campo personalizado Ajuste Requerido y pégalo en el campo de valor y almacena el nuevo campo de ejecución.

...
    if (params._source.containsKey('cases') &&
    params._source.cases != null &&
    params._source.cases.containsKey('customFields') &&
    params._source.cases.customFields != null) 
{
  for (def cf : params._source.cases.customFields) {
    if (cf != null &&
        cf.containsKey('key') &&
        cf.key != null &&
        cf.key.contains('TUNING_REQUIRED_FIELD_KEY_UUID') &&
        cf.containsKey('value') &&
        cf.value != null) {
      emit(cf.value);
      break;
    }
  }
}

Repite este proceso para el campo TuningDetail , recuerda usar el valor key del campo de texto en la escritura sencilla de este campo. Si tienes campos personalizados adicionales en tus casos que quieras usar para paneles o métricas, también puedes mapearlos con este mismo proceso.

Si controlas la configuración de tu clúster y las vistas de datos 'como código', también puedes agregar campos de ejecución a un mapeo índice usando la API de mapeo Update de la consola Kibana Dev Tools.

Automatización de la creación de solicitudes de ajuste

Podemos activar esta automatización de dos maneras: mediante una regla de detección personalizada (que crea una nueva alerta y la envía a un conector cuando un caso se actualice con una solicitud de ajuste) o mediante una automatización externa programada que consulta la API.

Esta automatización puede crear empleando cualquier plataforma de automatización como Tines, Github Actions o scripts personalizados. Esta es la lógica que usamos para nuestra automatización:

Paso 1: Encuentra cualquier caso recientemente etiquetado como TuningRequired

Puedes usar esta consulta elasticsearch para encontrar cualquier caso que se actualizó en la última hora donde el campo TuningRequired se configuró como true. Esta consulta emplea el campo cases.updated_at como rango de tiempo. Los mapeos de campos en tiempo de ejecución deben incluir en la solicitud de la API para consultar los campos personalizados.

Esta consulta devolverá todos los documentos del caso del índice de .kibana_alerting_cases que se actualizaron en la última hora y el campo TuningRequired se configuró en true

POST /.kibana_alerting_cases/_search  
{  
  "query": {  
    "bool": {  
      "must": [],  
      "filter": [  
        {  
          "bool": {  
            "should": [  
              {  
                "match": {  
                  "TuningRequired": true  
                }  
              }  
            ],  
            "minimum_should_match": 1  
          }  
        },  
        {  
          "range": {  
            "cases.updated_at": {  
              "format": "strict_date_optional_time",  
              "gte": "now-1h",  
              "lte": "now"  
            }  
          }  
        }  
      ],  
      "should": [],  
      "must_not": []  
    }  
  },  
 "runtime_mappings": {  
   "TuningDetail": {  
     "type": "keyword",  
     "script": {  
       "source": "if (\nparams._source.containsKey('cases') &&\nparams._source.cases != null &&\nparams._source.cases.containsKey('customFields') &&\nparams._source.cases.customFields != null\n) {\nfor (def cf : params._source.cases.customFields) {\nif (\ncf != null &&\ncf.containsKey('key') &&\ncf.key != null &&\ncf.key.contains('6cadc70a-7d68-4531-9861-7d5bc24c4c1c') &&\ncf.containsKey('value') &&\ncf.value != null\n) {\nemit(cf.value);\nbreak;\n}\n}\n}"  
     }  
   },  
   "TuningRequired": {  
     "type": "boolean",  
     "script": {  
       "source": "if (\nparams._source.containsKey('cases') &&\nparams._source.cases != null &&\nparams._source.cases.containsKey('customFields') &&\nparams._source.cases.customFields != null\n) {\nfor (def cf : params._source.cases.customFields) {\nif (\ncf != null &&\ncf.containsKey('key') &&\ncf.key != null &&\ncf.key.contains('496e71f2-2bce-47a2-93a8-00db0de2d1b4') &&\ncf.containsKey('value') &&\ncf.value != null\n) {\nemit(cf.value);\nbreak;\n}\n}\n}"  
     }  
   }  
 },  
  "fields": [  
    "TuningDetail",  
    "TuningRequired"  
  ]  
}

Cada vez que se cambia un campo o se hace un comentario en una funda, el campo de updated_at se actualizará a la hora actual. Como cualquier actualización o comentario agregado a un caso actualizará esta marca de tiempo, es posible que un único caso sea devuelvo varias veces por esta automatización si se ejecuta de manera regular mientras el caso se actualiza. Cualquier proceso de automatización empleado para esto debería tener un proceso de deduplicación para evitar procesar el mismo caso varias veces en este escenario.

Paso 2: Analizar cada caso

Repasa cada uno de los casos devueltos por la consulta anterior para procesarlos uno a uno. Cada documento devuelto contendrá el fields array con los valores de los campos personalizados, así como otros campos útiles. Analiza cada uno de los siguientes campos y almacénalos para su uso futuro:

  • El campo _id tendrá un formato como cases:{{case_ID}}. El ID del caso se emplea para futuras solicitudes API en la automatización para agregar comentarios al caso o recuperar todas las alertas adjuntas al caso.
  • cases.title es el título del caso
  • cases.assignees es a quien se asigna el caso
  • cases.updated_by es la última persona en actualizar el caso, a menudo es quien envía la solicitud de ajuste y puede ser útil para saber a quién contactar para obtener más información.
  • cases.tags Puede ser útil si usas etiquetas para ordenar o identificar tus casos.

Paso 3: Recuperar las alertas adjuntas al caso

Para cada caso querrás saber qué alertas están asociadas para saber cuáles deben ajustar. Esto se puede hacer usando la API de casos con el campo _id correspondiente al caso.

/api/cases/{caseId}/alerts

Esta consulta devolverá un array de todos los valores de alerta id que se asocian al caso. Usando este valor ID puedes consultar el índice de .siem-signals* elasticsearch para encontrar la información completa sobre cada alerta adjunta al caso que necesita ajuste.

POST /.siem-signals-*/_search  
{  
 "size": 1,  
 "query": {  
   "bool": {  
     "must": [],  
     "filter": [  
       {  
         "bool": {  
           "should": [  
             {  
               "match": {  
                 "_id": "{{alert_id}}"  
               }  
             }  
           ],  
           "minimum_should_match": 1  
         }  
       },  
       {  
         "range": {  
           "@timestamp": {  
             "format": "strict_date_optional_time",  
             "gte": "now-30d",  
             "lte": "now"  
           }  
         }  
       }  
     ],  
     "should": [],  
     "must_not": []  
   }  
 }  
}

A partir de los resultados de esta consulta puedes extraer información sobre la alerta, como el nombre y la fecha de creación, junto con cualquier otra información que pueda ayudar a ajustar, como los campos user.name o process.name . Como un caso puede tener muchas alertas asociadas, querrás deduplicar las alertas por el valor signal.rule.name .

Paso 4: Abrir una solicitud de afinación.

Este paso depende del sistema de tiquetes que emplees en tu entorno. Nuestro equipo usa GitHub Issues para rastrear solicitudes de ajuste y Slack para notificaciones, pero esto también se podría hacer con cualquier sistema de tiquetes o gestión de proyectos que soporte automatización.

Este es el flujo lógico que usamos para nuestra automatización usando tanto Github como Slack para rastrear las solicitudes de ajuste:

  • Usando el nombre de la alerta, buscamos cualquier solicitud de sintonización abierta existente.
    • Si existe una solicitud de ajuste existente, actualizamos esa solicitud con los detalles del caso y de la nueva solicitud
    • Si no existe ninguna solicitud existente, abrimos un nuevo problema de solicitud de ajuste y anexamos la información
  • Luego enviamos una notificación de Slack al canal de Slack del equipo de ingeniería de Detección que contiene un enlace a la solicitud de sintonización, un enlace al caso y detalles sobre la solicitud y la alerta.
  • Luego usamos la API de Casos para agregar un comentario al caso original con un enlace al problema de la solicitud de ajuste
  • Agente de IA opcional: Estamos empezando a experimentar con el uso de agentes de IA para analizar la información de alertas y casos y luego proporcionar un contexto aún mejor con la solicitud de ajuste, incluso recomendando los cambios a hacer en las reglas de detección.

El resultado final de esta automatización es que nuestros analistas SOC pueden crear un tiquete detallado de solicitud de ajuste de detección con un solo clic desde su caso. Vimos un aumento dramático en la reducción de falsos positivos y en la eficiencia general de nuestras reglas de detección gracias a esta automatización.

Conclusión

Empleando Kibana Cases con campos personalizados e integrando con plataformas de automatización, puedes optimizar muchos de tus procesos manuales. Este flujo de trabajo automatizado reduce la carga manual asociada a la recopilación de comentarios de los analistas, cerciorando que los valiosos conocimientos de los analistas se traduzcan rápidamente en mejoras accionables en las reglas de detección. El resultado es un SOC más eficiente, preciso y resiliente, capaz de adaptar rápidamente a amenazas emergentes y reducir la fatiga ante las alertas.

¿Listo para optimizar la eficiencia de tu SOC y mejorar tu postura de detección? ¡Explora Elastic Security y empieza a crear hoy mismo tus propios flujos de trabajo automatizados de solicitud de ajuste!