• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Контрабанда запросов через открытый текст HTTP/2 (h2c)

вавилонец

CPU register
Пользователь
Регистрация
17.06.2021
Сообщения
1 116
Реакции
1 265
1665537780412.png


ОРИГИНАЛЬНАЯ СТАТЬЯ
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ xss.pro
$600 ---> 0x5B1f2Ac9cF5616D9d7F1819d1519912e85eb5C09 для поднятия ноды ETHEREUM и тестов

Контрабанда HTTP-запросов привело к разрушительным уязвимостям при развертывании приложений. HTTP-запрос, отправленный контрабандным путем после проверки пограничного сервера, может привести к серьезным последствиям, включая поддельные внутренние заголовки, доступ к внутренним конечным точкам управления и множество возможностей для повышения привилегий.
HTTP/2 (или HTTP/3) — многообещающее решение проблем, с которыми мы столкнулись при туннелировании запросов, но поддержка HTTP/1.1 не исчезнет в ближайшее время. А пока нас ждут еще сюрпризы от нашего хорошего друга HTTP/1.1.
В этом посте я показываю, как обновление соединений HTTP/1.1 до менее известных соединений HTTP/2 через соединения с открытым текстом (h2c) может позволить обойти контроль доступа обратного прокси-сервера и привести к долгоживущему неограниченному HTTP-трафику непосредственно на серверную часть.

ПРЕДПОСЫЛКИ: ОБНОВЛЕНИЯ HTTP/1.1 И ПРОКСИ

Чтобы понять эту уязвимость, давайте рассмотрим поведение обновлений HTTP/1.1 и то, как реализуются прокси.

Заголовок Upgrade чаще всего используется для обновления соединений HTTP до долгоживущих соединений WebSocket. Прокси-серверы поддерживают это поведение, поддерживая исходное клиентское соединение и просто перенаправляя TCP-трафик на внутренний сервер. На этом этапе прокси-сервер больше не учитывает содержимое и больше не может применять правила управления доступом. Давайте рассмотрим процесс обновления h2c. Он начинается с того, что клиент инициирует запрос на обновление HTTP/1.1. После получения успешного ответа 101 «Switching Protocols» клиент повторно использует соединение и передает данные в соответствии с новым согласованным протоколом, в данном случае h2c.

1665539290717.png


После получения ответа 101 от внутреннего веб-сервера прокси-сервер поддерживает постоянное TCP-соединение и больше не отслеживает содержимое. Чтобы процитировать документацию NGINX WebSocket:
«Приложение WebSocket поддерживает постоянное открытое соединение между клиентом и сервером, облегчая разработку приложений в реальном времени. […] NGINX поддерживает WebSocket, позволяя настроить туннель между клиентом и внутренним сервером. - https://www.nginx.com/blog/web...
В своем исследовании туннелирования WebSocket Михаил Егоров ( @0ang3el ) продемонстрировал, что, вызывая проблемы с серверной частью при обновлении до соединения WebSocket, он может поддерживать конвейерное соединение HTTP/1.1 с серверной частью, когда прокси обновляет соединение. Это позволяло пересылать запросы контрабандой, обходя контроль доступа прокси-сервера.
Хотя эта форма контрабанды запросов не приводит к атакам с отравлением сокетов (также известным как рассинхронизация HTTP), она все же может позволить вам обойти важные элементы управления доступом к пограничному серверу. Это отличное дополнение к набору хитростей при тестировании сервисов с поддержкой WebSocket.
Но что, если бы нам не нужно было обманывать серверную часть и мы могли бы просто поддерживать туннель TCP на основе HTTP по дизайну? Вот где в игру вступают обновления h2c. Я решил исследовать поведение реализации h2c, чтобы посмотреть, смогу ли я найти более гибкий вариант для контрабанды.

Спецификация H2C и рискованная возможность

Как правило, использование протокола HTTP/2 согласовывается с помощью расширения протокола уровня приложений TLS (TLS-ALPN), где оно идентифицируется строкой «h2». Это происходит до того, как мы отправим наш первый HTTP-запрос. Однако HTTP/2 также может быть инициирован через заголовок обновления HTTP/1.1, идентифицируемый строкой «h2c» для связи в открытом виде. Вот пример запроса:
Код:
GET / HTTP/1.1
Host: www.example.com
Upgrade: h2c
HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
Connection: Upgrade, HTTP2-Settings

