flawopen.com/Teardowns/cve-2026-14540-google-mcp-toolbox-ssrf
CVE-2026-14540: SSRF в Google MCP Toolbox
CVE-2026-14540 позволяла HTTP-запросам MCP Toolbox следовать перенаправлениям без проверки конечного сетевого адреса. Обновите версию до 1.5.0 или новее.[1], [3]
Почтовый отдел проверяет первый адрес на посылке, а затем следует любой наклейке о пересылке, не проверяя новый пункт назначения. HTTP-перенаправление работает так же: без проверки конечного IP запрос к обычному сайту может попасть во внутреннюю сеть. Исправление проверяет фактический адрес при подключении и отдельно проверяет адреса перенаправлений.[2], [4], [7]
Ключевые понятия и термины
Server-side request forgery (SSRF)- Сервис вынуждают отправить HTTP-запрос к адресу, на который влияет атакующий. Запрос исходит от сервера и поэтому может попасть в сети, недоступные инициатору.[6]
HTTP-перенаправление- Ответ может указать HTTP-клиенту отправить следующий запрос на другой URL. Проверка только исходного URL не ограничивает адрес следующего запроса.[4], [7]
DNS rebinding и TOCTOU- Во время проверки имя хоста может разрешиться в один адрес, а при открытии сокета — в другой. Проверка разрешённого IP непосредственно при подключении закрывает разрыв между проверкой и использованием.[2], [7]
Generic HTTP source и tool- Компоненты MCP Toolbox, формирующие HTTP-запросы из настроенных конечных точек и параметров инструментов. В уведомлении этот путь указан как затронутый.[1], [2], [4]
CWE-918- Server-Side Request Forgery (SSRF): приложение получает URL или обращается к адресу, не ограничивая должным образом возможное направление запроса.[6]
Связи со стандартами
- Ссылка CWE для слабого места, описанного в этом руководстве: CWE-918
- D3-OTF Фильтрация исходящего трафика — Описанное в руководстве ограничение исходящего сетевого трафика сокращает список адресов, доступных сервису или хосту.
Анализ первопричины
В уязвимых версиях generic HTTP source создавала Go http.Client с тайм-аутом и транспортом, но без политики перенаправлений с проверкой назначения и без проверки IP на границе сокета. По умолчанию Go следовал перенаправлениям. Настроенные HTTP-инструменты могли включать параметры в запросы, поэтому специально выбранное значение или перенаправление могли увести запрос от ожидаемого адреса. Проверки только исходного URL недостаточно: перенаправление меняет адрес, а DNS может вернуть другой IP между проверкой и подключением. В исправлении добавлен SSRFGuard: он отклоняет запрещённые назначения в CheckRedirect и повторно проверяет разрешённый IP на уровне подключения. Частные, loopback, link-local и другие неглобальные адреса по умолчанию блокируются; разрешение диапазонов или частных сетей является исключением настройки и должно быть строго ограничено.[1], [2], [4]
Пошаговый сценарий атаки
Проверьте достижимость по трём условиям
Для этой цепочки нужны все три условия: (1) уязвимая версия 0.3.0–1.4.0 использует generic HTTP source/tool; (2) вызывающий может обратиться к этому пути и управлять URL/путём либо вызвать перенаправление; (3) узел Toolbox может маршрутизировать трафик к цели. Если хотя бы одного условия нет, эта цепочка не достигнет цели через данный путь. Собственные механизмы аутентификации и контроля доступа цели продолжают действовать.[1]
Параметр инструмента влияет на исходящий запрос
Настроенный HTTP-инструмент объединяет базовую конечную точку со входными значениями. В описании CVE указано, что специально сформированные параметры пути могут перенаправить HTTP source на другой адрес. Пользователь или агент MCP вызывает инструмент; недоверенное содержимое влияет на этот вызов только тогда, когда это допускает окружающий процесс.[1], [2]
Toolbox отправляет запрос из собственной сети
Следующий запрос исходит от хоста Toolbox и может обращаться к адресам, разрешённым сетью этого хоста. Внутренние сервисы или другие доступные точки могут получить запросы, которые пользователь MCP не мог бы отправить напрямую. CVE не доказывает, что в каждом развертывании раскрываются облачные учётные данные или что каждое перенаправление успешно.[1]
Обновите версию и проверьте исходящий трафик
Обновите MCP Toolbox до 1.5.0 или новее. Исправление проверяет настроенные IP-литералы и перенаправления, а при подключении блокирует запрещённые разрешённые IP, что устраняет и DNS rebinding. Оставьте allowPrivateNetworks отключённым без необходимости, строго ограничьте разрешённые диапазоны и отдельно применяйте политику сетевого выхода.[2], [3], [4]
Исходный код: Уязвимый vs Защищённый вариант
Здесь показан выбранный фрагмент upstream-пути HTTP-клиента, а не замена всего файла. Влитое исправление добавляет SSRFGuard: он проверяет назначения перенаправлений и отклоняет запрещённые разрешённые IP непосредственно при подключении, закрывая уязвимость DNS rebinding, которую оставила бы одна проверка перенаправления. По умолчанию guard блокирует частные и другие неглобальные адреса. allowPrivateNetworks, allowedIpRanges и customBlockedIpRanges — мощные настройки; исключение в allowlist следует ограничивать только нужным диапазоном. Исходный файл: internal/sources/http/http.go.[2]
Фрагмент исходного кода: Фрагмент HTTP-клиента и политики перенаправления
client := http.Client{
Timeout: duration,
Transport: tr,
}
// Без политики CheckRedirect клиент следует HTTP-перенаправлениям по
// умолчанию. Транспорт также не ограничивает адреса назначения для защиты от SSRF.
client := &http.Client{
Timeout: duration,
Transport: tr,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
if len(via) >= 10 {
return fmt.Errorf("stopped after 10 redirects")
}
hostname := req.URL.Hostname()
if ip := net.ParseIP(hostname); ip != nil {
if guard.IsIPBlocked(ip) {
return fmt.Errorf("redirect to blocked IP %s denied", ip)
}
return nil
}
addrs, err := resolver.LookupHost(req.Context(), hostname)
if err != nil {
return fmt.Errorf("failed to resolve redirect host %s: %w", hostname, err)
}
for _, addr := range addrs {
if ip := net.ParseIP(addr); ip != nil && guard.IsIPBlocked(ip) {
return fmt.Errorf("redirect host %s resolves to blocked IP %s", hostname, addr)
}
}
return nil
},
}
// Тот же SSRFGuard применяется и на границе открытия сокета,
// поэтому DNS-ответ не может заменить разрешённый адрес заблокированным.
Чек-лист по защите системы для инженеров
- ✓Проверьте бинарные сборки, контейнеры и зависимости Google MCP Toolbox; считайте версии 0.3.0–1.4.0 уязвимыми и обновите до 1.5.0 или новее.[1], [3]
- ✓Проверьте версию работающего процесса Toolbox; обновление MCP-клиента, агентского framework или хост-приложения не обновляет этот процесс.[1], [3]
- ✓Для каждого generic HTTP source/tool выясните, какие параметры влияют на URL, путь, хост или цепочку перенаправлений; уберите ненужный контроль назначения через недоверенные входные данные.[1], [2]
- ✓Оставляйте
allowPrivateNetworksвыключенным без документированной необходимости; при включении ограничьтеallowedIpRangesминимально нужными CIDR и рассматривайте исключение как правило firewall.[4], [2] - ✓Используйте
customBlockedIpRangesдля чувствительных адресов, которые должны оставаться недоступными даже при более широком разрешении частных сетей.[4], [2] - ✓Добавьте регрессионные тесты для прямых частных и loopback IP, имён с запрещёнными адресами, перенаправлений на запрещённые цели, циклов, неверных CIDR и изменяющихся DNS-ответов между проверкой и подключением.[2]
- ✓Применяйте сетевую политику исходящего трафика на уровне хоста, контейнера или VPC, чтобы будущая регрессия URL-проверки не открыла доступ к metadata-сервисам или посторонним внутренним сетям.[7]
- ✓Рекомендация FlawOpen по реагированию: Если уязвимый экземпляр был доступен извне, проверьте HTTP-журналы и исходящие соединения на необычные назначения; само наличие CVE не доказывает доступ к данным.
Источники
- Google CNA CVE record CVE-2026-14540 (NVD; CNA CVSS-BT 8.0, CVSS 4.0)
- Google MCP Toolbox pull request #3448: SSRF guard
- MCP Toolbox v1.5.0 release and changelog
- Google MCP Toolbox HTTP source documentation
- The Next Web: Google, JPMorgan and two governments fixed the same MCP flaw
- MITRE CWE-918: Server-Side Request Forgery (SSRF)
- OWASP: памятка по предотвращению SSRF