Burp + Elastic = Куча логов(багов?)
Интро
Периодически сталкиваюсь с тем, что мне нужны запросы из Burp которые я делал когда-то давно или необходимо посмотреть среди множества похожих запросов некоторые аномалии.
Наверняка вы сразу подумали про то, что можно использовать и сохранять проекты. Но это не столь наглядно и вызывает трудности, когда необходимо посмотреть на всю "картину" в целом.
Немного походив вокруг задачи я решил развернуть ELK для ее решения.
Но что же может дать использование ELK? Зачем оно надо?
Я заметил за собой, что часто пропускаю при анализе web-приложения такой параметр, как время ответа. И это ведет к тому, что потенциальные неочевидные уязвимые точки, например, содержащие SQLi, я могу просто не заметить. Используя ELK я могу на большом объеме посмотреть всю картину и найти аномалии по данному параметру.
Или можно представить кейс, когда появляется новая уязвимость в каком-то модуле или библиотеке. В таком случае, зная, предположим, паттерн пути, можно с легкостью найти весь ранее пройденый скоуп, который потенциально уязвим. И это не в рамках одного проекта, а всех.
Развертка ELK
Весь процесс сводится к копипасте официальной документации. Ниже продублированы основные файлы и конфигурации на случай, если дока переедет или изменится, так же сделан снапшот страницы через waybackmachine и файлов конфигурации .env и docker-compose.yml
Что потребуется?
Машинка с Docker и docker compose
Если у вас есть только машинка - не беда. Докер поставить - задача одной минуты.
Если нет машинки, то самое время найти такую. Себе под эксперементы я однажды взял Firebat MN56 и после небольшого тюнинга по ОЗУ и SSD, остаюсь полностью доволен по сей день.
Установка Docker (линки на оф.манулы)
Официальные манулы по установке Docker Desktop (GUI) :
- Mac https://docs.docker.com/desktop/install/mac-install/
- Linux https://docs.docker.com/desktop/install/linux-install/
- Windows https://docs.docker.com/desktop/install/windows-install/
Официальный манул на ubuntu (cli version) :
Настройка/запуск ELK
Развертывание в моем случае происходит на mini pc с Ubuntu 22.04 по инструкции multi-node cluster варианта.
Выберете для себя каталог размещения файлов .env и docker-compose.yml. В примере я использую /srv/elk/.
Создайте или сохраните файлы .env и docker-compose.yml.
# Password for the 'elastic' user (at least 6 characters) ELASTIC_PASSWORD=changeme # Password for the 'kibana_system' user (at least 6 characters) KIBANA_PASSWORD=changeme # Version of Elastic products STACK_VERSION=8.14.0 # Set the cluster name CLUSTER_NAME=docker-cluster # Set to 'basic' or 'trial' to automatically start the 30-day trial LICENSE=basic #LICENSE=trial # Port to expose Elasticsearch HTTP API to the host ES_PORT=9200 #ES_PORT=127.0.0.1:9200 # Port to expose Kibana to the host KIBANA_PORT=5601 #KIBANA_PORT=80 # Increase or decrease based on the available host memory (in bytes) MEM_LIMIT=1073741824 # Project namespace (defaults to the current folder name if not set) #COMPOSE_PROJECT_NAME=myproject
services:
setup:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
user: "0"
command: >
bash -c '
if [ x${ELASTIC_PASSWORD} == x ]; then
echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
exit 1;
elif [ x${KIBANA_PASSWORD} == x ]; then
echo "Set the KIBANA_PASSWORD environment variable in the .env file";
exit 1;
fi;
if [ ! -f config/certs/ca.zip ]; then
echo "Creating CA";
bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;
unzip config/certs/ca.zip -d config/certs;
fi;
if [ ! -f config/certs/certs.zip ]; then
echo "Creating certs";
echo -ne \
"instances:\n"\
" - name: es01\n"\
" dns:\n"\
" - es01\n"\
" - localhost\n"\
" ip:\n"\
" - 127.0.0.1\n"\
" - name: es02\n"\
" dns:\n"\
" - es02\n"\
" - localhost\n"\
" ip:\n"\
" - 127.0.0.1\n"\
" - name: es03\n"\
" dns:\n"\
" - es03\n"\
" - localhost\n"\
" ip:\n"\
" - 127.0.0.1\n"\
> config/certs/instances.yml;
bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;
unzip config/certs/certs.zip -d config/certs;
fi;
echo "Setting file permissions"
chown -R root:root config/certs;
find . -type d -exec chmod 750 \{\} \;;
find . -type f -exec chmod 640 \{\} \;;
echo "Waiting for Elasticsearch availability";
until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;
echo "Setting kibana_system password";
until curl -s -X POST --cacert config/certs/ca/ca.crt -u "elastic:${ELASTIC_PASSWORD}" -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
echo "All done!";
'
healthcheck:
test: ["CMD-SHELL", "[ -f config/certs/es01/es01.crt ]"]
interval: 1s
timeout: 5s
retries: 120
es01:
depends_on:
setup:
condition: service_healthy
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
- esdata01:/usr/share/elasticsearch/data
ports:
- ${ES_PORT}:9200
environment:
- node.name=es01
- cluster.name=${CLUSTER_NAME}
- cluster.initial_master_nodes=es01,es02,es03
- discovery.seed_hosts=es02,es03
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es01/es01.key
- xpack.security.http.ssl.certificate=certs/es01/es01.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es01/es01.key
- xpack.security.transport.ssl.certificate=certs/es01/es01.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
es02:
depends_on:
- es01
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
- esdata02:/usr/share/elasticsearch/data
environment:
- node.name=es02
- cluster.name=${CLUSTER_NAME}
- cluster.initial_master_nodes=es01,es02,es03
- discovery.seed_hosts=es01,es03
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es02/es02.key
- xpack.security.http.ssl.certificate=certs/es02/es02.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es02/es02.key
- xpack.security.transport.ssl.certificate=certs/es02/es02.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
es03:
depends_on:
- es02
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
- esdata03:/usr/share/elasticsearch/data
environment:
- node.name=es03
- cluster.name=${CLUSTER_NAME}
- cluster.initial_master_nodes=es01,es02,es03
- discovery.seed_hosts=es01,es02
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es03/es03.key
- xpack.security.http.ssl.certificate=certs/es03/es03.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es03/es03.key
- xpack.security.transport.ssl.certificate=certs/es03/es03.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
kibana:
depends_on:
es01:
condition: service_healthy
es02:
condition: service_healthy
es03:
condition: service_healthy
image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
volumes:
- certs:/usr/share/kibana/config/certs
- kibanadata:/usr/share/kibana/data
ports:
- ${KIBANA_PORT}:5601
environment:
- SERVERNAME=kibana
- ELASTICSEARCH_HOSTS=https://es01:9200
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
mem_limit: ${MEM_LIMIT}
healthcheck:
test:
[
"CMD-SHELL",
"curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
]
interval: 10s
timeout: 10s
retries: 120
volumes:
certs:
driver: local
esdata01:
driver: local
esdata02:
driver: local
esdata03:
driver: local
kibanadata:
driver: localСамые внимательные наверняка заметили, что в варианте описаном выше отсутствует строка version: "2.2". Это сделано специально, т.к. в последних версиях docker compose свойство version устарело и больше не используется.
Теперь для запуска остается выполнить команду
docker compose up -d
И подождать минут 5, пока первоначальный процесс установки закончится.
http://ip_вашей_машины:5601/app/enterprise_search/content/search_indices
Вводим логин elastic и пароль из переменной ELASTIC_PASSWORD=
Тут нам необходимо создать индекс, который будет содержать в себе данные из burp
Настройка Burp
Плагины
Приступаем к самому интересному.
Как же заставить Burp отправлять логи в Elastic? Посмотрим, что предлагает BApp Store и не только:
Я попробовал все варианты. Какими выводами я могу с вами поделиться:
ElasticBurp, ElasticBurp-NG (Next Generation!!!11) и Report To Elastic Search - это все разные стороны одной кучи 💩
Эти плагины считают, что соединение к elastic должно быть по http и без аутентификации.
Другое дело Logger++, но нужена версия с github от nccgroup, т.к. в BApp Store лежит древняя.
Итак, мы поставили плагин и уже хотим пойти в настройки. Но именно на данном этапе стоит сделать шаг в сторону.
Настройка сертификатов
В используемой конфигурации elastic'а, соединение возможно только через https. Поэтому для корректной работы необходимо добавить сертификат сервера в доверенные сертификаты той Java, которая используется Burp'ом.
Интернет полон следующим адресом хранилища сертификатов $JAVA_HOME/jre/lib/security/cacerts, однако это не применимо к Burp под MacOS тк там используется поставляемый, вместе с Burp'ом, Java bundle.
Как быть, если мы MacOS пользователи.
Для начала сохраним наш сертификат в домашний каталог пользователя на нашей MacOS
openssl x509 -in <(openssl s_client -connect адрес_вашего_сервера:9200 -prexit 2>/dev/null) -out ./elk.crt
Затем "пропатчим" хранилище сертификатов Java bundle
sudo keytool -importcert -file ~/elk.crt -alias example -keystore /Applications/Burp\ Suite\ Professional.app/Contents/Resources/jre.bundle/Contents/Home/lib/security/cacerts -storepass changeit
Теперь момент о котором легко забыть - мы добавили сертификат, в котором указан Common Name: es01. В таком случае при обращении по IP мы будем получать сообщение о несоответствии сертификата к хостнейму.
Для обхода этого необходимо добавить банальные записи в /etc/hosts
192.168.100.27 es01 # тут нужно указать ваш адрес сервера
Настройка плагина
Данный пунк весьма прост. Идем в настройки плагина и выставляем общие настройки по желанию и необходимости, а настройки соединения приводим к следующему виду
Не забудьте про кнопку Configure
Все. Теперь вы можете наслаждаться логами в Kibana http://es01:5601/app/discover#/ , смотреть, фильтровать и строить визуализации.