Заголовок HTTP2-Settings содержит параметры соединения HTTP/2 в кодировке Base64. Согласно спецификации, обновления h2c разрешены только для соединений с открытым текстом, а заголовок HTTP2-Settings не должен пересылаться ( RFC 7540, раздел 3.2.1 ).

Чтение спецификации привело меня к трем вопросам:
  1. Если пограничный прокси-сервер выполняет завершение TLS, а я отправляю запрос на обновление h2c в сообщении HTTP, как внутренний сервер узнает, что мы пытаемся обновить h2c через TLS?
  2. Если пограничный прокси-сервер не поддерживает h2c, будет ли он пересылать клиентский запрос на обновление h2c?
  3. Если пограничный прокси-сервер успешно перенаправляет мое обновление h2c на внутренний сервер и оно принимается этим сервером, могу ли я обойти ограничения прокси-сервера в предоставленном туннеле TCP?
cURL и другие клиенты HTTP/2 не позволят вам выполнить обновление h2c через TLS, потому что это нарушение спецификации. Итак, используя библиотеку Hyper-2 HTTP2, я создал собственный клиент для тестирования.

ПОДТВЕРЖДЕНИЕ КОНЦЕПЦИИ

Я настроил сервер NGINX с завершением TLS на порту 443 с proxy_pass , подобным WebSocket, на конечной точке / для серверной службы, поддерживающей обновления h2c. Я также настроил сервер NGINX с контролем доступа, который блокировал все запросы к конечной точке /flag , как показано в конфигурации ниже:

Код:
server {
    listen       443 ssl;
    server_name  localhost;

    ssl_certificate       /usr/local/nginx/conf/cert.pem;
    ssl_certificate_key   /usr/local/nginx/conf/privkey.pem;

    location / {
     proxy_pass http://backend:9999;
     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection $http_connection;
    }

    location /flag {
    deny all;
    }

Для внутреннего сервера я создал простой сервер Golang, поддерживающий обновления h2c:

Код:
// Lightly modified example from: https://github.com/thrawn01/h2c-golang-example
package main

import (
    "fmt"
    "golang.org/x/net/http2"
    "golang.org/x/net/http2/h2c"
    "net"
    "net/http"
    "os"
)

func checkErr(err error, msg string) {
    if err == nil {
        return
    }
    fmt.Printf("ERROR: %s: %s\n", msg, err)
    os.Exit(1)
}

func main() {   
    h2s := &http2.Server{}

    handler := http.NewServeMux()
    handler.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %v, http: %v", r.URL.Path, r.TLS == nil)
    })

    handler.HandleFunc("/flag", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "You got the flag!");
    })

    server := &http.Server{
        Addr:    "0.0.0.0:9999",
        Handler: h2c.NewHandler(handler, h2s),
    }

    fmt.Printf("Listening [0.0.0.0:9999]...\n")
    checkErr(server.ListenAndServe(), "while listening")
}

Прямая отправка запросов к прокси-серверу для конечной точки / прошла успешно, а конечная точка /flag не удалась, как и ожидалось:

1665539352684.png


Это поведение показано на диаграмме ниже:

1665539373682.png


Теперь, используя мой собственный клиент h2cSmuggler для запуска обновления через TLS, мы можем успешно получить доступ к ограниченной конечной точке ( -x указывает прокси):

1665539390169.png


Это поведение показано на диаграмме ниже:

1665539413433.png


Давайте разберем, что только что произошло:
  1. h2cSmuggler отправляет запрос на обновление HTTP/1.1 в конечную точку / на обратном прокси-сервере NGINX.
  2. Прокси-сервер перенаправляет заголовки Upgrade и Connection на серверную часть, которая отвечает «101 Switching Protocols» и готовится к приему сообщений HTTP2.
  3. Получив ответ 101 от серверной части, прокси-сервер «обновляет» соединение до неуправляемого туннеля TCP.
  4. Получив ответ 101 от прокси-сервера, h2cSmuggler повторно использует существующее соединение и обменивается кадрами инициализации HTTP/2 с сервером. К ним относится ответ сервера для конечной точки, запрошенной при обновлении HTTP/1.1 h2c (конечная точка /).
  5. Используя мультиплексирование HTTP/2, h2cSmuggler отправляет дополнительный запрос на ограниченный флаг /flag .
  6. Прокси-сервер, который больше не отслеживает связь в туннеле TCP, перенаправляет запрос на внутренний сервер.
  7. Сервер отвечает флагом.
