hacktricks/macos-hardening/macos-security-and-privilege-escalation/mac-os-architecture/macos-ipc-inter-process-communication/macos-xpc-connecting-process-check.md

7.2 KiB
Raw Blame History

macOS XPC连接进程检查

☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 YouTube 🎥

XPC连接进程检查

当与XPC服务建立连接时服务器将检查连接是否被允许。通常会执行以下检查

  1. 检查连接的进程是否使用Apple签名的证书仅由Apple提供
  • 如果未经验证,攻击者可以创建一个伪造的证书以匹配其他任何检查。
  1. 检查连接的进程是否使用组织的证书进行签名团队ID验证
  • 如果未经验证可以使用Apple的任何开发者证书进行签名并连接到服务。
  1. 检查连接的进程是否包含正确的Bundle ID
  • 如果未经验证,可以使用由同一组织签名的任何工具与XPC服务进行交互。
  1. 4或5检查连接的进程是否具有正确的软件版本号
  • 如果未经验证即使其他检查已经通过也可以使用旧的、存在安全漏洞的客户端进行连接到XPC服务的过程注入。
  1. 4或5检查连接的进程是否具有带有危险权限的强化运行时例如允许加载任意库或使用DYLD环境变量的权限
  • 如果未经验证,客户端可能容易受到代码注入的攻击。
  1. 检查连接的进程是否具有允许其连接到服务的授权。这适用于Apple的二进制文件。
  2. 验证必须基于连接的客户端的审计令牌而不是其进程IDPID因为前者可以防止PID重用攻击。
  • 开发人员很少使用审计令牌API调用因为它是私有的所以Apple可以随时更改。此外Mac App Store应用程序不允许使用私有API。

有关PID重用攻击检查的更多信息请参见

{% content-ref url="macos-pid-reuse.md" %} macos-pid-reuse.md {% endcontent-ref %}

Trustcache - 防止降级攻击

Trustcache是一种在Apple Silicon机器上引入的防御方法它存储了Apple二进制文件的CDHSAH数据库因此只有允许的非修改二进制文件才能执行。这可以防止执行降级版本。

代码示例

服务器将在名为**shouldAcceptNewConnection的函数中实现此验证**。

{% code overflow="wrap" %}

- (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection {
//Check connection
return YES;
}

{% endcode %}

对象NSXPCConnection有一个私有属性**auditToken(应该使用但可能会更改)和一个公共属性processIdentifier**(不应该使用)。

可以使用以下方式验证连接的进程:

{% code overflow="wrap" %}

[...]
SecRequirementRef requirementRef = NULL;
NSString requirementString = @"anchor apple generic and identifier \"xyz.hacktricks.service\" and certificate leaf [subject.CN] = \"TEAMID\" and info [CFBundleShortVersionString] >= \"1.0\"";
/* Check:
- Signed by a cert signed by Apple
- Check the bundle ID
- Check the TEAMID of the signing cert
- Check the version used
*/

// Check the requirements with the PID (vulnerable)
SecRequirementCreateWithString(requirementString, kSecCSDefaultFlags, &requirementRef);
SecCodeCheckValidity(code, kSecCSDefaultFlags, requirementRef);

// Check the requirements wuing the auditToken (secure)
SecTaskRef taskRef = SecTaskCreateWithAuditToken(NULL, ((ExtendedNSXPCConnection*)newConnection).auditToken);
SecTaskValidateForRequirement(taskRef, (__bridge CFStringRef)(requirementString))

如果开发人员不想检查客户端的版本,他至少可以检查客户端是否容易受到进程注入的攻击:

{% code overflow="wrap" %}

[...]
CFDictionaryRef csInfo = NULL;
SecCodeCopySigningInformation(code, kSecCSDynamicInformation, &csInfo);
uint32_t csFlags = [((__bridge NSDictionary *)csInfo)[(__bridge NSString *)kSecCodeInfoStatus] intValue];
const uint32_t cs_hard = 0x100;        // don't load invalid page.
const uint32_t cs_kill = 0x200;        // Kill process if page is invalid
const uint32_t cs_restrict = 0x800;    // Prevent debugging
const uint32_t cs_require_lv = 0x2000; // Library Validation
const uint32_t cs_runtime = 0x10000;   // hardened runtime
if ((csFlags & (cs_hard | cs_require_lv)) {
return Yes; // Accept connection
}

{% endcode %}

☁️ HackTricks 云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