Документация и PoC-код для CVE-2022-24125 и CVE-2022-24126.
Новое обновление игры, 1.15.1, было выпущено для Dark Souls III 25.08.2022, вместе с восстановлением онлайн-сервисов. Это обновление исправило как CVE-2022-24125, так и CVE-2022-24126, а также множество других потенциальных уязвимостей безопасности в P2P-сети игры (чтения/записи за пределами границ). Кроме того, были исправлены все известные эксплойты, позволяющие повредить сохранения других игроков. Также были пропатчены многие распространённые мелкие читы (например, «проклятый нож»), которые часто встречались в онлайн-мультиплеере.
Этот репозиторий содержит код доказательства концепции и документацию для самой последней RCE-уязвимости, затрагивающей игры FROM SOFTWARE, CVE-2022-24126. Хотя теоретически это возможно и в других играх, основное внимание уделяется Dark Souls III, поскольку именно на этой игре проводилось моё исследование. На данный момент код доказательства концепции существует только для Dark Souls III; подтверждено наличие уязвимости в:
Уязвимый код также присутствует в Sekiro (авторство: LukeYui), хотя способа его запуска нет. Наличие в Demon's Souls не подтверждено, но весьма вероятно. Хотя закрытое сетевое тестирование было затронуто этой проблемой, релизная версия Elden Ring — нет. Фактически, огромный список сетевых вылетов, чтений/записей за пределами границ и эксплойтов, позволявших игрокам изменять данные игры других участников в Dark Souls III, был исправлен в Elden Ring. Благодарность за составление этого списка и FROM SOFTWARE за быструю реакцию! Я рад сообщить, что
Вопреки распространённому мнению, это НЕ эксплойт одноранговой (P2P) сети. Он связан с матчмейкинг-сервером и поэтому гораздо серьёзнее, поскольку из-за другой уязвимости матчмейкинг-сервера (CVE-2022-24125) вам не нужно участвовать в каких-либо действиях в мультиплеере, чтобы стать уязвимым.
Учитывая, что в месяцы, предшествовавшие отключению серверов, в игру в среднем одновременно играло около 20 000 человек, было очевидно, что проблему необходимо исправить немедленно, особенно с учётом возможности её наличия в Elden Ring. Поскольку FROM SOFTWARE не предприняла никаких действий в течение более чем 40 дней после моего первоначального отчёта с видео доказательствами концепции и подробной документацией по эксплойту (на которой основана большая часть этого readme), я решил публично продемонстрировать существование эксплойта безвредным способом, надеясь привлечь внимание и добиться его устранения разработчиками, — и это сработало.
Подробнее об этих 3 гаджетах см. здесь. Если для какой-либо другой игры этот метод виртуальных вызовов неприменим, перенаправление произвольного кода всё равно может быть использовано для создания более традиционного ROP-эксплойта.
Чтобы запустить код доказательства концепции, сначала необходимо иметь сервер для подключения. Поскольку официальные серверы были отключены из-за эксплойта, вы можете настроить частный сервер с помощью ds3os. ds3os спроектирован так, чтобы максимально точно имитировать поведение релизного сервера, но в этот проект уже были внесены исправления безопасности для устранения данного эксплойта. Однако вы всё равно можете настроить тестовую среду, собрав проект самостоятельно с константами SEND_MESSAGE_TO_PLAYERS_SANITY_CHECKS и NRSSR_SANITY_CHECKS, установленными в false в BuildConfig.h. Это имитирует небезопасное поведение релизного сервера. Следуйте инструкциям, предоставленным ds3os, чтобы запустить игру и подключиться к вашему серверу.
Как только это будет сделано и ваша игра подключится к серверам, соберите PoC-код и запустите исполняемый файл Injector.exe. Он внедрит DLL, содержащую код эксплойта, в процесс Dark Souls III. Затем эта DLL будет использовать игровую функцию, отправляющую FRPG-сообщения на сервер, чтобы доставить эксплойт вашему собственному клиенту.
Функция 140ca5010 проверяет размеры записей, а 140ca4fa0 предназначена для записей переменного размера и не выполняет проверок корректности поля размера (Ошибка №1). Чтобы добиться описанного выше перенаправления произвольного кода, нам нужно установить его в 14F3B0. Это вызовет чтение за пределами границ объёмом примерно 1.3МиБ, но страницы памяти должно быть достаточно, чтобы избежать нарушений доступа.
140ca56b0Эта функция вызывается предыдущей с аргументом nrssr_data. Она создаёт объект DLMemoryInputStream на стеке, который затем передаётся в качестве аргумента парсеру NRSSR.
141955f50: ParseNRSessionSeachResultПарсер NRSessionSearchResult. Проверяет сигнатуру NRSSR и номера версий (14196a0f0), разбирает список свойств (14196a260), имя хоста (14195603a) и ещё некоторую информацию (см. rce.h)
14195603aЦикл в вышеуказанной функции, который небезопасно копирует имя хоста (Ошибка №2). Вот некоторые адреса, которые могут помочь отслеживать, что происходит во время переполнения буфера:
14F128DLMemoryInputStream: 14F3A0DLMemoryInputStream после перезаписи: 1439e8b30DLMemoryInputStream, используемой DLInputStreamReader: 0x181439e8b48MOV RCX,qword ptr [RCX + 0x8]
MOV RAX,qword ptr [RCX]
JMP qword ptr [RAX + 0x40]
Сюда мы попадаем после первого перенаправления кода, вызванного перезаписанной vftable потока памяти. Здесь начинается цепочка перенаправлений виртуальных вызовов.
Для Dark Souls III Вер. 1.15. Максимальный теоретический размер полезной нагрузки зависит от раскладки стека и поэтому варьируется в зависимости от игры и версии. ↩