Как показано выше, мы успешно обошли контроль доступа прокси-сервера для доступа к частной конечной точке! инструмент тут
В соответствии со спецификацией прокси-серверы всегда будут ожидать, что согласование протокола h2 будет происходить через TLS-ALPN. Таким образом, вместо этого мы можем инициировать h2c-соединения через HTTP/1.1 через TLS с помощью h2cSmuggler. Мы также можем выполнить эту атаку по некоторым каналам с открытым текстом. Пока прокси-сервер не поддерживает обновления h2c и просто перенаправляет запрос клиента на обновление h2c на серверную часть, эта атака, вероятно, будет успешной и на незашифрованных каналах.
С помощью отдельного эксперимента я подтвердил, что в случае нескольких слоев прокси этот метод все еще работает. Предполагая, что все прокси успешно передают необходимые заголовки, вы можете выполнить первоначальную атаку, и она передаст ваши данные по серии промежуточных туннелей TCP, созданных каждым соответствующим прокси.
С этим типом контрабанды запросов («туннельной контрабандой»?) вы можете отправлять столько запросов, сколько хотите, через мультиплексирование HTTP/2. Кроме того, как мы знаем из предыдущих исследований, контрабанда HTTP-запросов делает возможным широкий спектр атак, в том числе: подделку внутренних заголовков, доступ к ограниченным административным конечным точкам, а иногда и SSRF-заголовкам хоста, позволяющий дальнейшее перемещение по сети. Но я знаю, что вы думаете: «Эта конфигурация NGINX кажется слишком специфичной. Когда это произойдет?»

Вот небезопасные конфигурации HAProxy, Traefik и Nuster (настолько общие и безобидные, насколько вы можете себе представить), которые по умолчанию пересылают необходимые заголовки h2c:

HAProxy/Nuster

Код:
mode http
frontend fe
bind *.8080
   default_backend be1
backend be1
server s1 backend:80

Traefik

Код:
http:
  routers:
    to-test:
      rule: "PathPrefix (`/`)"
      service: test

  services:
    test:
      loadBalancer:
        servers:
        - url: http://backend:80

Примечание. Traefik не включает HTTP-2-Settings в строку проксируемого подключения, что может привести к сбою атаки в некоторых реализациях h2c.

Как насчет внутренних серверов, поддерживающих h2c?

Из-за своего свойства уменьшать пропускную способность h2c является сильным кандидатом на внутрисетевую (т. е. микросервисную) связь с малой задержкой и позволяет избежать накладных расходов на управление и (оспаривается, но часто упоминается) производительности TLS. Таким образом, популярные веб-фреймворки часто поддерживают параметр конфигурации для включения поддержки обновления h2c. Тем не менее, поддержка редко является стандартной по умолчанию. Предполагая небезопасную конфигурацию внешнего прокси-сервера, использование h2c в микросервисах может увеличить вероятность успешной атаки.

ИСПРАВЛЕНИЕ
Чтобы снизить риски контрабанды h2c на прокси-серверах:
  • Требуется поддержка WebSocket: разрешить только значение websocket для заголовков обновления HTTP/1.1 (например, Upgrade: websocket ).
  • Поддержка WebSocket не требуется: не пересылать Upgrade заголовки
Какие службы затронуты (и не затронуты) по умолчанию?

Для успешной контрабанды h2c заголовок Upgrade (а иногда и заголовок Connection) должен быть успешно перенаправлен с пограничного сервера на внутренний сервер, который поддерживает обновления h2c. Эта конфигурация может выполняться на любом обратном прокси-сервере, WAF или балансировщике нагрузки. По умолчанию следующие сервисы пересылают заголовки Upgrade и Connection во время прокси-прохода, тем самым позволяя контрабанду h2c «из коробки»:
  • HAProxy
  • Traefik
  • Nuster
По умолчанию эти службы не пересылают заголовки Upgrade и Connection во время прокси-прохода, но могут быть настроены небезопасным образом (путем передачи нефильтрованных заголовков Upgrade и Connection ):
  • AWS ALB/CLB
  • NGINX
  • Apache
  • Squid
  • Varnish
  • Kong
  • Envoy
  • Apache Traffic Serve
