Rails: критическую уязвимость ActiveStorage атаковали через 8 часов после патча

29 июля 2026 года исследователи из компании Ethiack раскрыли критическую уязвимость в ActiveStorage, компоненте Ruby on Rails 8 и новее, позволяющую удалённо читать произвольные файлы и выполнять код при обработке вариантов изображений. Уязвимости присвоили номер CVE-2026-66066 и неофициальное имя KindaRails2Shell. Изначально в GitHub Security Advisory не было оценки серьёзности, и утром 29 июля команда безопасности Rietta (обслуживает клиентов, включая организации с медицинскими данными по HIPAA и госструктуры штатов) отнесла обновление к плановым. К вечеру того же дня уязвимости присвоили оценку 9.5 из 10 по шкале CVSS, и Rietta объявила экстренный режим: подготовила и прогнала через полный набор автотестов патч для всех затронутых Rails-приложений клиентов и к 23:09 по восточному времени США развернула его в проде, разослав уведомления клиентам.

Один из клиентов, государственное учреждение штата (название не раскрывается), тем не менее подвергся атаке. Первая попытка эксплуатации зафиксирована в 7:10:25 утра по восточному времени 30 июля, то есть через 8 часов 1 минуту после того, как Rietta применила патч у этого клиента, более чем за 11 часов до публикации официального инструментария для расследования от команды Rails и почти за сутки до полного технического разбора от Ethiack. Атака использовала специально сформированный повреждённый файл формата BMP. Публичный proof-of-concept (PoC) с точно таким же приёмом, эксплуатацией через испорченный BMP, был выложен на GitHub в 21:47:30 по UTC 29 июля, то есть более чем за 5 часов до того, как патч Rietta был полностью развёрнут (в 3:09 по UTC 30 июля), и за 13 часов 22 минуты 55 секунд до самой атаки. Андре Баптиста из Ethiack, один из первооткрывателей уязвимости, в переписке с автором поста в X указал на это совпадение техники. Автор подчёркивает: совпадение, это корреляция, а не доказательство, что атакующий использовал именно этот PoC, а не собственный инструмент; тем не менее по цепочке рассуждений это наиболее простое объяснение из всех, что согласуются с фактами.

По мнению автора, произошедшее, не история об одном исключительно быстром взломщике, а признак того, что экосистема исследователей уязвимостей в целом опережает согласованные сроки раскрытия (coordinated disclosure). Баптиста подтвердил эту динамику напрямую: команда Rails выпустила свой инструментарий для расследования на четыре недели раньше изначально заявленной даты (28 августа) именно потому, что несколько независимых исследователей уже реконструировали атаку и опубликовали PoC-код, по данным независимого отслеживания инцидентов от Rapid7.

Одиночная попытка 30 июля не переросла сразу в масштабную кампанию, следующих обращений к этому клиенту несколько дней не фиксировалось. Устойчивая и адаптирующаяся волна сканирования началась отдельно, 3 августа в 1:01:05 ночи по восточному летнему времени, уже с использованием замаскированного под PNG файла вместо BMP. С этого момента попытки продолжались ежедневно на протяжении всего августа, с ротацией IP-адресов по всему миру и разными user-agent, включая поддельную маскировку под краулер Claude-SearchBot от Anthropic и подозрительно откровенный user-agent, прямо называющий CVE, на которую идёт проверка. Клиент действительно пользуется услугами по оценке защищённости, но, по словам автора, ни изолированная попытка 30 июля, ни последующая кампания с ней не связаны, это было неавторизованное, непрерывное прощупывание уязвимости. Все попытки эксплуатации провалились именно в той точке, которую закрывал патч; Rietta дополнительно усилила защиту: более строгую валидацию загружаемых файлов, автоматическую блокировку повторных сканирований и централизованные оповещения.

Автор формулирует практические рекомендации для команд, работающих с Rails: относиться к любому отдельному security-релизу зависимости как к срочному ещё до присвоения оценки CVSS, поскольку присвоение оценки может отставать от реального риска на много часов; проверить, использует ли приложение ActiveStorage, и если да, патчить немедленно; заранее, до инцидента, оформить полномочия на экстренное изменение в обход обычного цикла согласования; запускать ежедневное автоматическое сканирование зависимостей (bundler-audit) и статический анализ кода Rails-специфичных уязвимостей (Brakeman); относиться к обработке файлов, загружаемых пользователями, как к отдельной границе угроз, проверять тип файла по магическим байтам, а не по заголовку content-type, ужесточать политику библиотек обработки изображений (например, policy.xml у ImageMagick) и по возможности выполнять такую обработку в песочнице с урезанными привилегиями; использовать веб-файрвол (WAF, например Cloudflare или AWS WAF & Shield) как один из слоёв защиты, а не единственный; наращивать автоматическое тестирование, чтобы можно было быстро и уверенно катить патчи под давлением; и регулярно просматривать мониторинг исключений, включая неуспешные запросы.

