- Proposal: JBX-0001
- Authors: osy
- Status: draft
The ecosystem of iOS jailbreaks has remained largely unchanged since iOS 1.0 even though the system internals of iOS has undergone several evolutions, enhancing security and enabling new features. iOS jailbreaks traditionally involves neutering a significant portion of the OS's security in order to enable unsigned code execution ("apps") and system modifications ("tweaks"). This allows malware to target jailbroken users and for misbehaving apps to corrupt data.
The traditional implementation of jailbreak (henceforth referred to as "legacy jailbreak") relies on modifications to the root partition, injecting code in all processes without discrimination, and managing installs through the Debian Package system (which is mostly used in the GNU/Linux ecosystem and was not designed for Darwin/XNU).
In iOS 15, the addition of System Signed Volume (SSV) necessitates jailbreaks to be "rootless". This change will break compatibility with many tweaks that depend on being installed in root with no sandbox. This gives us an opening to design a better jailbreak infrastructure. The purpose of this document is to lay down the groundwork for such a endeavor.
The goals of this new jailbreak infrastructure is as follows:
- Design a set of system level modifications and frameworks for the versatility and creativity of jailbreak apps and tweaks while also extending and complementing the security contract of iOS in order to maintain system security and stability.
- Provide a way for users to verify and consent to access of system assets.
- Extend the root of trust from Apple to Apple plus the user of the device. The user should be able to run anything they want on their own device. (As a corollary, code not explicitly trusted by the user should not run.)
- The amount of modification done as part of the jailbreak install (as described by this document) should be minimal and only enough to provide a way to install, validate, and run tweaks and apps.
Note that we only define the programmer visible API for the infrastructure and leave out details for the implementation as that may vary from jailbreak to jailbreak.
To the extent possible, we will reuse and modify existing system features in lieu of implementing new features. This means that we are largely relying on patching undocumented and private system interfaces that are known to change from version to version. The advantage though, is that we are better able to utilize existing (tested) code.
We mainly rely on two system level features:
- Entitlements allow us to define fine grained access control for an executable running in a sandbox environment.
- App Extensions allows for pre-defined extension points to execute third-party code in a sandbox. We design a new extension point at process activation time to allow third-party tweaks to inject code/data into the target process.
In a stock iOS installation, Apple is the root of trust for all code running on the device. In a jailbreak environment, we add a new root (the "user signing certificate") that is controlled by the user of the device.
To reduce the chance of user error, man-in-the-middle attacks, and other risks, the user signing certificate shall be generated on device. If the device is A7 or higher, the certificate should be generated in the Secure Enclave. The mechanism can be with the SecKeyCreateRandomKey
function using the kSecAttrTokenIDSecureEnclave
attribute (see here for more details). This will entangle the signing certificate with the per-device hardware key as well as the user passcode and measurements of the currently running OS. This will ensure that the signed executable extracted from one device cannot be used to attack another user's device.
The generation of the user signing certificate shall be done as part of the initial jailbreak installation process. Once the jailbreak installation is completed, the installer should block attempts to reinstall in an already jailbroken state in order to mitigate against an attacker from using the jailbreak installer as an attack vector to bypass user-signing.
The installer application is an iOS application that manages jailbreak tweaks and apps. It shall hold two entitlements (details in the following section): jailbreak.installer.user-code-sign
(set to true
) and com.apple.private.mobileinstall.allowedSPI
(set to Install
).
Packages are in the standard Apple IPA format.
The installer application shall display any entitlements used by the app (and its embedded bundles) outside of a predefined allow-list to the user before proceeding. The GUI should attempt to provide a user-readable description of each entitlement used. The allow-list should be defined by the developer of the installer application.
The installer application shall block, provide an alert separate from the entitlement verification, or otherwise require some extra action taken by the user to consent to the installation of any app that has the com.apple.private.mobileinstall.allowedSPI
entitlement with the exception of an update to the installer application itself which should be validated in an implementation defined means. This is to detect malware from masquerading as an installer application.
The installer application should optionally perform some sort of verification of packages in an implementation defined method. This can be, for example, a GPG system where each IPA has an associated signature file.
After user consent, the installer application shall sign or resign the executable in the IPA along with any bundles by interfacing with Jailbreak.framework
. The installer application should keep the entitlements when re-signing.
The installer application shall use the MobileInstallation.framework
interfaces to install the resigned IPA package.
Uninstallation can be performed either by the installation application or by the user via standard system means.
The installer application must be signed with the user signing certificate. This can be done at jailbreak installation time (after the certificate generation) or through a "sign on first launch" of the installer application. In the second option, care must be taken to ensure that unsigned code execution happens exactly once and only for the installer application.
In addition to system defined entitlements, the following entitlements are defined:
- Key:
jailbreak.installer.user-code-sign
- Type: Boolean
If true, this process can use Jailbreak.framework
to sign code with the user signing certificate.
- Key:
jailbreak.extension.install-process-hook
- Type: Boolean
If true, this process can use Jailbreak.framework
to install a new process hook App Extension.
- Key:
jailbreak.process-modify-data.allowed-identifiers
- Type: Array of strings
An array of bundle identifiers whose address space is allowed by this process to modify read/write data.
- Key:
jailbreak.process-modify-code.allowed-identifiers
- Type: Array of strings
An array of bundle identifiers whose address space is allowed by this process to modify read-only data and code. Note: not all jailbreaks may support this entitlement.
A new system framework, Jailbreak.framework
, shall be created to provide an interface for user code-signing and implementing modifications of system and third party applications (tweaks). The framework shall work through an XPC interface that can be considered as privileged as any system daemon. The jailbreak installation and/or activation shall ensure that the user signing certificate private key can only be used by this XPC process and that the framework must be immutable. It is part of the root-of-trust in a jailbroken device.
This class shall provide an XPC interface to register and enable the App Extension bundle enclosed in the calling application as a Process Hook Extension. The jailbreak.extension.install-process-hook
entitlement shall be checked.
This protocol should be implemented by the App Extension code to handle the tweak's activation points. The NSExtensionPointIdentifier
shall be jailbreak.extension.process-hook
. Additional details of this interface is TBD but it should provide an activation function that returns a reference to an object that can be used to inject code/data into a target process that it is allowed to hook as defined by the jailbreak.process-modify-data.allowed-identifiers
and jailbreak.process-modify-code.allowed-identifiers
entitlements.
A compatibility layer can be implemented to support Substrate or libhooker with the limitation that only the processes defined in the entitlement can be hooked.
Note that data in the extension can be shared with the application containing the extension through group containers.
This class shall provide an XPC interface to use the user code-signing certificate to sign an executable. It shall verify that the jailbreak.installer.user-code-sign
entitlement is held by the caller process.
This should not be confused with any existing jailbreakd
. In this implementation of jailbreakd, an XPC interface shall be defined to implement the functionality defined in the preceding sections. Additionally, it shall activate process hooks installed by the JBProcessExtension
interface.
Upon process creation, jailbreakd shall identify any Process Hook Extensions that are currently registered and launch those extensions as separate processes. The activation point of those executable should call back into jailbreakd (through an XPC interface abstracted by Jailbreak.framework
) to perform the actual process patching.
When a process crashes with a process hook enabled, any App Extension that hooks the process should be disabled. There may be a user configurable option to change the behavior to only work on platform executables. This removes the need for a "safe mode."
When the enclosing application of a Process Hook Extension is deleted by the user, the hook should automatically be unregistered and not be loaded the next time the target process is launched.
It is also jailbreakd's responsibility to patch MISValidateSignatureAndCopyInfo
(or a similar function) to accept the user code signing certificate in addition to the Apple code signing certificate for purposes of verifying an executable.
Thanks to the nouveau proposal for inspirations.
I think that’s beyond the scope of this proposal. I mostly want to focus on what the bare minimum would be needed to have a “functional” jailbreak. A CLI package manager would fall under the definition of an “installer application” here.