Пример исправления для HAProxy/Nuster:

Если должны быть разрешены только обновления WebSocket:

Код:
http-request replace-value Upgrade (.*) websocket

Если никакие обновления не должны быть разрешены:

Код:
http-запрос del-header Upgrade

Пример исправления для Traefik:

Эта конфигурация промежуточного программного обеспечения заменит или удалит заголовки Upgrade по мере их появления во входящих запросах:

Код:
http:
  routers:
    routerA:
      middlewares:
        - "testHeader"
  <span style="color:#c2282e;">…omitted for brevity…</span>
  middlewares:
    testHeader:     
      headers:
        customRequestHeaders:
          Upgrade: "" # "" removes the header; set to “websocket” to hardcode the value

НАШИ РЕЗУЛЬТАТЫ ИСПЫТАНИЙ Bishop Fox's Cosmos (раньше отличались)

В рамках нашего исследовательского процесса мы тестируем недавно обнаруженные методы атак на клиентов Bishop Fox's Cosmos, управляемого сервиса, который постоянно проверяет внешние периметры клиентов. Вот уроки, которые мы извлекли, когда пытались идентифицировать случаи контрабанды h2c на большом наборе хостов:
  • Каждая конечная точка прокси-пропуска должна быть проверена отдельно. При тестировании всех активов клиентов набор результатов варьировался в зависимости от тестируемого пути ( /api/ — более распространенный путь proxy_pass , чем /). Тестирование одной произвольной конечной точки (например, /api/ ) на несколько целей менее эффективно, чем тестирование нескольких известных конечных точек (например, результатов перечисления каталогов с помощью gobuster ) на одну цель.
  • Основными ложными срабатываниями в службах с поддержкой TLS были серверы, которые ответили «101 Switching Protocols» в ответ на наш запрос на обновление h2c, но не ответили ни на один из последующих кадров HTTP/2, которые мы отправили. Вместо этого на транспортном уровне мы получали только пакеты TCP ACK и RST. Это указывало на то, что серверы могут отвечать кодом 101, но могут быть не оборудованы для связи по протоколу HTTP/2.
  • Рекомендуется протестировать как совместимые Connection : Upgrade, HTTP2-Settings , так и несовместимые Connection : Upgrade варианты заголовка соединения (опция --upgrade-only в h2cSmuggler ). Как и в случае с прокси, не все серверные части соответствовали требованиям.
Вот несколько советов по эксплуатации:
  • h2cSmuggler Перебор конечных точек с мультиплексированием HTTP/2 (параметр -i ) выполняется очень быстро и может использоваться для поиска дополнительных внутренних конечных точек.
  • См . список заголовков param-miner для вдохновения для подделки внутренних заголовков.
  • Поскольку вы обходите промежуточные прокси-серверы, в вашем запросе могут отсутствовать заголовки, ожидаемые серверной службой. Для успешного взаимодействия с внутренними службами может потребоваться раскрытие дополнительной информации посредством сообщений об ошибках или разведки.
  • Если нет элементов управления доступом, которые можно обойти, то туннелирование запросов через контрабанду h2c не предоставляет никакого дополнительного доступа (например, завершающий балансировщик сетевой нагрузки TLS может пересылать обновления, но не обеспечивает никаких средств управления доступом HTTP).
ВЫВОД
Контрабанда запросов и другие уязвимости обхода прокси-серверов выдвигают на первый план растущую проблему, влияющую на архитектуру современных веб-приложений: чрезмерную зависимость от контроля доступа на границе для гарантий безопасности. Во многих отношениях произвольные запросы, контролируемые пользователем посредством контрабанды запросов или атак с подделкой запросов, стали «захватом указателя инструкций» современных архитектур микросервисов, управляемых RPC. Поддержание стратегий глубокоэшелонированной защиты, снижение значимости контрабандных заголовков в вашей архитектуре и готовность выявлять и отклонять подозрительные запросы на серверной части помогут уменьшить влияние будущих методов атак.

Ознакомьтесь с инструментом и демонстрациями здесь: https://github.com/BishopFox/h2csmuggler .
 

Вложения

  • 1665539336927.png
    1665539336927.png
    5.2 КБ · Просмотры: 8


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх