В Google решили опубликовать статью о взломе браузера Google Chrome, который был грамотно осуществлён на мероприятии Pwn2Own в марте этого года. Все ошибки были устранены разработчиками браузера в первые 24 часа.
Один из участников, скрывающийся под ником Pinkie Pie, провёл атаку с помощью шести ошибок, найденных в разных частях браузера Google Chrome, запустив целую цепочку ошибок, он смог получить удалённый доступ к компьютеру для выполнения произвольного кода.
Как же взломщик смог получить такой результат? Мы пройдём все этапы этого занимательного цикла.
Первым делом была использована ошибка в работе Prerender (1), данный механизм отвечает за первоначальную загрузку страниц, которые с большой вероятностью может посетить пользователь, в фоновой вкладке чтобы затем сразу их отобразить (в Google эту возможность трактуют примерно так "уменьшаем время ожидания загрузки страниц пользователем за счёт специального алгоритма предвыборки, предзагрузки и отрисовки страниц", а реально в глазах пользователей при удачном нажатии по ссылке уже предзагруженной страницы это звучит так "Вау, как быстро Хром загружает странички").
После загрузки веб-страницы prerender отключает плагины, сделано это для блокировки звуков и других возможных действий, которые могут отвлекать пользователя. Как оказалось браузер отключает только часть плагинов, из-за недосмотра разработчиков происходит запуск Native Client, который по идее может запускаться только в установленных расширениях и приложениях.
Полученный доступ к запуску Native Client сам по себе мало что даёт, так как плагин запускается в более строгой песочнице нежели обычный HTML-контент. Но у плагина Native Client есть один довольно существенный плюс, есть доступ к командным GPU-буферам. Данные буферы используются для исполнения графических операций в GPU-процессе.
Итак, зная это, Пинки использует вторую ошибку в обработке инструкций GPU (2):
static uint32 ComputeMaxResults(size_t size_of_buffer) { return (size_of_buffer - sizeof(uint32)) / sizeof(T); }
Ошибка находится в переменной size_of_buffer, значение которой может быть меньше чем результат функции sizeof(uint32), а это в свою очередь приводит к получению очень большого числа на выходе.
После полученный результат используется в следующем коде:
static size_t ComputeSize(size_t num_results) { return sizeof(T) * num_results + sizeof(uint32); }
Стоит отметить, что все этапы реализации выполнения ошибки пока закрыты для соблюдения безопасности.
Как следствие произошло переполнение и функция вместо верного значения возвращает ноль, освобождая место под новое значение вместо sizeof(uint32). Используя это, Пинки записал восемь байт в конец последнего буфера. Буфер в данном случае является одним из передающих графических буферов, которые находятся в адресных пространствах двух процессов и используется для передачи данных между Native Client и GPU-процессом.
Встроенный распределитель адресного пространства Windows помещает буферы в случайных местах памяти (для предотвращения атак с помощью переполнения буфера и других методов), но с помощью Native Client можно непосредственно управлять размером буферов и их размещением в адресном пространстве. Таким образом, появляется довольно обширный контроль за тем, где будет произведена перезапись данных в GPU-процессе.
А вообще, Pinkie Pie это задорная лошадка
Следующая цель Пинки должна была соответствовать критерию: кусок памяти должен быть расположен в диапазоне, доступном для перезаписи и в котором можно изменить первые восемь байт. Для этого были использованы GPU-блоки, это другой IPC-примитив, передаваемый из GPU-процесса в Native Client процесс. Блоки представлены в виде дерева, первые восемь байт которых являются указателями на другие ветки дерева.
Перезаписав первые восемь байт, Пинки может указать на поддельную древовидную структуру, которую он создал в одном из буферов передачи. Используя поддельное дерево, Пинки может читать и писать данные в различных адресных пространствах GPU-процесса. Комбинируя с некоторыми предсказуемыми адресами пространства в Windows, это позволило ему создать цепочку атак ROP (Return-to-libc attack) и выполнять произвольный код в GPU-процессе.
В нормальном случае GPU-процесс находится в песочнице, но менее строгой, чем у Native Client- или HTML5-процессов. Поэтому у GPU-процесса присутствуют некоторые права, такие как возможность перечислений и подключения к нумерованным каналам, используемым в IPC (Inter-process Communication) слое браузера Chrome. Обычно это не является ошибкой, но в данном случае это следующая использованная ошибка (3), Пинки нашёл небольшое окно перед тем как браузер запускает новое средство отрисовки, в этот момент GPU-процесс может заметить IPC канал существуемого отрисовщика и подсоединиться сначала к нему, тем самым GPU-процесс запускает отрисовщик.
Хотя отрисовщики в браузере выполняются в ещё более строгой песочнице нежели GPU-процесс, есть особый класс средств визуализации, которые имеют IPC интерфесы с повышенными правами. Эти отрисовщики не применяются для веб-контента, но используются в обработке расширений и страниц настроек. Теперь Пинки использует следующую найденную ошибку (4), которая позволяет непривилегированному отрисовщику запустить управление в одном из привилегированных средств визуализации и использовать это действие для запуска менеджера расширений.
Как только начинается выполнение менеджера расширений Пинки использует ещё две ошибки для полного выхода из песочницы. Предпоследняя ошибка (5) позволила ему указать путь загрузки для расширения из средства визуализации менеджера расширений.
Заключительная ошибка (6) помогла обойти запрос подтверждения на установку распакованного NPAPI плагина. С этими двумя ошибками Пинки смог установить и запустить свой собственный NPAPI плагин, который выполнялся вне песочницы с полным набором пользовательских полномочий.
Примерно вот таким долгим процессом автор уязвимости заработал себе 60000 долларов США и смог взломать браузер Google Chrome. Все ошибки, присутствующие в данном материале, уже давно устранены в браузере. Но так как присутствуют различные проекты на основе Chromium, некоторые ошибки пока что полностью не освещены для предотвращения возможных атак.
Если Вам было интересно, то следующим материалом будет подробно рассказано об эксплойте, выполненном Сергеем Глазуновым, и состоящим примерно из 10 различных ошибок. На данный момент информация об ошибках также ещё недоступна для общественности, хоть ошибки и исправлены в браузере, всё же присутствует довольно широкий ряд продуктов от различных компаний, в которых могут ещё присутствовать некоторые ошибки.