В статье представлена цепочка из пяти уязвимостей, позволяющая нападающему получить возможности 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/
Добавить комментарий