
Пошаговое лабораторное описание эксплуатации CVE-2019-20933 — обхода аутентификации в InfluxDB с помощью поддельных JWT-токенов, включая эксплуатацию, пост-эксплуатацию и рекомендации по устранению уязвимости.
Начнём с того, что запущено в среде. Я выведу список всех активных контейнеров:
docker ps

Жертва предоставляет доступ к одному порту: 8086.
В настоящее время у меня нет подробной информации о цели. Из вывода docker ps видно, что система предоставляет доступ только к одному заметному сервису внешне на порту 8086, который сопоставлен с сервисом внутри контейнера. Это основная поверхность атаки, которую необходимо проанализировать.
Вместо того чтобы сразу заходить через браузер, мы приступаем к идентификации сервиса с помощью Nmap, чтобы определить, какой сервис запущен на порту 8086:
nmap -sV -sC -p 8086 192.168.3.137

Результаты сканирования показывают, что порт 8086 является HTTP-сервисом InfluxDB OSS 1.6.6. Это база данных временных рядов, доступная через HTTP API, а не типичное веб-приложение.
InfluxDB — это база данных временных рядов с открытым исходным кодом, написанная на Go. В отличие от RDBMS (оптимизированных для точных транзакций) или Elasticsearch (оптимизированного для текстового поиска), InfluxDB создана с единственной целью: Обработка огромных объемов записи (Высокая пропускная способность записи) и запрос данных по временной оси с низкой задержкой.

Поскольку сервис был идентифицирован как InfluxDB, следующим шагом является обращение к тому, как InfluxDB взаимодействует с клиентами. Согласно документации InfluxDB v1 HTTP API, порт 8086 является портом HTTP API по умолчанию. Важные конечные точки включают:
/ping: проверяет рабочее состояние сервера./query: отправляет запросы InfluxQL для чтения метаданных или данных./write: записывает данные временных рядов в базу данных.⇒ Размышление: После того, как Nmap идентифицирует сервис как InfluxDB http admin 1.6.6, мы не продолжаем тестировать его как обычный веб-сайт. Для веб-приложений мы обычно ищем маршруты, формы входа или каталоги. Однако в случае с InfluxDB поверхность атаки находится в HTTP API. Поэтому нам необходимо переключиться на тестирование стандартных конечных точек InfluxDB API, чтобы определить, требует ли API аутентификации. Следовательно, следующее направление тестирования — не доступ к / через браузер, а отправка запросов напрямую к конечным точкам API InfluxDB.
/pingПосле идентификации порта 8086 как HTTP API InfluxDB, проверьте конечную точку /ping, чтобы подтвердить работоспособность сервиса:
curl -i <http://192.168.3.137:8086/ping>

Ответ 204 No Content подтверждает, что InfluxDB работает нормально. Заголовки дополнительно подтверждают версию сервиса как InfluxDB OSS 1.6.6
/querycurl -i -s "http://192.168.3.137:8086/query?q=SHOW+DATABASES"

Конечная точка /query не разрешает прямые запросы без учетных данных аутентификации. Это подтверждает, что в InfluxDB включена аутентификация и она блокирует все анонимные запросы, отправляемые в систему.
Я переключаюсь на размышление: есть ли в версии InfluxDB 1.6.6 какая-либо уязвимость, позволяющая обойти механизм аутентификации?

Обратившись к публичным базам данных уязвимостей, версии InfluxDB до 1.7.6 подвержены CVE-2019-20933. Это уязвимость обхода аутентификации в функции аутентификации InfluxDB, связанная с обработкой JWT-токенов с пустым общим секретом.
Поскольку цель работает под управлением InfluxDB 1.6.6, что ниже версии с патчем 1.7.6, сервис попадает в диапазон уязвимых версий.
Можно сделать вывод:
Service: InfluxDB OSS
Version: 1.6.6
Authentication: Enabled
CVE mapping: CVE-2019-20933
Impact: Authentication Bypass
Status: Version vulnerable
⇒ Размышление: Изначально конечная точка /query возвращает 401 Unauthorized, что указывает на то, что механизм аутентификации активен. Однако наличие аутентификации не означает абсолютную безопасность. Когда версия идентифицирована как 1.6.6, нам необходимо сопоставить её с известными CVE. Результаты показывают, что эта версия попадает в диапазон, затронутый CVE-2019-20933, что означает, что можно обойти механизм аутентификации, защищающий конечную точку /query. На основании этих результатов идентификации этап эксплуатации будет сосредоточен на проверке CVE-2019-20933 путём генерации соответствующего JWT-токена для обхода аутентификации и выполнения запросов к конечной точке /query.
Уязвимость CVE-2019-20933 возникает в функции authenticate в файле services/httpd/handler.go InfluxDB версии ниже 1.7.6.
InfluxDB поддерживает аутентификацию с использованием JSON Web Tokens (JWT) для запросов HTTP API. При получении запроса с заголовком:
Authorization: Bearer <token>
InfluxDB выполняет следующие шаги:
shared-secret из файла influxdb.conf, чтобы использовать его в качестве секретного ключа для проверки подписи токена.username из утверждений (claims) для определения пользователя, выполняющего запрос.В уязвимых версиях, если аутентификация JWT включена, но параметр shared-secret не настроен, значение секрета может обрабатываться как пустая строка ("").
Система не выполняет адекватную проверку надёжности секрета перед проверкой подписи JWT. Это позволяет злоумышленнику создать собственный JWT, подписать его пустым секретом, а затем установить утверждение username на существующий аккаунт в системе, например admin, если этот аккаунт существует в лаборатории.
Когда этот токен отправляется через заголовок Authorization: Bearer <token>, InfluxDB использует тот же пустой секрет для проверки подписи. Если подпись совпадает и имя пользователя существует, запрос будет авторизован без необходимости ввода реального пароля пользователя.
Поток обработки можно обобщить следующим образом:
| Step | Normal Processing | Flaw in CVE-2019-20933 |
|---|---|---|
| 1 | Client sends Authorization: Bearer <token> | Злоумышленник самостоятельно создаёт JWT |
| 2 | Server reads shared-secret from configuration | shared-secret не задан |
| 3 | Server uses secret to verify JWT signature | Секрет обрабатывается как пустая строка "" |
| 4 | If token is valid, retrieve username from claim | Злоумышленник устанавливает username=admin, если пользователь существует |
| 5 | Server grants permissions based on the claim user | Запрос принимается без запроса пароля |
Поток эксплуатации на логическом уровне:
InfluxDB < 1.7.6
→ authentication enabled
→ empty shared-secret
→ attacker creates JWT signed with secret ""
→ sends token via Authorization: Bearer
→ server accepts the token
→ query to /query succeeds