Catalina正在检查未签名的可执行文件的公证

2020-05-23 20:47:07

这是Allan Odgaard的优秀文章MacOS10.15:Slow by Design的后续文章。我想特别谈一谈产生新过程的第一部分,因为人们对此有广泛的误解。Odgaard提供了一个简单的测试,以显示当Catalina在线检查可执行文件的公证状态时,可执行文件的第一次运行被延迟。即使对于不能进行代码签名的shell脚本,也会发生这种情况!

包括我在内的许多人都转载了这个问题。然而,其他一些人声称他们不能复制它。我对这些说法相当怀疑,因为我发现了不少人曲解自己测试的案例。你不能指望只是经历一个明显的长时间延迟,因为延迟的长度取决于你的网络连接状况和速度,以及你与苹果服务器的距离。(黑客新闻上的一位中国评论者发布的结果是,虚拟专用网上的结果是5.746秒对6毫秒,非虚拟专用网的结果是1.936秒对5毫秒。)。如果没有在线检查,脚本应该在几毫秒内完成执行。因此,即使你的第一个测试结果只有100毫秒左右,它仍然比预期的要长很多倍。有些人试图解释延迟的原因,例如,我会把300ms而不是5ms归因于文件系统缓存,但这种挥手是经不起进一步审查的。

记住,Catalina会缓存在线检查的结果,这一点也很重要。如果您多次测试,这可能会给出误导性的结果。在我的测试中,触发新的在线检查的最简单方法是修改脚本内容。我只需在TextEdit中创建一个脚本,保存它,然后使TextEdit保持打开状态,以便于编辑和保存。

您可以通过进行数据包跟踪来验证是否存在在线检查。在第一次运行时,显然是在线检查。在未修改的脚本的后续运行中,不会进行在线检查,并且执行速度要快得多。如果您关闭Mac的互联网连接,您可以看到脚本的第一次运行现在比以前快得多;但是没有互联网的第一次运行仍然比后续运行慢。因此,它仍在尝试进行在线检查,但失败了,然后将结果缓存。

Catalina是否正在尝试检查可执行文件的公证?证据有力地表明是这样的。此包跟踪看起来与普通应用程序公证检查的包跟踪完全相同。它们总是属于同一个域名:api.apple-cloudkit.com。如果搜索Catalina文件系统,则只有几个关于此域的结果。我发现/System/Library/PrivateFrameworks/WorkflowKit.framework和/System/iOSSupport/System/Library/PrivateFrameworks/WorkflowKit.framework,与快捷方式相关,/usr/libexec/remindd与提醒相关,/usr/libexec/syspolicyd是我们正在寻找的,负责检查公证的进程。事实上,只有一个地方-https://api.apple-cloudkit.com/database/1/%@/%@/public/records/lookup-syspolicyd联系该域。(URL中的%@是Objective-C格式的字符串。是的,和大多数MacOS一样,syspolicyd仍然是用Objective-C编写的。)。您还可以在syspolicyd";中找到针对未签名代码执行遗留公证检查的日志消息。我不确定它为什么会说遗产,我可以推测,但这只会分散人们对主要问题的注意力。在任何情况下,我都不知道除了公证检查之外,这怎么可能被称为其他任何东西,因为这里只有一个在线API,既可用于常规应用程序,也可用于非应用程序可执行文件。

顺便说一下,您可以通过安装Little Snitch并设置规则来拒绝来自syspolicyd的任何传出连接,从而在不关闭互联网连接的情况下阻止MacOS公证检查。我强烈推荐“小飞贼”,认为它是Mac绝对必不可少的软件。

与Catalina相反,MacOS10.14Mojave没有任何关于shell脚本的在线检查。这也可以通过数据包跟踪进行验证。即使我从网上下载了一个文件,添加了隔离扩展属性,仍然没有公证检查。在Mojave上第一次运行shell脚本的速度与后续运行脚本的速度一样快。莫哈韦没有引入任何在线延迟。

回到Catalina,我开始想知道其他类型的可执行文件。如果编译后的命令行工具既不是脚本也不是应用程序怎么办?我在Xcode中创建了一个简单的";Hello World";项目,并更改了构建设置,以便该工具根本不是由Xcode代码签名的。我第一次运行这个工具的时候,没有在线公证检查,这让我有点吃惊。不过,当我查看Xcode构建记录时,我找到了解释。测试的最后阶段

由于Xcode干扰了我的测试,我决定放弃Xcode,转而使用clang直接编译命令行可执行文件。我没有对编译后的可执行文件进行代码签名。当我第一次运行它的时候,有一个公证检查!当然,在随后的运行中也没有公证检查。因此,Catalina似乎在检查每个未签名的可执行文件的公证,无论是shell脚本还是编译的Mach-O文件。

对于我的下一个测试,我决定编译另一个工具,但这一次在它上执行临时代码签名(CoDesign--用身份签名)。临时签名的可执行文件仅针对您的Mac进行签名,并且不需要签名证书。当我第一次运行我的特别签名工具时,这也触发了公证检查,就像未签名的案例一样。

我没有测试的一个场景是运行一个用我的苹果开发人员证书签名的编译命令行工具。使用Xcode很容易做到这一点,没有Xcode就不那么容易了。这并不是不可能的,您只需找出CoDesign调用的适当参数即可。老实说,在我做了所有其他测试之后,我就是不想做额外的工作。其他人可以试试这个,拜托!

回到最初的文章,艾伦·奥德加德(Allan Odgaard)问道,苹果是否将我所有定制脚本的源代码发送到他们的服务器?答案是否定的。有两种独立的方法来验证这一点。首先,您可以查看反汇编(otool-tv/usr/libexec/syspolicyd)以了解它的确切工作方式。其次,您可以查看数据包跟踪。例如,如果您创建一个非常大的脚本,您可以将脚本的大小与发送到Apple的数据字节数进行比较。没有足够的字节来容纳一个大的脚本;在公证检查中根本没有太多的字节,这就是问题所在,因为它应该是尽可能快的(网络)。代码签名和公证使用安全散列,而不是完整的文件内容。

我希望这次讨论是一个有用的澄清。不幸的是,我无法解释为什么Catalina要对这些可执行文件运行公证检查。这个谜团真的要由苹果来解释了。你有很多解释要做!

今天,我看到一位Apple Xcode工程师发表了一条耐人寻味的评论。(顺便说一句,这个工程师因为未知的原因在鸟的网站上屏蔽了我,…。(我想,除了Xcode上的通用翻录之外,其他信息都是未知的。)。

“系统首选项”、“安全性”、“隐私”中的“开发人员工具”窗格具有相同的功能。将您想要授予相同权限的任何内容(如xcodebuild)拖到该列表中。子进程也会继承这一点。

这样做的目的是避免恶意软件将Xcode的几个位打包在自己身上,并在目标机器上以静默方式编译自己,从而绕过系统安全策略。

因此,这可能表明苹果公司将公证检查添加到脚本和其他独立可执行文件的动机。然而,据我所知,一个主要问题是,这些信息在任何地方都没有记录在案。这是我第一次听说它,我是一名专业的Mac开发人员。艾伦·奥德加德也是。但我们都只是在黑暗中挣扎,试图应对神秘的系统行为。

把这件事说成是关于速度的,等于埋没了引线。从隐私和用户自由的角度来看,这是可怕的。

你不这么认为吗?从理论上讲,苹果现在有一个集中的数据库,记录每一个使用过YouTube-dl的Mac用户。或者托尔。或者TrueCrypt。