Подробный разбор цепочки эксплойтов Playstation 4 и 5

от автора

В статье представлена цепочка из пяти уязвимостей, позволяющая нападающему получить возможности JIT и исполнять произвольные полезные нагрузки. Передаваемая полезная нагрузка вызывает переполнение буфера, приводящее к kernel panic.

Уязвимости

[Уровень серьёзности: средний][PS4] [PS5] Уязвимость 1

Класс com.sony.gemstack.org.dvb.user.UserPreferenceManagerImpl при помощи readObject() десериализует файл userprefs в привилегированном контексте, что небезопасно:

    private void initPreferences() {         try {             UserPreferenceManagerImpl.preferences = AccessController.doPrivileged((PrivilegedExceptionAction<String[][]>)new ReadPreferenceAction());         }         catch (PrivilegedActionException ex) {}         if (UserPreferenceManagerImpl.preferences == null) {             UserPreferenceManagerImpl.preferences = new String[UserPreferenceManagerImpl.PREFERENCES.length][];         }         if (UserPreferenceManagerImpl.preferences[3] == null) {             UserPreferenceManagerImpl.preferences[3] = new String[] { "26" };             this.savePreferences();         }     }

    private static class ReadPreferenceAction implements PrivilegedExceptionAction     {         public Object run() throws Exception {             String[][] array = null;             ObjectInputStream objectInputStream = null;             try {                 objectInputStream = new ObjectInputStream(new BufferedInputStream(new FileInputStream(RootCertManager.getOriginalPersistentRoot() + "/userprefs")));                 array = (String[][])objectInputStream.readObject();             }             finally {                 if (objectInputStream != null) {                     objectInputStream.close();                 }             }             return array;         }     }

Злоумышленник может заменить файл userprefs зловредным сериализированным объектом для создания экземпляров классов в привилегированном контексте. На старых прошивках, например, 5.05, в которых отсутствует коммит https://github.com/openjdk/jdk/commit/020204a972d9be8a3b2b9e75c2e8abea36d787e9#diff-2c19943dd71743c3de69aa065025e753ca2e1f3b7ebc798e0d954de75d995de5, эксплуатировать эту уязвимость легко: нападающий может создать экземпляр подкласса ClassLoader для вызова defineClass с любыми разрешениями, а в конечном итоге обойти диспетчер безопасности.

[Уровень серьёзности: средний][PS4] Уязвимость 2

Класс com.oracle.security.Service содержит метод newInstance, вызывающий Class.forName для произвольного имени класса. Это позволяет создавать экземпляры произвольных классов, даже ограниченных (например, в sun.). Уязвимость работает для всех классов с публичными конструкторами, которые имеют единственные аргументы. Проверку в newInstance можно обойти, вызвав com.oracle.ProviderAdapter.setProviderAccessor для специальной созданной реализации ProviderAccessor.

        if (!this.registered) {             if (ProviderAdapter.getService(this.provider, this.type, this.algorithm) != this) {                 throw new NoSuchAlgorithmException("Service not registered with Provider " + this.provider.getName() + ": " + this);             }             this.registered = true;         }

[Уровень серьёзности: средний][PS4] [PS5] Уязвимость 3

Класс com.sony.gemstack.org.dvb.io.ixc.IxcProxy содержит защищённый метод invokeMethod, способный вызывать методы в привилегированном контексте. Проверки разрешений в методах можно обойти при соблюдении следующих условий:

  • Метод публичный и нестатический
  • Класс метода публичный, не final и его экземпляры можно создавать.

В такой ситуации нападающий может написать подкласс целевого класса, реализующий интерфейс, в котором нужный метод выбрасывает RemoteException.
Например, в File.list() присутствуют проверки разрешений. Злоумышленник может обойти их при помощи следующих классов:

class FileImpl extends File implements FileInterface {   FileImpl(String pathname) {     super(pathname);   } } Code 91 Bytes interface FileInterface extends Remote {   public String[] list() throws RemoteException; }

Эту уязвимость можно использовать для обеспечения утечки структуры файловой системы, а также для дампинга файлов (например, из /app0/).

[Уровень серьёзности: высокий][PS4] Уязвимость 4

«compiler receiver thread» получает от рабочего процесса структуру размером 0x58 байтов:

