Хакер #305. Многошаговые SQL-инъекции
В блоге разработчиков браузера Chromium опубликованы подробности истории двухмесячной давности. В марте 2012 года в рамках хакерского конкурса Pwnium было получено два качественных эксплойта для Chrome. Авторы обоих эксплойтов — PinkiePie и Сергей Глазунов — получили по $60K в качестве вознаграждения от компании Google.
В первой части детально рассказано об эксплойте PinkiePie. История довольно интересная: чтобы добиться исполнения произвольного кода и взломать песочницу Chrome, ему пришлось виртуозно использовать цепочку из шести багов.
Сначала использовался баг (117620) в системе пререндеринга Chrome, чтобы загрузить модуль Native Client на веб-странице. Пререндериг — функция оптимизации производительности, которая предусматривает скачивание и предварительный рендеринг страницы до того, как пользователь нажал на ссылку, чтобы на неё перейти, так что «загрузка документа» для пользователя кажется мгновенной. Чтобы предотвратить преждевременное звучание звуков и другие нюансы, система пререндринга Chrome блокирует плагины на странице до тех пор, пока пользователь реально не нажмёт на ссылку. Хакер выяснил, что на целевой странице Chrome активирует абсолютно все плагины, даже Native Client, который должен быть разрешён только для установленных приложений и расширений.
Конечно, один только Native Client сам по себе мало что даёт, ведь в нём есть эффективная песочница для изоляции исполняемого кода, причём песочница даже с более жёсткими ограничениями, чем нативная песочница Chrome для HTML-контента. Но преимущество Native Client в том, что он открывает интерфейсы низкого уровня к командным буферам GPU. Этим и воспользовался PinkiePie: он создал специальный командный буфер для эксплойта бага (117656) в декодировании команд GPU. Вот этот баг:
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); }
Итог вычислений переполняет буфер и в качестве результата записывается ноль. PinkiePie применил баг для записи нескольких битов в буфер, который используется для переноса данных между Native Client и процессами GPU, отражаясь в том числе в адресном пространстве процессов. Менеджер памяти Windows помещает буферы в относительно предсказуемое место.
Далее PinkiePie использовал ту же уязвимость для изменения значений в одном из буферов, чтобы поставить ссылку на фальшивое красно-чёрное дерево, которое он создал в других буферах. С помощью этого дерева PinkiePie уже мог читать и записывать произвольные адреса в процессах GPU. Вкупе с предсказуемым адресными координатами в Windows, это дало ему возможность построить цепочку методом возвратно-ориентированного программирования, чтобы исполнять произвольный код внутри процессов GPU.
Процессы GPU всё ещё хорошо защищены песочницей, но уже не так сильно, как процессы Native Client или рендеринга HTML. У них есть некоторые привилегии, в том числе возможность подключаться к определённым внутренним процессам Chrome (Inter-process Communication (IPC)). Здесь не должно быть никакой опасности, но PinkiePie обнаружил небольшое окно в тот момент, когда Chrome порождает новый рендерер — в этот момент процесс GPU может увидеть канал IPC и первым к нему подключиться, и тогда процесс GPU действует под видом рендерера (баг 117627).
Хотя у рендереров более строгая песочница, чем у GPU-процессов, но есть отдельный класс рендереров с повышенными привилегиями. Они не должны иметь дела с веб-контентом, а используются для рендеринга вещей вроде страницы с расширениями и настройками Chrome. Однако, PinkiePie обнаружил ещё один баг (117417), который позволял от обычного рендерера передать управление привилегированному рендереру, и использовать его для запуска менеджера расширений, после чего, как в случае с предыдущим багом, вредоносный процесс просто захватывал IPC-канал менеджера расширений.
Получив права менеджера расширений, PinkiePie использовал ещё два бага, чтобы окончательно вырваться из песочницы. Первый баг (117715) позволил ему определить путь загрузки для расширения от рендеринга менеджера расширений. Второй баг (117736) — отсутствие диалогового окна для подтверждения перед установкой неупакованного расширения NPAPI. С этими двумя багами PinkiePie смог установить и запустить под видом NPAPI-плагина свою собственную программу, которая исполнялась вне песочницы с полными пользовательскими привилегиями.
Вот так PinkiePie и заработал свою награду в 60 тысяч долларов. Все упомянутые баги уже исправлены.
Во второй части истории будут рассказаны подробности об эксплойте Сергея Глазунова, который основан уже не на шести, а на десяти различных багах. Поскольку это баги не только в продуктах Google, то информацию некрасиво публиковать, пока не прошло достаточно времени с момента уведомления соответствующих вендоров.