mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-21 20:23:18 +00:00
GITBOOK-4342: No subject
This commit is contained in:
parent
84f54544b3
commit
b007a3dab1
3 changed files with 186 additions and 16 deletions
|
@ -46,6 +46,12 @@ Here you can find start locations useful for **sandbox bypass** that allows you
|
|||
* **`~/Library/LaunchDemons`**
|
||||
* **Trigger**: Relog-in
|
||||
|
||||
{% hint style="success" %}
|
||||
As interesting fact, **`launchd`** has an embedded property list in a the Mach-o section `__Text.__config` which contains other well known services launchd must start. Moreover, these services can contain the `RequireSuccess`, `RequireRun` and `RebootOnSuccess` that means that they must be run and complete successfully.
|
||||
|
||||
Ofc, It cannot be modified because of code signing.
|
||||
{% endhint %}
|
||||
|
||||
#### Description & Exploitation
|
||||
|
||||
**`launchd`** is the **first** **process** executed by OX S kernel at startup and the last one to finish at shut down. It should always have the **PID 1**. This process will **read and execute** the configurations indicated in the **ASEP** **plists** in:
|
||||
|
@ -101,6 +107,28 @@ launchctl list
|
|||
If a plist is owned by a user, even if it's in a daemon system wide folders, the **task will be executed as the user** and not as root. This can prevent some privilege escalation attacks.
|
||||
{% endhint %}
|
||||
|
||||
#### More info about launchd
|
||||
|
||||
**`launchd`** is the **first** user mode process which is started from the **kernel**. The process start must be **successful** and it **cannot exit or crash**. It's even **protected** against some **killing signals**.
|
||||
|
||||
One of the first things `launchd` would do is to **start** all the **daemons** like:
|
||||
|
||||
* **Timer daemons** based on time to be executed:
|
||||
* atd (`com.apple.atrun.plist`): Has a `StartInterval` of 30min
|
||||
* crond (`com.apple.systemstats.daily.plist`): Has `StartCalendarInterval` to start at 00:15
|
||||
* **Network daemons** like:
|
||||
* `org.cups.cups-lpd`: Listens in TCP (`SockType: stream`) with `SockServiceName: printer`
|
||||
*  SockServiceName must be either a port or a service from `/etc/services`
|
||||
* `com.apple.xscertd.plist`: Listens on TCP in port 1640
|
||||
* **Path daemons** that are executed when a specified path changes:
|
||||
* `com.apple.postfix.master`: Checking the path `/etc/postfix/aliases`
|
||||
* **IOKit notifications daemons**:
|
||||
* `com.apple.xartstorageremoted`: `"com.apple.iokit.matching" => { "com.apple.device-attach" => { "IOMatchLaunchStream" => 1 ...`
|
||||
* **Mach port:**
|
||||
* `com.apple.xscertd-helper.plist`: It's indicating in the `MachServices` entry the name `com.apple.xscertd.helper`
|
||||
* **UserEventAgent:**
|
||||
* This is different from the previous one. It makes launchd spawn apps in response to specific event. However, in this case, the main binary involved isn't `launchd` but `/usr/libexec/UserEventAgent`. It loads plugins from the SIP restricted folder /System/Library/UserEventPlugins/ where each plugin indicates its initialiser in the `XPCEventModuleInitializer` key or. in the case of older plugins, in the `CFPluginFactories` dict under the key `FB86416D-6164-2070-726F-70735C216EC0` of its `Info.plist`.
|
||||
|
||||
### shell startup files
|
||||
|
||||
Writeup: [https://theevilbit.github.io/beyond/beyond\_0001/](https://theevilbit.github.io/beyond/beyond\_0001/)\
|
||||
|
|
|
@ -9,7 +9,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
@ -78,6 +78,59 @@ cat /Library/LaunchDaemons/com.jamf.management.daemon.plist
|
|||
|
||||
The ones in **`LaunchDameons`** are run by root. So if an unprivileged process can talk with one of these it could be able to escalate privileges.
|
||||
|
||||
## XPC Objects
|
||||
|
||||
* **`xpc_object_t`**
|
||||
|
||||
Every XPC message is a dictionary object that simplifies the serialization and deserialization. Moreover, `libxpc.dylib` declares most of the data types so it's possible to make that the received data is of the expected type. In the C API every object is a `xpc_object_t` (and it's type can be checked using `xpc_get_type(object)`).\
|
||||
Moreover, the function `xpc_copy_description(object)` can be used to get a string representation of the object that can be useful for debugging purposes.\
|
||||
These objects also have some methods to call like `xpc_<object>_copy`, `xpc_<object>_equal`, `xpc_<object>_hash`, `xpc_<object>_serialize`, `xpc_<object>_deserialize`...
|
||||
|
||||
The `xpc_object_t` are created calling `xpc_<objetType>_create` function, which internally calls `_xpc_base_create(Class, Size)` where it's indicated the type of the class of the object (one of `XPC_TYPE_*`) and the size of it (some extra 40B will be added to the size for metadata). Which means that the data of the object will start at the offset 40B.\
|
||||
Therefore, the `xpc_<objectType>_t` is kind of a subclass of the `xpc_object_t` which would be a subclass of `os_object_t*`.
|
||||
|
||||
{% hint style="warning" %}
|
||||
Note that it should be the developer who uses `xpc_dictionary_[get/set]_<objectType>` to get or set the type and real value of a key.
|
||||
{% endhint %}
|
||||
|
||||
* **`xpc_pipe`**
|
||||
|
||||
A **`xpc_pipe`** is a FIFO pipe that processes can use to communicate (the communication use Mach messages).\
|
||||
It's possible to create a XPC server calling `xpc_pipe_create()` or `xpc_pipe_create_from_port()` to create it using a specific Mach port. Then, to receive messages it's possible to call `xpc_pipe_receive` and `xpc_pipe_try_receive`.
|
||||
|
||||
Note that the **`xpc_pipe`** object is a **`xpc_object_t`** with information in its struct about the two Mach ports used and the name (if any). The name, for example, the daemon `secinitd` in its plist `/System/Library/LaunchDaemons/com.apple.secinitd.plist` configures the pipe called `com.apple.secinitd`.
|
||||
|
||||
An example of a **`xpc_pipe`** is the **bootstrap pip**e created by **`launchd`** making possible sharing Mach ports.
|
||||
|
||||
* **`NSXPC*`**
|
||||
|
||||
These are Objective-C high level objects which allows the abstraction of XPC connections.\
|
||||
Moreover, it's easier to debug these objects with DTrace than the previous ones.
|
||||
|
||||
* **`GCD Queues`**
|
||||
|
||||
XPC uses GCD to pass messages, moreover it generates certain dispatch queues like `xpc.transactionq`, `xpc.io`, `xpc-events.add-listenerq`, `xpc.service-instance`...
|
||||
|
||||
## XPC Services
|
||||
|
||||
These are **bundles with `.xpc`** extension located inside the **`XPCServices`** folder of other projects and in the `Info.plist` they have the `CFBundlePackageType` set to **`XPC!`**.\
|
||||
This file have other configuration keys like `ServiceType` which can be Application, User, System or `_SandboxProfile` which can define a sandbox or `_AllowedClients` which might indicate entitlements or ID required to contact the ser. these and other configuration options will be useful to configure the service when being launched.
|
||||
|
||||
### Starting a Service
|
||||
|
||||
The app attempts to **connect** to a XPC service using `xpc_connection_create_mach_service`, then launchd locates the daemon and starts **`xpcproxy`**. **`xpcproxy`** enforce configured restrictions and. spawns the service with the provided FDs and Mach ports.
|
||||
|
||||
In order to improve the speed of the search of the XPC service, a cache is used.
|
||||
|
||||
It's possible to trace the actions of `xpcproxy` using:
|
||||
|
||||
```bash
|
||||
supraudit S -C -o /tmp/output /dev/auditpipe
|
||||
```
|
||||
|
||||
The XPC library use `kdebug` to log actions calling `xpc_ktrace_pid0` and `xpc_ktrace_pid1`. The codes it uses are undocumented so it's needed to add the into `/usr/share/misc/trace.codes`. They have the prefix `0x29` and for example one is `0x29000004`: `XPC_serializer_pack`.\
|
||||
The utility `xpcproxy` uses the prefix `0x22`, for example: `0x2200001c: xpcproxy:will_do_preexec`.
|
||||
|
||||
## XPC Event Messages
|
||||
|
||||
Applications can **subscribe** to different event **messages**, enabling them to be **initiated on-demand** when such events happen. The **setup** for these services is done in l**aunchd plist files**, located in the **same directories as the previous ones** and containing an extra **`LaunchEvent`** key.
|
||||
|
@ -113,6 +166,8 @@ xpcspy -U -r -W <bundle-id>
|
|||
xpcspy -U <prog-name> -t 'i:com.apple.*' -t 'o:com.apple.*' -r
|
||||
```
|
||||
|
||||
Another possible tool to use is [**XPoCe2**](https://newosxbook.com/tools/XPoCe2.html).
|
||||
|
||||
## XPC Communication C Code Example
|
||||
|
||||
{% tabs %}
|
||||
|
@ -407,6 +462,28 @@ static void customConstructor(int argc, const char **argv)
|
|||
}
|
||||
```
|
||||
|
||||
## Remote XPC
|
||||
|
||||
This functionality provided by `RemoteXPC.framework` (from `libxpc`) allows to communicate via XPC through different hosts.\
|
||||
The services that supports remote XPC will have in their plist the key UsesRemoteXPC like it's the case of `/System/Library/LaunchDaemons/com.apple.SubmitDiagInfo.plist`. However, although the service will be registered with `launchd`, it's `UserEventAgent` with the plugins `com.apple.remoted.plugin` and `com.apple.remoteservicediscovery.events.plugin` which provides the functionality.
|
||||
|
||||
Moreover, the `RemoteServiceDiscovery.framework` allows to get info from the `com.apple.remoted.plugin` exposing functions such as `get_device`, `get_unique_device`, `connect`...
|
||||
|
||||
Once connect is used and the socket `fd` of the service is gathered, it's possible to use `remote_xpc_connection_*` class.
|
||||
|
||||
It's possible to get information about remote services using the cli tool `/usr/libexec/remotectl` using parameters as:
|
||||
|
||||
```bash
|
||||
/usr/libexec/remotectl list # Get bridge devices
|
||||
/usr/libexec/remotectl show ...# Get device properties and services
|
||||
/usr/libexec/remotectl dumpstate # Like dump withuot indicateing a servie
|
||||
/usr/libexec/remotectl [netcat|relay] ... # Expose a service in a port
|
||||
...
|
||||
```
|
||||
|
||||
The communication between BridgeOS and the host occurs through a dedicated IPv6 interface. The `MultiverseSupport.framework` allows to establish sockets whose `fd` will be used for communicating.\
|
||||
It's possible to find thee communications using `netstat`, `nettop` or the open source option, `netbottom`.
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Learn AWS hacking from zero to hero with</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
||||
|
@ -416,7 +493,7 @@ Other ways to support HackTricks:
|
|||
* If you want to see your **company advertised in HackTricks** or **download HackTricks in PDF** Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||||
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Share your hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
||||
|
||||
</details>
|
||||
|
|
|
@ -301,7 +301,7 @@ Note that these pages aren't persistent like background pages as they load dynam
|
|||
|
||||
As browser extensions can be so **privileged**, a malicious one or one being compromised could allow the attacker **different means to steal sensitive information and spy on the user**.
|
||||
|
||||
Check how these settings work and how thye could get abused in:
|
||||
Check how these settings work and how they could get abused in:
|
||||
|
||||
{% content-ref url="browext-permissions-and-host_permissions.md" %}
|
||||
[browext-permissions-and-host\_permissions.md](browext-permissions-and-host\_permissions.md)
|
||||
|
@ -357,6 +357,10 @@ In public extensions the **extension-id is accesible**:
|
|||
|
||||
Although, if the `manifest.json` parameter **`use_dynamic_url`** is used, this **id can be dynamic**.
|
||||
|
||||
{% hint style="success" %}
|
||||
Note that even if a page is mentioned here, it might be **protected against ClickJacking** thanks to the **Content Security Policy**. So you also need to check it (frame-ancestors section) before confirming a ClickJacking attack is possible.
|
||||
{% endhint %}
|
||||
|
||||
Being allowed to access these pages make these pages **potentially vulnerable ClickJacking**:
|
||||
|
||||
{% content-ref url="browext-clickjacking.md" %}
|
||||
|
@ -364,7 +368,13 @@ Being allowed to access these pages make these pages **potentially vulnerable Cl
|
|||
{% endcontent-ref %}
|
||||
|
||||
{% hint style="success" %}
|
||||
Allowing these pages to be loaded only by the extension and not by random URLs could prevent CLickJacking attacks.
|
||||
Allowing these pages to be loaded only by the extension and not by random URLs could prevent ClickJacking attacks.
|
||||
{% endhint %}
|
||||
|
||||
{% hint style="danger" %}
|
||||
Note that the pages from **`web_accessible_resources`** and other pages of the extension are also capable of **contacting background scripts**. So if one of these pages is vulnerable to **XSS** it could open a bigger vulnerability.
|
||||
|
||||
Moreover, note that you can only open pages indicated in **`web_accessible_resources`** inside iframes, but from a new tab it's possible to access any page in the extension knowing the extension ID. Therefore, if an XSS is found abusing same parameters, it could be abused even if the page isn't configured in **`web_accessible_resources`**.
|
||||
{% endhint %}
|
||||
|
||||
### `externally_connectable`
|
||||
|
@ -393,7 +403,60 @@ Therefore, this is a **very powerful bypass**.
|
|||
Moreover, if the client installs a rouge extension, even if it isn't allowed to communicate with the vulnerable extension, it could inject **XSS data in an allowed web page** or abuse **`WebRequest`** or **`DeclarativeNetRequest`** APIs to manipulate requests on a targeted domain altering a page's request for a **JavaScript file**. (Note that CSP on the targeted page could prevent these attacks). This idea comes [**from this writeup**](https://www.darkrelay.com/post/opera-zero-day-rce-vulnerability).
|
||||
{% endhint %}
|
||||
|
||||
##
|
||||
## Communication summary
|
||||
|
||||
### Extension <--> WebApp
|
||||
|
||||
To communicate between the content script and the web page post messages are usually used. Therefore, in the web application you will usually find calls to the function **`window.postMessage`** and in the content script listeners like **`window.addEventListener`**. Note however, that the extension could also **communicate with the web application sending a Post Message** (and therefore the web should expect it) or just make the web load a new script.
|
||||
|
||||
### Inside the extension
|
||||
|
||||
Usually the function **`chrome.runtime.sendMessage`** is used to send a message inside the extension (usually handled by the `background` script) and in order to receive and handle it a listener is declared calling **`chrome.runtime.onMessage.addListener`**.
|
||||
|
||||
It's also possible to use **`chrome.runtime.connect()`** to have a persistent connection instead of sending single messages, it's possible to use it to **send** and **receive** **messages** like in the following example:
|
||||
|
||||
<details>
|
||||
|
||||
<summary><code>chrome.runtime.connect()</code> example</summary>
|
||||
|
||||
```javascript
|
||||
var port = chrome.runtime.connect();
|
||||
|
||||
// Listen for messages from the web page
|
||||
window.addEventListener("message", (event) => {
|
||||
// Only accept messages from the same window
|
||||
if (event.source !== window) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the message type is "FROM_PAGE"
|
||||
if (event.data.type && (event.data.type === "FROM_PAGE")) {
|
||||
console.log("Content script received: " + event.data.text);
|
||||
// Forward the message to the background script
|
||||
port.postMessage({ type: 'FROM_PAGE', text: event.data.text });
|
||||
}
|
||||
}, false);
|
||||
|
||||
// Listen for messages from the background script
|
||||
port.onMessage.addListener(function(msg) {
|
||||
console.log("Content script received message from background script:", msg);
|
||||
// Handle the response message from the background script
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
It's also possible to send messages from a background script to a content script located in a specific tab calling **`chrome.tabs.sendMessage`** where you will need to indicated the **ID of the tab** to send the message to.
|
||||
|
||||
### From allowed `externally_connectable` to the extension
|
||||
|
||||
**Web apps and external browser extensions allowed** in the `externally_connectable` configuration can send requests using :
|
||||
|
||||
```javascript
|
||||
chrome.runtime.sendMessage(extensionId, ...
|
||||
```
|
||||
|
||||
Where it's needed to mention the **extension ID**.
|
||||
|
||||
## Web **↔︎** Content Script Communication
|
||||
|
||||
|
@ -403,6 +466,7 @@ The environments where **content scripts** operate and where the host pages exis
|
|||
|
||||
{% code title="content-script.js" %}
|
||||
```javascript
|
||||
// This is like "chrome.runtime.sendMessage" but to maintain the connection
|
||||
var port = chrome.runtime.connect();
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
|
@ -413,6 +477,7 @@ window.addEventListener("message", (event) => {
|
|||
|
||||
if (event.data.type && (event.data.type === "FROM_PAGE")) {
|
||||
console.log("Content script received: " + event.data.text);
|
||||
// Forward the message to the background script
|
||||
port.postMessage(event.data.text);
|
||||
}
|
||||
}, false);
|
||||
|
@ -460,16 +525,6 @@ You can also find an example of a **DOM based XSS to compromise a browser extens
|
|||
[browext-xss-example.md](browext-xss-example.md)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Sensitive Information in Memory/Code
|
||||
|
||||
If a Browser Extension stores **sensitive information inside it's memory**, this could be **dumped** (specially in Windows machines) and **searched** for this information.
|
||||
|
||||
Therefore, the memory of the Browser Extension **shouldn't be considered secure** and **sensitive information** such as credentials or mnemonic phrases **shouldn't be stored**.
|
||||
|
||||
Of course, do **not put sensitive information in the code**, as it will be **public**.
|
||||
|
||||
To dump memory from the browser you could **dump the process memory** or to go to the **settings** of the browser extension click on **`Inspect pop-up`** -> In the **`Memory`** section -> **`Take a snaphost`** and **`CTRL+F`** to search inside the snapshot for sensitive info.
|
||||
|
||||
## Content Script **↔︎** Background Script Communication
|
||||
|
||||
A Content Script can use the functions [**runtime.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage) **or** [**tabs.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/tabs#method-sendMessage) to send a **one-time JSON-serializable** message.
|
||||
|
@ -486,7 +541,7 @@ Sending a request from a **content script** looks like this:
|
|||
})();
|
||||
```
|
||||
|
||||
Sending a request from the **extension** (usually a **background script**) A Content Script can use the functions, except that you need to specify which tab to send it to. Example of how to send message to the content script in the selected tab:
|
||||
Sending a request from the **extension** (usually a **background script**). Example of how to send message to the content script in the selected tab:
|
||||
|
||||
```javascript
|
||||
// From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script
|
||||
|
@ -519,6 +574,16 @@ An important consideration is that in scenarios where multiple pages are set to
|
|||
|
||||
When crafting new extensions, the preference should be towards promises as opposed to callbacks. Concerning the use of callbacks, the `sendResponse()` function is considered valid only if it's executed directly within the synchronous context, or if the event handler indicates an asynchronous operation by returning `true`. Should none of the handlers return `true` or if the `sendResponse()` function is removed from memory (garbage-collected), the callback associated with the `sendMessage()` function will be triggered by default.
|
||||
|
||||
## Sensitive Information in Memory/Code
|
||||
|
||||
If a Browser Extension stores **sensitive information inside it's memory**, this could be **dumped** (specially in Windows machines) and **searched** for this information.
|
||||
|
||||
Therefore, the memory of the Browser Extension **shouldn't be considered secure** and **sensitive information** such as credentials or mnemonic phrases **shouldn't be stored**.
|
||||
|
||||
Of course, do **not put sensitive information in the code**, as it will be **public**.
|
||||
|
||||
To dump memory from the browser you could **dump the process memory** or to go to the **settings** of the browser extension click on **`Inspect pop-up`** -> In the **`Memory`** section -> **`Take a snaphost`** and **`CTRL+F`** to search inside the snapshot for sensitive info.
|
||||
|
||||
## Loading an Extension in the Browser
|
||||
|
||||
1. **Download** the Browser Extension & unzipped
|
||||
|
|
Loading…
Reference in a new issue