Содержание статьи
Философия Ruby on Rails делает разработку простой и эффективной, так что неудивительно, что у фреймворка сформировалось огромное сообщество. Давай познакомимся поближе с философией этой платформы как с точки зрения архитектуры, так и с точки зрения безопасности.
«ВЕБ-РАЗРАБОТКА, КОТОРАЯ НЕ ПАРИТ»
2012–2013 годы стали черной полосой для Ruby on Rails в плане безопасности — проверке на прочность подвергся как сам фреймворк, так и проекты на его основе. В этот период над рубистами стали откровенно стебаться. Например: «Ребята, у меня такой странный баг с кешем — каждый раз, когда захожу на Hacker News, вижу новости о критических уязвимостях в руби». Другой шутник зарегистрировал домен www.didrailshaveamajorsecurityflawtoday.com. В какой-то момент злорадства стало даже слишком много. Информационная война как она есть: пхпшники (не сумевшие изучить Rails) против их более успешных (и я не только про зарплату) коллег-рубистов.
Многие, видя в заголовках обновлений SQL injection или XSS, начинали кричать на каждом углу, что рельсы — решето, а мы все — хипстеры несчастные. По факту (и я не хочу перечислять) большинство таких обновлений закрывают минорные дырки, которые можно было бы эксплуатировать в менее чем 0,01% приложений. Но были и действительно серьезные вещи.
Отправной точкой, по моему скромному мнению, стал мой взлом GitHub в марте. Я достаточно долго занимался агитацией в сообществе защиты от атак с использованием уязвимостей атак mass assignment, но безуспешно. В итоге решил продемонстрировать это на примере GitHub — разработчики GH так и не удосужились провести полный аудит, закрывая лишь отдельные дыры. Ну а остальное ты уже знаешь. После этого началась работа сообщества в области CSRF/XSS/SQLi-защиты, а кульминацией стала комбинация обнаруженных векторов атак, позволившая найти несколько Remote code execution.
Если ты ни разу не сталкивался с Ruby on Rails, то передовая веб-разработка явно не твой конек. Да, мы, рубисты, любим кидать понты. Сложно сказать, смог бы Ruby стать таким популярным без фреймворка Rails, но очевидно — своим успехом Rails полностью обязан гибкости и красоте языка Ruby. Поэтому, когда рубисты обсуждают Rails, они говорят о «тандеме» Ruby & Rails.
Слоган рельс — «Web development that doesn’t hurt», что условно можно перевести как «Веб-разработка, которая не парит». И правда, этот фреймворк прежде всего удобен для программиста. Простота, эффективность и скорость разработки в Ruby on Rails сделала его любимой платформой для разработки как в стартапах, так и в крупных компаниях. RoR начал быстро набирать популярность c момента своего появления, что связано с лаконичностью и «синтаксическим сахаром» Ruby. Разработка прототипа при должной сноровке занимает считаные дни, и переписывать заново его уже не придется. Это позволяет оперативно представить результат инвестору, запустить проект, а потом, при необходимости, легко найти новых разработчиков (разбираться в чужом, но правильно написанном Rails Way коде очень легко).
Rails определенно не подходит для создания очередного SEO-решения (сателлита, дорвея, сплога), как и для создания форума, личной странички (хотя технически такая возможность, конечно, присутствует). Зато идеально подходит для создания серьезных бизнес-проектов различного масштаба и направленности, реализующих новые идеи и решения. Конечно, такие проекты не могут не заинтересовать злоумышленников, что, в свою очередь, и объясняет рост числа атак на RoR-приложения в последнее время.
Какие проекты сделаны на рельсах? GitHub и GitLab — хранение кода, Stripe.com и recurly.com — платежные системы, Diaspora, Look At Me, Groupon, Basecamp, Hulu, Scribd, Shopify, Yellowpages.com, Danbooru и сотни других социальных стартапов, очень популярный проект-трекер Redmine и другие. Также на Ruby написан и сам rubygems.org, главный репозиторий джемов (так называются пакеты/библиотеки в мире руби).
Для начала вводный курс в идеологию фреймворка: Convention over configuration, или все нужно делать по дзену the Ruby/Rails Way. Это звучит очень круто, ведь когда новая команда разработчиков берется за доделку существующего Rails-проекта, то число WTF в секунду ниже, чем у их коллег, использующих PHP. Есть четкий подход к архитектуре приложения — использование MVC (model — view — controller) и то же самое в подходе к безопасности. Есть политика партии, тьфу, 37signals (контора — создатель фреймворка и главный евангелист), и ей нужно следовать. Бытует шутка-цитата из уст создателя Ruby On Rails, (DHH — Дэвид Хейнемейер Хэнссон), что Rails is omakase. Попросту говоря — что вам приготовили, то и ешьте.
Вернемся от философии к безопасности. Откровенно говоря, рельсы хорошо балансируют на грани между «удобно» и «безопасно» — не стесняя действия разработчика, они предоставляют защиту от основных уязвимостей из коробки. XSS, CSRF, SQL inject — рубисту просто не нужно знать значения этих слов, ведь конвенция разработки грамотно решает эти проблемы на корню.
Наконец, сердце RoR — система модулей, gems. Каждый gem хранит внутри себя код и метафайл в формате YAML. Как можно догадаться, если в этот метафайл положить уже известный RCE-exploit для YAML и загрузить такой gem на сервер Rubygems, то можно выполнять любой код в контексте главного репозитория кода руби, скомпрометировав тем самым всю экосистему. Именно это и произошло. Говорят, что админы rubygems были предупреждены за 10 дней, но никаких действий не предприняли. Чтобы продемонстрировать серьезность угрозы, 30 января был анонимно залит gem с говорящим названием «exploit». Очевидно, это была шутка некоего whitehat’а, но ради галочки людям пришлось всю неделю сверять checksum’ы джемов из бэкапов и текущих для выявления скомпрометированных библиотек. Очередное доказательство, что уязвимости надо исправлять быстро, а серьезные уязвимости — мгновенно.
Эта YAML-RCE была и остается самой серьезной уязвимостью в рельсах, затрагивающей огромное число инсталляций Redmine, GitLab и прочих редко обновляемых приложений. Определенно, она была эксплуатирована множество раз на реальных проектах как автоматическими сканерами, так и хакерами, например, были украдены биткоины у биржи Vircurex.
Тем, кто хочет познакомиться с руби поближе, я настоятельно рекомендую изучить синтаксис языка и попробовать его в повседневных задачах. Более того, популярный Metasploit Framework написан на руби и для быстрого «прототипирования» атак нет ничего лучше лаконичного руби. Начать исследования стоит с аудита кода популярных джемов типа Rails, Sinatra, Rack, ибо средний рельс-проект использует сотню-другую сторонних джемов, и в каждом из них может прятаться уязвимость, о которой никто пока не знает. Архитектура «подписывания» и sandbox’инга джемов находится только в самом зачатии, поэтому я уверен, что лично ты можешь найти множество интересных вещей в экосистеме. Удачи!
Фреймворк Ruby on Rails и его безопасность
Проведение большинства классических атак (таких как SQL injection, File inclusion, XSS, CSRF) просто невозможно в RoR, или же защита от таких уязвимостей уже включена в фреймворк по умолчанию. Поэтому для того, чтобы провести атаку на RoR-проекты, необходимо эксплуатировать специфические для RoR или самого языка Ruby уязвимости. О них и поговорим.
Особенность Ruby Regexp
Рассматривать потенциальные уязвимости начнем с анализа специфики работы Ruby с регулярными выражениями.
Поддержка регулярных выражений в Ruby реализована при помощи стандартного класса Regexp. Сами регулярные выражения являются Perl-совместимыми (PCRE). При этом у них есть одна особенность, о которой практически нигде не упоминается, — многострочный режим обработки регулярных выражений (multiline mode) включен по умолчанию и не может быть выключен с использованием каких-либо модификаторов (интересно, что при этом в Ruby также существует специальный модификатор M, активирующий этот многострочный режим обработки).
Таким образом, по умолчанию регулярное выражение /^\d\d$/ сработает не только для “42”, но и для “ANYTHING\n42\nANYTHING”. Такая ситуация возникает при любом способе создания регулярного выражения в Ruby — будь то конструктор Regexp::new или литерал %r{}.
Практика использования метасимволов ^ и $ широко распространена в других языках программирования (например, PHP, Python, Perl), рекомендации использовать именно их для работы с PCRE-совместимыми регулярными выражениями присутствуют во многих книгах и самоучителях по Ruby. Поэтому весьма велика вероятность того, что Ruby-программист использует именно эти символы вместо корректных \A и \z (или \Z), являющихся «настоящими» указателями начала и конца строки.
Рассмотрим пример сценария, реализующего эксплуатацию уязвимости отсутствия фильтрации пользовательского ввода посредством атаки XSS с использованием описанной особенности обработки регулярных выражений. В данном сценарии осуществляется выполнение JavaScript-кода из адресной строки через префикс javascript: (работает не во всех браузерах).
Найдем на сайте сценарий, обрабатывающий пользовательский ввод при помощи уязвимого регулярного выражения. Предположим, что таким местом будет значение поля, принимающего произвольное значение URL-адреса, используемое для перенаправления пользователя по данному адресу. Поместим в поле следующую конструкцию (строки разделены символом перевода строки):
javascript:exploitCode();/*
http://anyproperurl.com
*/
Данный код успешно пройдет проверку регулярным выражением с использованием метасимволов ^ и $ (например, /^https?:\/\/$/), и после щелчка по созданной ссылке выполнится функция exploitCode (при этом само значение URL попало в комментарий). Эта уязвимость может эксплуатироваться как непосредственно, так и, например, путем проведения атаки сlickjacking с попаданием клика пользователя на созданный javascript: URL.
Хакер #173. Уязвимости Ruby on Rails
В своем исследовании я установил, что данной уязвимости подвержены, например, такие крупные проекты, как tumblr.com, scribd.com, github.com, soundcloud.com, а также многие другие.
Рекомендация: используй \A\z вместо популярных, но уязвимых ^$.
CSRF
Атака CSRF — одна из любимых тем моих исследований. Я неоднократно доказывал, что CSRF — это уязвимость в протоколе HTTP и его реализации в браузерах, а не в веб-приложениях. Уже который год публикуется информация о десятках данных уязвимостей в популярных сайтах (например, YouTube, Facebook), но консорциум только отмахивается от проблемы. Но сейчас я бы хотел сказать не об этом, а о том, как обстоят дела с этой атакой и сопутствующими уязвимостями в RoR.
В рельсы встроен элегантный механизм, который позволяет разработчикам просто забыть о CSRF и наслаждаться разработкой: в пользовательской сессии хранится созданный приложением Ruby токен с именем authenticity_token. При каждом запросе пользователя хелперы для тега