Ключевые факты

  • Критическая RCE-уязвимость ActiveStorage в Ruby on Rails (CVE-2026-66066, KindaRails2Shell) получила оценку 9.5/10 по CVSS вечером 29 июля 2026 года
  • Компания Rietta развернула экстренный патч для всех клиентов в тот же день, но у одного из клиентов, госучреждения штата, первая атака (через испорченный BMP-файл) случилась уже через 8 часов 1 минуту после патча
  • Публичный PoC с той же техникой (испорченный BMP) был выложен на GitHub ещё за 5+ часов до завершения развёртывания патча Rietta и за 13 часов 23 минуты до самой атаки
  • Официальный технический разбор от команды Rails и от Ethiack вышел уже после первой атаки, эмбарго на раскрытие деталей на практике не сработало
  • С 3 августа началась устойчивая ежедневная кампания сканирования с ротацией IP по всему миру, включая поддельный user-agent под краулер Claude-SearchBot от Anthropic

Почему это важно

История показывает разрыв между теорией и практикой скоординированного раскрытия уязвимостей (coordinated disclosure): производитель обещал полные технические детали не раньше чем через месяц, но публичный код исправления оказался достаточной подсказкой для рабочего эксплойта уже через несколько часов после выхода патча, быстрее, чем сама компания успела закончить экстренное развёртывание патча у части клиентов. Разрыв между «патч вышел» и «эксплойт работает» измерялся часами, а не неделями.

Кому это важно

В первую очередь, командам, эксплуатирующим приложения на Ruby on Rails с компонентом ActiveStorage, особенно там, где обрабатываются чувствительные данные: медицинские организации, подпадающие под HIPAA, и государственные структуры. Также релевантно любой компании, которая полагается на оценку CVSS как на сигнал срочности, и специалистам по безопасности, отвечающим за процесс патч-менеджмента и загрузку пользовательских файлов.

Как это применить

Автор перечисляет конкретные шаги: патчить security-релизы как срочные ещё до присвоения оценки CVSS; проверить использование ActiveStorage в своих Rails-приложениях; заранее оформить полномочия на экстренное изменение в обход обычного согласования; поставить ежедневное автосканирование зависимостей (bundler-audit) и статический анализ кода (Brakeman); обрабатывать пользовательские загрузки как отдельную границу угроз, проверка по магическим байтам, ужесточение политики библиотек обработки изображений, песочница с урезанными правами; использовать WAF как один из слоёв защиты, а не единственный; расширять автоматическое тестирование и регулярно просматривать мониторинг исключений.

Можно ли доверять

Материал, блог самой компании Rietta, экстренно патчившей клиентов, поэтому у неё есть очевидный интерес представить свою скорость реакции в выгодном свете. При этом в тексте приведены точные метки времени по каждому шагу, ссылка на независимое отслеживание инцидента от Rapid7 и прямая цитата одного из первооткрывателей уязвимости (Ethiack), подтверждающая общую динамику с их стороны. Сам автор явно оговаривает: совпадение техники (испорченный BMP) между публичным PoC и первой атакой, это корреляция, а не доказательство, что атакующий использовал именно этот PoC.

Риски и подводные камни

Оценка CVSS обновилась не сразу и первоначально привела к недооценке срочности патча, полагаться только на неё опасно. Сигнатурные правила WAF, по словам автора, часто пропускают новую полезную нагрузку, спрятанную в испорченном файле, так что WAF не заменяет патч и валидацию загрузок. Сохранившийся текст источника обрывается на середине списка рекомендаций, поэтому часть практических советов в пересказе отсутствует не из-за упущения, а потому что их нет в доступном тексте.

«Мы во многих случаях сдерживали технические детали, чтобы дать защитникам больше времени, но события развиваются слишком быстро.»

— Андре Баптиста, Ethiack