Содержание статьи
Сегодня существует немало различных программ bug bounty, с помощью которых можно неплохо заработать на поиске уязвимостей в софте с открытыми исходниками. В браузерном мире сама Netscape инициировала это движение уже в далеком 1995 году, а затем Mozilla и Google подхватили тенденцию. Прямо сейчас я научу тебя, как выжать баксы из Google Chrome.
Об инициативе Google
Прежде чем хвататься за поиск багов и написание отчетов, с моей стороны было бы корректно рассказать читателю, с чем мы имеем дело. А дело мы имеем с Google Vulnerability Reward Program. В рамках этой программы корпорация добра предлагает денежное вознаграждение всем, кто желает помочь проекту Google Chrome в повышении уровня безопасности. При этом можно не только получить деньги, но и засветиться в списке Hall of Fame, куда включают всех исследователей, которые так или иначе помогли в исправлении багов. Чтобы попасть в него, вовсе не обязательно претендовать на кеш, достаточно быть искренне заинтересованным в оказании помощи, активно участвовать в проекте и положительно себя проявить.
Эта программа, запущенная в январе 2010 года, изначально предусматривала три уровня вознаграждения: $500, $1000 и $1337. Через полгода в программу, отметившую мини-юбилей, были внесены изменения, в том числе и введен четвертый уровень вознаграждения — теперь за обнаружение критического бага дают $3133,7, а за отчет хорошего качества — $1000 (что это за отчет, ты узнаешь, прочитав статью до конца).
Лидером команды безопасников Chrome является небезызвестный исследователь Chris Evans. Вместе с Adam Mein он и раздает кеш налево и направо. Первым человеком, которому выплатили сумму, соответствующую новому «элитному» уровню, стал Сергей Глазунов, нашедший уязвимость «Browser crash in HTML5 speech UI» (crbug.com/68666). Правда, не всегда стоит рассчитывать на получение заявленной суммы. Вознаграждение может оказаться и больше. 🙂 Например, недавно человеку под ником wushi из команды team509 выплатили не 500, а 509 долларов за найденную уязвимость просто ради шутки, из-за символичного названия. Так что ребята в Google тоже не без юмора.
В зависимости от типа приложения и его лицензии применяются разные методы поиска уязвимостей. Но браузер с открытыми исходниками предоставляет нам возможность пользоваться абсолютно всеми доступными методами, что увеличивает шансы обнаружить баг. В данном случае я считаю целесообразным прибегнуть как минимум к следующим методам поиска уязвимостей: фаззинг, изучение исходников, бинарный анализ, «переоткрытие» багов, ручной поиск с тестированием. Последние два метода могут смутить своими названиями, однако далее мы подробно поговорим о них.
Статистика Hall of Fame
На сегодняшний день на странице Google Security Hall of Fame висит длинный и регулярно пополняющийся список хакеров. Но обычно там можно встретить одних и тех же известных багхантеров, всего около 60 человек (включая исследовательские группы и компании). За всё время существования инициативы было выплачено порядка 270 тысяч долларов!
Фаззинг
Думаю, понятие фаззинга всем известно, поэтому не буду повторяться, а лишь опишу некоторые моменты, касающиеся браузеров. Здесь, прежде всего, следует помнить о том, что не ты один ищешь уязвимости — я смело предположу, что это делают тысячи людей по всему миру с помощью компьютеров и так называемых фаззинговых ферм. Так что это самая настоящая гонка! И чтобы не отставать от других, твоя программа-фаззер должна обладать следующими свойствами:
- оригинальностью;
- высокой скоростью работы (количество уникальных тестов в единицу времени);
- способностью воспроизведения крашей (логирование).
Под оригинальностью я в первую очередь подразумеваю какие-либо особенности, отличающие твой фаззер от тех, которые находятся в публичном доступе. Таким образом, лучше написать свой собственный фаззер, хотя, конечно, можно взять и любой доступный, но его необходимо модифицировать так, чтобы он мог генерировать уникальные тест-кейсы. Как ты понимаешь, нет никакого смысла в том, чтобы всем дружно фаззить одни и те же баги. Да, можно найти какой-нибудь всеми забытый фаззер и использовать его. Но много ли будет проку от инструмента, которым по какой-то причине никто не пользуется?
Дополнительный вклад в оригинальность вносит выбор исследуемого компонента. Практически любой современный браузер представляет из себя этакий мультимегакомбайн — чего туда только не понапихано, чтобы усладить нежную душу веб-разработчика или дизайнера. Ни один вендор также не хочет отставать в гонке на соответствие требованиям W3C, теряя из-за этого некоторую долю рынка, поэтому вендоры стремятся реализовывать в своих творениях абсолютно все современные фичи. Тут еще, конечно же, встает вопрос выбора между скоростью внедрения и ценой за эту скорость. Как говорится, поспешишь — людей насмешишь. В нашем случае же поспешишь — багхантеров накормишь. 🙂 К таким фичам относятся CSS 3, HTML 5, DOM, SVG, Canvas, Audio/Video, WebGL, Drag'n'Drop, всякие хранилища и прочее и прочее. Что касается самого Chrome, то там есть и собственные разработки, например формат картинок WebP.
Хакер #157. Деньги на багах в Chrome
Изучение исходников
В случае с опенсорсными браузерами можно получить исходники и искать уязвимости непосредственно в миллионах строк кода, перебирая всё подряд, или же целенаправленно исследовать какой-либо компонент, допустим XML-парсер. Однако этот метод более трудоемкий, чем фаззинг. Тут нужны усидчивость и желание рыться в исходниках часами напролет, а также уверенные знания C++ (их уровень должен быть не ниже, чем у тех ребят, которые пишут данный браузер). Я бы не слишком надеялся, что в коде удастся найти какие-либо опечатки или недочеты, хотя и это не исключено. К тому же где гарантия того, что тебя, после того как ты потратишь месяц на копание в коде, за пять минут не обойдет чей-нибудь фаззер, написанный на коленке за пару часов? Если уж на то пошло, то процесс было бы неплохо автоматизировать с помощью использования статических анализаторов кода, а только лишь после этого подключать голову. Но ознакомление с исходниками в любом случае не повредит.
Переоткрытие багов
Что значит «переоткрытие багов»? Очень просто — листаем старые уязвимости и проверяем, насколько хорошо они исправлены. Например, уязвимость в Mozilla Firefox с идентификатором CVE-2010-0179, позволяющая выполнять произвольный код в Firebug, была переоткрыта, после чего ей присвоили еще и идентификатор CVE-2010-3773. Да, хоть и редко, но такое бывает — уязвимости, которую разработчик плохо исправил, присваивают еще один идентификатор. Несмотря на то, что таким способом много уязвимостей не найдешь, анализ старых багов помогает понять, где разработчики чаще всего ошибаются и на чем следует заострять внимание. К тому же этот способ позволяет попрактиковаться в изучении уязвимостей на реальных примерах в исходниках. На баг-трекерах Mozilla и Webkit полным-полно описаний уязвимостей как от разработчиков, так и от ZDI, так что очень советую туда заглянуть. Лично я регулярно посещаю эти злачные места.
К методам реинкарнации жуков относится исследование баг-трекера или чейнджлога и поиск еще не исправленных уязвимостей в различных браузерах. Несмотря на то что баги, которые были признаны критическими с точки зрения безопасности, обычно закрывают от публичного доступа, и тикет получает статус public только после выхода патча, всегда существует вероятность найти нечто интересное. К Chrome, конечно, это относится в меньшей степени, так как команда его разработчиков очень быстро реагирует на обнаруженные ошибки и исправляет их. Другое дело Safari — они подолгу тянут с исправлениями, и поэтому есть шанс в определенный промежуток времени найти уязвимость, написать сплойт и продать его.
Бинарный анализ и ручной поиск
Бинарный анализ имеет свои преимущества даже при наличии исходников, несмотря на всю его сложность. Уровень исходников и бинарь — это два совершенно разных мира. В первом случае мы оперируем более абстрактными понятиями, а во втором — уже конкретными вещами. Программист пишет код в соответствии со своими представлениями о том, как он должен работать, а хакеры видят, как код работает в действительности. Конечно, попытка проследить логику работы какого-либо куска кода в ассемблере, имея на руках исходники, не оправдывает себя. Здесь имеет смысл обращать внимание на такие низкоуровневые процессы, как чтение из определенных участков памяти или запись в них. К тому же для оптимизации программы компиляторы могут менять код не предусмотренным программистом образом. В общем, то, что ты видишь, — это не то, что будет исполняться. Конечно, так или иначе придется делать бинарный анализ, но тут всё уже зависит от того, как ты ищешь уязвимости и, соответственно, с какой целью реверсишь бинарь.
Ручной поиск с тестированием проводится в случаях, когда автоматизировать процесс поиска уязвимостей сложно. Допустим, это может быть проверка корректной работы политик безопасности в каких-либо специфических условиях или при использовании новых технологий, поиск багов, которые возникают, когда пользователь выполняет определенную комбинацию действий через интерфейс. Ну вот как такое нафаззить? Да никак, поэтому тут можно или чисто случайно найти баг, что одному ресерчеру удается не так часто, а можно и целенаправленно исследовать определенную технологию, применяя нестандартное мышление хакера.
Тестовая платформа для Chrome
Если ты собрался тестировать Chrome, то не забывай, что он работает на многих ОСях: Windows (только 32 бита), Linux и Mac. Существует вполне весомая причина протестировать его на всех доступных тебе системах: какой-либо баг может не показать себя на одной операционке, зато успешно проявится на другой. Например, недавно был обнаружен крайне интересный баг в библиотеке GNU C, который проявлялся исключительно под Линуксом (crbug.com/48733). Также попробуй протестировать максимальное количество браузеров. Одновременно могут стоять только canary и любая другая версия, но не dev, beta или stable вместе (кеш можно получить за версии stable, beta или dev). Таким образом, после простых расчетов получаем, что для фаззинга у нас есть как минимум 15 вариантов сборок браузера всего лишь от одного производителя. Это существенно повышает шансы найти уязвимость, а если у тебя имеется возможность фаззить все это одновременно, то вообще прекрасно — процесс ускоряется в разы! Можно исследовать готовый бинарник, а можно и самому собрать браузер. Последний вариант имеет свои преимущества, о которых я сейчас и расскажу.
Google Chrome можно собрать с ASan. Что такое ASan? Это сокращение от Address Sanitizer, который представляет собой еще один проект от гугловцев, призванный заменить Valgrind. Он работает гораздо быстрее Valgrind. Если последний замедляет программу в десять раз, то ASan — всего в два. Этот инструмент позволяет обнаруживать уязвимости типа use-after-free, overflow/underflow кучи и стека, а также другие багги, связанные с повреждением памяти. Кроме того, ASan находит больше багов, чем старый добрый Valgrind. Он заменяет malloc()/free() на свои функции, которые «маркируют» зоны вокруг используемой области памяти. Затем компилятор генерирует код, который проверяет меченые зоны. Если запрошенный адрес помечен, выводится ошибка. Советую заглянуть на сайт проекта — там представлено достаточно примеров, которые позволяют понять, как работает данный инструмент.
Подготовленный таким образом Chrome сильно облегчает задачу определения типа уязвимости, будь то heap buffer overflow, use-after-free или что-то другое. Для этого достаточно посмотреть в логи ASan. Однако не все так просто. В процессе компиляции браузера потребуется хорошее интернет-соединение для регулярной синхронизации исходников, а также довольно мощный компьютер для сборки и последующего анализа краша. Но обо всем по порядку.
Прежде чем приступить к делу, хочу сказать, что я использовал Ubuntu 10.10, x64 и поэтому не могу знать об особенностях сборки браузера на других системах.
Сборка браузера
Для начала давай скачаем исходники браузера со страницы проекта, а затем распакуем их. Теперь необходимо исправить файл .gclient, добавив туда следующие строки:
"custom_deps" : {
"src/third_party/asan":
"http://src.chromium.org/svn/trunk/deps/third_party/asan",
Это укажет конфигуратору, что нужно использовать ASan. Для сборки ASan необходим Clang (bit.ly/mf7cuG). После его установки выполняем в командной строке сценарий ./build/install-build-deps.sh. Этот скрипт разрешит нужные зависимости и наведет порядок там, где это необходимо. Теперь следует настроить переменные окружения, выполнив следующие команды:
export PATH=$HOME/depot_tools:$PATH
cd src
ASAN=`pwd`/third_party/asan
ASAN_BIN=$ASAN/asan_clang_Linux/bin
BLACKLIST="-mllvm -asan-blacklist=$ASAN/asan_blacklist.txt"
CC="$ASAN_BIN/clang $BLACKLIST"
CXX="$ASAN_BIN/clang++ $BLACKLIST"
GYP_DEFINES='asan=1 linux_use_tcmalloc=0 release_extra_cflags=\
"-g -O1 -fno-inline-functions -fno-inline" ' gclient runhooks
Команда для сборки самого браузера выглядит вот так:
make -j16 BUILDTYPE=Release CC="$CC" CXX="$CXX" CC.host="$CC" \
CXX.host="$CXX" LINK.host="$CXX" chrome
На моем компьютере сборка заняла меньше часа. Но, как уже было упомянуто выше, этот процесс весьма требователен к конфигурации, поэтому советую выделить не меньше 50 Гб на жестком диске, как минимум 12 Гб оперативной памяти и использовать мощный процессор, чтобы сборка не затягивалась.
Ищем баги
Если браузер собрался успешно, то запускаем его с такими параметрами:
ASAN_OPTIONS=stats=1 out/Release/chrome --no-sandbox 2>&1 |\
third_party/asan/scripts/asan_symbolize.py | c++filt
Браузер запустится без песочницы, все ошибки будут перенаправлены на вход специального фильтрующего скрипта, который отвечает за символы. Имей в виду, что утилита addr2line, которую использует этот скриптом, пожирает огромное количество памяти во время работы (у меня на нее уходило вплоть до 9 Гб). В принципе, совсем необязательно запускать браузер вместе с парсерами и инструментами для сборки статистики, можно запустить и так:
out/Release/chrome --no-sandbox
Теперь, когда ты научился правильно собирать тестовую платформу, настало время выбрать способ для поиска багов. По понятным причинам я не буду приводить здесь конкретные рецепты по багхантингу и перечислять соответствующие мануалы, но для начала посоветую остановиться на фаззинге и выбрать правильный софт (если, конечно, ты все-таки не захотел или не смог использовать свои собственные наработки). На данный момент доступно несколько достойных внимания публичных фаззеров браузеров: crossfuzz, reffuzz, Canvas fuzzer от Michal Zalewski, jsfunfuzz от Jesse Rudermann, BF от Jeremy Brown. У всех перечисленных фаззеров разные принципы работы: фаззинг DOM, мутирование HTML-документа, фаззинг грамматики JavaScript, фаззинг canvas и WebGL. Большая часть этих фаззеров отработала свое и вряд ли сможет найти новые уникальные уязвимости — всё требует доработки. Но разработчики браузеров продолжают развивать некоторые фаззеры, например jsfunfuzz. Подробно описывать каждую из перечисленных программ было бы нецелесообразно, так что советую просто взять их с нашего диска и самостоятельно попробовать в деле.
Вернемся к нашему браузеру. После выхода новой сборки ты можешь обновить исходники с помощью команды "./gclient sync". Затем следует повторить вышеописанные операции для поиска багов. Чтобы не вводить каждый раз все команды при обновлении браузера, я использую простой bash-скрипт, который можно также найти на диске. Однако далеко не всегда полезно синхронизироваться, зачастую лучше проверить состояние проекта на странице bit.ly/s9wt5F. Если вверху висит статус Open, то можно качать сорцы, если Closed, то Chrome может и не собраться. Информацию эта страница получает от ботов, которые регулярно в автоматическом режиме собирают браузеры в разных системах.
Вероятно, тебя интересует, каковы шансы найти уязвимость в таком браузере, как Chrome. Так вот, эти шансы весьма и весьма неплохи. За одну неделю фаззинга в Chrome мне удалось найти четыре уязвимости: одну DoS и три типа use-after-free. В то время я фаззил без ASan, поэтому предполагаю, что вполне мог упустить часть уязвимостей из-за сложности анализа или нехватки времени.
Топ-5 исследователей Google Chrome
- Сергей Глазунов, 54 уязвимости.
- miaubiz, 49 уязвимостей.
- Aki Helin, 24 уязвимости.
- kuzcc, 22 уязвимости.
- Christian Holler, 19 уязвимостей.
Жук пойман, что дальше?
Итак, допустим, ты нашел баг в Chrome. Не спеши сразу же о нем сообщать! Из обычного бага можно выжать гораздо больше, чем если просто раскрыть разработчикам свой Proof-of-Concept. Тут есть масса нюансов, о которых нужно обязательно рассказать. Для начала необходимо понять, является ли обнаруженный баг настоящей уязвимостью или нет.
В принципе, на странице проекта указано, какие именно багги не являются уязвимостями: DoS, OOM — баги истощения памяти, Stack exhaustion — истощение стека (например, когда функция попала в рекурсию). На всё остальное — переполнение буфера или кучи, use-after-free и прочие известные нам баги — следует обращать внимание. Если из-за DoS падает весь браузер, то ее стоит пометить как Security (в багтраке такой баг будет помечен как некритичный). Но большинство багов — это действительно только баги, поэтому, особенно если долго занимаешься багхантингом, перестаешь радоваться при виде очередного «Aw, Snap!». Иногда Chrome принудительно убивает процесс, чтобы избежать всяких неприятностей типа истощения памяти. Самая популярная уязвимость среди браузеров — это use-after-free, попытка использовать указатель на память после того, как ее уже освободили. Баги повреждения памяти хорошо ловить инструментами типа Valgrind или ASan. Это быстро и удобно, но можно, конечно, использовать и отладчик gdb или WinDbg. Под виндой я использую WinDbg — все нужные символы доступны с сервера проекта. И сразу предупрежу начинающих — если в стеке вызовов содержится много строк типа RelaunchChromeBrowserWithNewCommandLineIfNeeded, то это значит, что с символами непорядок, их нужно перезагрузить:
!sym noisy
.reload /d /f /o
После того как ты определил, что некий баг — это не просто краш таба, а самая настоящая уязвимость, можешь отсылать отчет. А можешь и не отсылать. Дело в том, что оценка твоей уязвимости напрямую зависит от того, насколько ты облегчишь жизнь разработчикам. Чем проще понять, в чем суть бага, тем быстрей его исправят. В противном случае процесс выпуска релиза затянется, а ты не скоро получишь свой кеш. Образец, который ты собрался посылать, должен быть максимально урезан и содержать только то, что крашит таб или браузер. Так легче локализовать баг и понять, что именно вызывает краш. Да и отладка, конечно же, ускоряется и упрощается.
Итак, красивый сэмпл есть, но к нему необходимо еще и описание. Без излишних эмоций и лирики нужно описать то, как заставить образец крашить браузер. Или же, если там всё и так ясно, можно просто написать, что при загрузке приаттаченного файла происходит то-то и то-то. Ну, или не файла, всё зависит от того, что ты нашел. Лучше всего, если ты сам понял суть бага и можешь четко и грамотно описать, где находится проблемный участок кода. Это еще один шанс повысить вознаграждение и избавить разработчиков от лишней работы. Реально качественный отчет от Chris Rohlf оценили в целую штуку, хотя он и касался бага, который создает среднюю угрозу. Не знаю, что тут еще добавить, видимо, стоит просто открыть и почитать этот сабмит по адресу crbug.com/63866. Однако здесь не стоит тянуть время, так как кто-нибудь может описать уязвимость раньше тебя. Однажды такое произошло и со мной. Сейчас я пишу эти строки, а чуть раньше на мой ящик пришло сообщение, что новая уязвимость, о которой я сообщил, является дубликатом. Уязвимость тянула на критический уровень. К сожалению, я опоздал всего на пару дней, и кеш получил человек, первым сообщивший о баге. Такие дубликаты сливают (делают merge) с ранее обнаруженной уязвимостью. Да, обидно, но ничего не поделаешь — не в первый и не последний раз, есть куча других жуков, которые скучают по нам. И вот, наконец-то, мы сообщили о своей первой уязвимости, сидим и ждем. Нет, не ждем, а продолжаем искать другие уязвимости. Обычно на сообщение реагируют в течение суток, затем констатируют критичность уязвимости и подтягивают соответствующих разработчиков, которые начинают процесс устранения бага и разработки патча.
Получение кеша
Это одновременно и приятный, и муторный процесс. Точных сроков получения вознаграждения не существует, так как всё зависит от того, на каком этапе планирования релиза браузера ты отправил сообщение о баге, а также от того, что он собой представляет. Бывает так, что уязвимость, которую ты нашел, не так-то просто исправить, ошибка может затрагивать сразу несколько компонентов и требовать от разработчика тщательной проверки. Теперь предположим, что тебе уже пообещали выплатить определенную сумму. Вернее, в баг-трекере указали лейбл, например reward-500. Ты также увидишь стандартный текст (Boilerplate text) с предупреждением о том, что до выхода исправления нежелательно разглашать подробную информацию об уязвимости, иначе это может привести к невыплате вознаграждения. Затем тебе нужно дождаться, когда с тобой свяжется Chris Evans и сообщит о дальнейших действиях — он дает ссылки на форму, которую нужно заполнить, чтобы стать подрядчиком Google. Ужасная форма, я тебе скажу. Во-первых, она на английском, что, может, не так уж и страшно, во-вторых, там присутствует множество полей, которые не так-то просто заполнить. К тому же, если ты не гражданин США, то тебе придется заполнить еще и специальный PDF-файл, отсканировать его и отправить по мылу. В этих формах следует указать информацию о реквизитах твоего банковского счета и некоторую другую персональную информацию вроде почтового адреса, телефона и т. д. Затем, в зависимости от того, насколько быстро ты справишься и когда отреагирует человек, который управляет тикетами, тебя примут в систему Google. Заполнять больше ничего не понадобится. Через какое-то время после регистрации тебе сообщат, что деньги находятся в системе перевода.
WWW
- список инициатив, где можно получить кеш за уязвимости;
- таблица возможностей браузеров;
- историческая новость от Netscape;
- Hall of Fame;
- проект ASan;
- исследовательская работа «How Open Should Open Source Be?»;
- интересная работа «Grammar-Based Interpreter Fuzz Testing».
Домашнее задание
Надеюсь, мне удалось заинтересовать тебя ресерчем Google Chrome, ведь Hall of Fame всегда ждет новых исследователей. Для начала посети баг-трекер Хрома — обещаю, что там не соскучишься. На баг-трекере можно найти и полезные комментарии от команды безопасников, и анализ уязвимостей, и немало смешных перлов от пользователей. Полагаю, я привел достаточное количество аргументов, чтобы мотивировать тебя на поиски уязвимостей в Google Chrome.