понедельник, 31 июля 2017 г.

Splunk. Подключаем Vulners к Splunk.

Приветствую, уважаемый читатель!

Год назад я писал про получение списка эксплойтов по CVE-номеру уязвимости при помощи vulners.com http://unitybas.blogspot.ru/2016/07/vulners.html. Спустя какое-то время захотелось более плотно интегрировать данную возможность в splunk, и получать информацию с данного ресурса прямо в запрос на SPL.   





Соединять vulners и splunk будем через скрипт на python. Алгоритм следующий:
скрипт получает из splunk список CVE-номеров, последовательно опрашивает vulners на предмет наличия сведений по данной уязвимости, и далее возвращает в splunk информацию в удобном для парсинга виде. 

1.                  Текст модернизированного скрипта представлен ниже:

#!/usr/bin/env python
import csv
import sys
import os
import json
import requests

def main():
            infile = sys.stdin
            outfile = sys.stdout

            r = csv.DictReader(infile)
            header = r.fieldnames

            w = csv.DictWriter(outfile, fieldnames=r.fieldnames)
            w.writeheader()

            for result in r:
                        cvenum = result["cve"]
                        uniq=[]
                        matchcve = ''
                        url = 'https://vulners.com/api/v3/search/lucene/?query=cvelist:'+cvenum
                        req = requests.get(url, verify=False)
                        sploit = json.loads(req.content)
                        for jread in sploit['data']['search']:
                                   elem = jread['_source']['type']
                                   if uniq.count(elem) == 0:
                                               uniq.append(elem)
                        uniqlen = len(uniq)
                        for i in range(uniqlen):
                                   matchcve = matchcve + 'v_' + uniq[i] + '=1;'

                        result["matchcve"] = matchcve
                        w.writerow(result)

if __name__ == '__main__':
            main()


Примечание:

a. Фактически скрипт получает из splunk список событий в формате csv. Для нас главное, чтобы этот список включал fields с именем cve.
b. Выполняем get-запросы с указанием CVE-номера уязвимостей на https://vulners.com/api/v3/search/lucene/?query=, парсим ответы, и формируем строку, содержащую список источников, в которых есть информация по данной уязвимости.

2.                  Подключаем скрипт к splunk

a.   Необходимо разместить скрипт в директории /opt/splunk/etc/system/bin. Особо хочу отметить, в splunk встроен свой интерпретатор Python, поэтому перед подключением скрипта убедитесь, что нужные вам библиотеки есть тут - /opt/splunk/lib/python2.7/site-packages.
b.      Далее необходимо «зарегистрировать» новый lookup, который будет использовать данный скрипт. Фактически подключение скрипта, это подключение lookup-таблицы. 
Делается это в /opt/splunk/etc/apps/search/local/transforms.conf:

[allvuln]
external_cmd = vulners_cve_all_v1.py cve
fields_list = cve,matchcve

Примечание:
В параметре fields_list должен содержать список всех полей, которые могут быть использованы в SPL-запросе.

c.                  Создадим файл с произвольными CVE-номера, следующего вида:
«cve
CVE-2016-0099
CVE-2016-2119
CVE-2017-0144»


Собственно, для успешного использования осталось только передать в скрипт CVE-номера из файла:

| inputcsv cve.csv
| lookup allvuln cve OUTPUT matchcve




На этом можно было бы, и закончить, но хочется привести результаты в человеческий вид. Для этого существенно усложним запрос:

| inputcsv cve.csv
| lookup allvuln cve OUTPUT matchcve
| eval sources = split(matchcve, ";")
| mvexpand sources
| rex field=sources "(?<key>[^=]+)=(?<value>.*)$"
| eval {key} = value
| fields - key,sources,value
| stats first(*) as * by cve
| foreach v_* [eval <<FIELD>>=if((<<FIELD>>="1"),"Found","Not")]
| fields – matchcve
| eval link_vulners = "https://vulners.com/search?query=" + cve


Пояснение:

1. | eval sources = split(matchcve, ";") # разделяем строку на пары «поле=значение»

2. | mvexpand sources
   | rex field=sources "(?<key>[^=]+)=(?<value>.*)$"  # для каждого cve-номера разделяем поле source на отдельные строки для каждой пары «поле=значение».

3. | eval {key} = value
    | fields - key,sources,value
   | stats first(*) as * by cve   #создаём каждого cve-номера отдельные поля, соответствующие значениям поля «key»

4.  | foreach v_* [eval <<FIELD>>=if((<<FIELD>>="1"),"Found","Not")]   #изменяем значения во вновь созданных полях.
   

Теперь получилось красиво J






Но…..для большей наглядности, создадим из данного запроса дашборд, и к визуальному компоненту «table», после конца секции «search»  добавляем следующий код:

<format type="color" field="">
<colorPalette type="map">{"Found":#d93627,"Not":#C7F439}</colorPalette>
</format>


Получилось, как-то так:


Всем удачного использования и спасибо vulners.com. 

1 комментарий:

  1. Добрый день!
    Не могли бы вы рассмотреть вопрос как в splunk проверять логи на наличие значений в неком блеклисте и выдачи в случае совпадения алерта или информации об этом.

    ОтветитьУдалить