typedef struct {   uint8_t cmd; // 0x00   uint64_t arg0; // 0x08   uint64_t arg1; // 0x10   uint64_t arg2; // 0x18   uint64_t arg3; // 0x20   uint64_t arg4; // 0x28   uintptr_t runtime_data; // 0x30   uintptr_t compiler_data; // 0x38   uint64_t data1; // 0x40   uint64_t data2; // 0x48   uint64_t unk; // 0x50 } CompilerAgentRequest; // 0x58  CompilerAgentRequest req; while (CompilerAgent::readn(s, &req, sizeof(req)) > 0) {   uint8_t ack = 0xAA;   CompilerAgent::writen(s, &ack, sizeof(ack));   if (req.compiler_data != 0) {     memcpy(req.compiler_data + 0x28, &req, sizeof(req));     ...   }   ... }

Эта структура содержит указатель на смещение 0x38 (мы называем его compiler_data) от процесса компилятора, который используется для создания резервной копии структуры запроса. Нападающий может просто отправить ненадёжный указатель, а compiler receiver thread скопирует данные из запроса в его память. Иными словами, это примитив write-what-where. Нападающий может эксплуатировать эту уязвимость, передавая указатель на память JIT и сохраняя содержимое, которое должно быть записано в запрос. Компилятор запишет эти данных в память JIT, давая нам возможность исполнять произвольные полезные нагрузки. Последствия могут быть очень серьёзными:

  • Можно написать загрузчик ELF для загрузки и исполнения пиратских игр
  • Эксплойт ядра становится тривиальной задачей, поскольку отсутствует SMEP и можно просто перейти к пользователю при помощи повреждённого указателя функции.

[Уровень серьёзности: высокий][PS4] [PS5] Уязвимость 5

В PS4 и PS5 используется драйвер UDF https://github.com/williamdevries/UDF, содержащий переполнение буфера. Злоумышленник может сделать размер inf_len больше, чем sector_size (при внутреннем распределении предполагается, что данные меньше, чем размер сектора) и вызвать переполнение при помощи memcpy().

int udf_read_internal(struct udf_node *node, uint8_t *blob) { struct file_entry *fe = node->fe; struct extfile_entry *efe = node->efe; struct udf_mount *ump; uint64_t inflen; int addr_type, icbflags; uint32_t sector_size; uint8_t *pos;  /* получаем диапазон и выполняем параноидальные проверки */ ump = node->ump; sector_size = ump->sector_size;  if (fe != NULL) { inflen = le64toh(fe->inf_len); pos = &fe->data[0] + le32toh(fe->l_ea); icbflags = le16toh(fe->icbtag.flags); } else { inflen = le64toh(efe->inf_len); pos = &efe->data[0] + le32toh(efe->l_ea); icbflags = le16toh(efe->icbtag.flags); } addr_type = icbflags & UDF_ICB_TAG_FLAGS_ALLOC_MASK;  /* копируем информацию */ memset(blob, 0, sector_size); memcpy(blob, pos, inflen);  return (0); }

Proof-of-concept

Была создана цепочка эксплойтов bd-jb в виде файла .iso, демонстрирующая использование уязвимостей 1-4, что доказывает возможность запуска произвольных полезных нагрузок. Необходимо записать образ iso с файловой системой UDF 2.5. Полезную нагрузку можно отправить при помощи nc $PS4IP 1337 < payload.bin. Переданная полезная нагрузка приводит к kernel panic, вызывая уязвимость 5 (файл /PWN/0 был модифицирован, чтобы использовать внутреннее распределение, он имеет размер 4 МБ и заполнен символами A). Протестировано на самой свежей прошивке 9.00.

Влияние

Благодаря этим уязвимостям можно выпускать пиратские игры на дисках Bluray. Это возможно даже без эксплойта ядра, поскольку у нас есть возможности JIT.

Хроника устранения уязвимостей

25 октября 2021 года — theflow0 отправил отчёт PlayStation.

5 ноября 2021 года — shoshin_cup (представитель PlayStation) изменил статус на Triaged.

12 ноября 2021 года — theflow0 выплачено вознаграждение $20000.

5 апреля 2022 года — shoshin_cup закрыл отчёт и изменил статус на Resolved.

5 апреля 2022 года — theflow0 попросил опубликовать этот отчёт.

10 июня 2022 года — sazerac (представитель HackerOne) согласился опубликовать отчёт.

10 июня 2022 года — отчёт был опубликован.


ссылка на оригинал статьи https://habr.com/ru/post/671088/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *