bd-j exploit chain
Team Summary
Official summary from PlayStation
Hey PlayStation! Below are 5 vulnerabilities chained together that allows an attacker to gain JIT capabilities and execute arbitrary payloads. The provided payload triggers a buffer overflow that causes a kernel panic. Please consider each of the vulnerabilities individually. AFAIK, this is the first exploit chain that is being submitted to you :) ## Vulnerabilities ### [MEDIUM] [PS4] [PS5] Vulnerability 1 The class `com.sony.gemstack.org.dvb.user.UserPreferenceManagerImpl` deserializes the `userprefs` file under privileged context using `readObject()` which is insecure: ```java 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(); } } ``` ```java 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; } } ``` An attacker can replace the `userprefs` file with a malicious serialized object to **instantiate classes under privileged context**. On older firmwares such as 5.05, where the commit https://github.com/openjdk/jdk/commit/020204a972d9be8a3b2b9e75c2e8abea36d787e9#diff-2c19943dd71743c3de69aa065025e753ca2e1f3b7ebc798e0d954de75d995de5 is not present, exploitation of this vulnerability is easy: An attacker can instantiate a `ClassLoader` subclass to call `defineClass` with all permissions and finally bypass the security manager. ### [MEDIUM] [PS4] Vulnerability 2 The class `com.oracle.security.Service` contains a method `newInstance` which calls `Class.forName` on an arbitrary class name. **This allows arbitrary classes, even restricted ones (for example in `sun.`), to be instantiated**. This works for all classes with public constructors that have single arguments. The check in `newInstance` can be bypassed by calling `com.oracle.ProviderAdapter.setProviderAccessor` on a custom `ProviderAccessor` implementation. ```java 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; } ``` ### [MEDIUM] [PS4] [PS5] Vulnerability 3 The class `com.sony.gemstack.org.dvb.io.ixc.IxcProxy` contains the protected method `invokeMethod` which can call methods under privileged context. Permission checks in methods can be bypassed if the following conditions are met: - The method is public and non-static. - The method's class is public, non-final and can be instantiated. In such a scenario, an attacker can write a subclass of the target class which implements an interface where the desired method throws `RemoteException`. For example, there are permission checks in `File.list()`. An attacker can bypass them with the following classes: ```java class FileImpl extends File implements FileInterface { FileImpl(String pathname) { super(pathname); } } ``` ```java interface FileInterface extends Remote { public String[] list() throws RemoteException; } ``` This vulnerability can be used to leak the file system structure as well as dumping files (for example from `/app0/`). ### [HIGH] [PS4] Vulnerability 4 The "compiler receiver thread" receives a structure of size 0x58 bytes from the runtime process: ```c 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)); ... } ... } ``` This struct contains a pointer at offset 0x38 (we call it `compiler_data`) from the compiler process which is used to make a backup of the request structure. An attacker can simply send an untrusted pointer and the compiler receiver thread will copy data from the request into its memory. In other words, **we have a write-what-where primitive**. An attacker can exploit this vulnerability by supplying a pointer to JIT memory and store the content to be written in the request. The compiler will write this data into JIT memory and therefore give us the opportunity to execute arbitrary payloads. **This has severe implications**: - An ELF loader can be written to **load and execute pirated games**. - **Kernel exploitation becomes trivial** as there is no SMEP and one can simply jump to user with a corrupted function pointer. ### [HIGH] [PS4] [PS5] Vulnerability 5 The UDF driver https://github.com/williamdevries/UDF is used on the PS4 and PS5 which contains a **buffer overflow**. An attacker can make the size `inf_len` larger than `sector_size` (the assumption of internal allocation is that the data is smaller than the sector size) and cause an overflow with `memcpy()`. ```c 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; /* get extent and do some paranoia checks */ 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; /* copy out info */ memset(blob, 0, sector_size); memcpy(blob, pos, inflen); return (0); } ``` ## Proof-of-concept Attached is the exploit chain *bd-jb* as a `.iso` file which demonstrates the exploitation of vulnerabilities 1-4 that demonstrates the ability to run arbitrary payloads. Burn the iso image with UDF 2.5 file system. You can send the payload using `nc $PS4IP 1337 < payload.bin`. The provided payload causes a kernel panic by triggering vulnerability 5 (the file `/PWN/0` has been modified to use internal allocation and has a size of 4MB filled with `A`). Tested on latest firmware `9.00`. ## Impact - With these vulnerabilities, it is possible to **ship pirated games on bluray discs**. That is possible even without a kernel exploit as we have JIT capabilities.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Bounty
$20000.00
Submitted
Weakness
Privilege Escalation