It’s common knowledge that app signatures are only checked on first run. Once an app has passed through Gatekeeper’s stringent initial checks, when that app is launched again, the signature isn’t checked. This claim is repeated extensively wherever macOS Gatekeeper and signature checks are discussed, and it appears to be wrong, at least as of Mojave 10.14.2. 众所周知,应用程序签名只在第一次运行时进行检查。一旦应用程序通过了Gatekeeper严格的初始检查,当该应用程序再次启动时,不会检查签名。无论在哪里讨论macOS看门人和签名支票,这种说法都会被广泛重复,而且它似乎是错误的,至少在Mojave 10.14.2中是这样。
In this article I will demonstrate that app signatures are checked whenever an app is opened, and that when those checks return serious errors, those errors may be ignored, and app launch allowed to proceed normally. This is based on log examination of many app launches made in 10.14.2.
在本文中,我将演示每当打开应用程序时都会检查应用程序签名,当这些检查返回严重错误时,这些错误可能会被忽略,而应用程序的启动可以正常进行。这是基于10.14.2中许多应用程序启动的日志检查。
Key to this is Jeff Johnson’s information that it is possible to modify the Info.plist, executable code, and other components of a notarized app, but for it then to open and run normally in spite of the fact that those modifications have broken validation of the app’s signature. I have instinctively performed such modifications away from ‘real’ apps in /Applications, and that was my error.
杰夫约翰逊的信息的关键,这是有可能修改的Info.plist,可执行代码,以及其他经过认证的应用程序的组成部分,尽管这些修改已经破坏了应用程序签名的验证,但之后它仍然可以正常打开和运行。我本能地进行了这样的修改,远离/应用程序中的“真正的”应用程序,这是我的错误。
Jeff revealed that the security database recognises apps by their path. If you copy an app to another folder, change it, and then try opening it there, this forces a signature check, and if that returns in an error, the app is crashed or terminated.
杰夫透露,安全数据库可以根据应用程序的路径识别它们。如果你把一个应用复制到另一个文件夹,改变它,然后试着在那里打开它,这会强制进行签名检查,如果返回一个错误,应用就会崩溃或终止。
This can be seen as a means of allowing apps to modify their own bundles once they have passed checks on first open – something which shouldn’t really happen now, as it means that malicious apps can also modify the bundle, which brings us back to the question of checking bundle signatures again.
这可以被视为一种手段,允许应用程序修改自己的包一旦通过了检查第一次打开,现在真的不应该发生,因为它意味着恶意程序也可以修改包,让我们回到问题的再次检查包签名。
If you want to craft yourself an app which runs fine but generates signature errors, place it in /Applications without modification (other than changing the name of the app, if you wish). Run it from there so that it registers with the security database, quit it, then perform the modifications in place. Chances are that it will then open normally in spite of the fact that its app bundle now has signature errors, as reported by What’s Your Sign or Signet.
如果你想制作一个运行良好但会产生签名错误的应用程序,把它放在/Applications中而不做任何修改(如果你愿意,除了更改应用程序的名称之外)。从那里运行它,以便它向安全数据库注册,退出它,然后在适当的地方执行修改。尽管它的应用程序包现在有签名错误,如What 's Your Sign or Signet报告的那样,但之后它很可能会正常打开。
Claims that such malicious tampering must be followed by the generation of new signatures are therefore wrong: macOS will happily run a subverted app in this way. This applies to signed apps and those which have been notarized.
因此,声称这种恶意篡改之后必须生成新签名的说法是错误的:macOS将愉快地以这种方式运行一个被破坏的应用程序。这适用于已签署的应用程序和已公证的应用程序。
Look at the log, though, and the picture is very different. Here are the relevant entries from opening an app whose signature validates without error: 但是,看看日志,情况就完全不同了。下面是打开一个签名验证无误的应用程序的相关条目:
06.644329 lsd Security SecTrustEvaluateIfNecessary
06.645934 com.apple.securityd rvc trustd trustd asynchronously fetching CRL (http://crl.apple.com/root.crl) for client (lsd[355]/0#-1 LF=0)
06.645961 com.apple.securityd policy trustd trustd cert[2]: AnchorTrusted =(leaf)[force]> 0
No error is returned, and app launch proceeds normally as expected. 没有返回任何错误,应用程序启动正常进行预期。
But is that certificate check actually a proper signature check? Look at what appears in the log when our altered app is opened:
但那张证书支票真的是正确的签名支票吗?当我们的修改后的应用程序被打开,看看什么出现在日志中:
00.486402 launchservicesd Security SecTrustEvaluateIfNecessary
00.488468 com.apple.securityd rvc trustd trustd asynchronously fetching CRL (http://crl.apple.com/root.crl) for client (launchservicesd[96]/0#-1 LF=0)
00.488498 com.apple.securityd policy trustd trustd cert[2]: AnchorTrusted =(leaf)[force]> 0
00.490739 com.apple.securityd security_exception launchservicesd Security MacOS error: -67030
Error -67030 means “invalid Info.plist (plist or signature have been modified)”, so is exactly what we’d expect after changing the app’s Info.plist.
错误-67030表示“无效Info.plist (plist或签名已被修改)”,这正是我们在更改应用程序的Info.plist后所期望的。
The same error is reported slightly later in response to a check by TCC:
稍后在TCC检查时报告了同样的错误:
00.495847 tccd Security SecTrustEvaluateIfNecessary
00.497237 com.apple.securityd rvc trustd trustd asynchronously fetching CRL (http://crl.apple.com/root.crl) for client (tccd[281]/0#-1 LF=0)
00.497343 com.apple.securityd policy trustd trustd cert[2]: AnchorTrusted =(leaf)[force]> 0
00.498542 com.apple.securityd security_exception tccd Security MacOS error: -67030
and this repeats again for sharedfilelistd, and for tccd again. Despite this error being returned in four separate checks, the app is allowed to open normally, and no warning is given to the user. Only if the app has been launched from a directory from which it has not previously been run, or if its quarantine flag is set, does macOS appear to react by stopping the launch or terminating the app.
对于sharedfilelistd和tccd,这种情况会再次重复。尽管这个错误在四个单独的检查中被返回,应用程序仍然被允许正常打开,并且没有给用户任何警告。只有当应用程序从之前没有运行过的目录中启动,或者设置了隔离标志,macOS才会停止启动或终止应用程序。
This is also true for an app with a signature using revoked certificates, provided that the app isn’t flagged as being in quarantine. For Microsoft Messenger, for example:
对于使用撤销证书签名的应用程序也是如此,前提是该应用程序没有被标记为处于隔离状态。例如,对于Microsoft Messenger:
00.380029 syspolicyd Security SecTrustEvaluateIfNecessary
00.380286 com.apple.securityd pinningQA trustd trustd could not enable test hierarchy: no UAT pinning preferences set
00.380439 com.apple.securityd policy trustd trustd cert[2]: WeakSignature =(leaf)[]> 0
00.380447 com.apple.securityd policy trustd trustd cert[2]: WeakSignature =(leaf)[]> 0
00.380756 com.apple.securityd policy trustd trustd cert[2]: WeakSignature =(leaf)[]> 0
00.380760 com.apple.securityd policy trustd trustd cert[2]: MissingIntermediate =(leaf)[force]> 0
00.380767 com.apple.securityd policy trustd trustd cert[2]: WeakSignature =(leaf)[]> 0
00.380777 com.apple.securityd policy trustd trustd cert[2]: WeakSignature =(path)[]> 0
00.380795 com.apple.securityd policy trustd trustd cert[2]: BlackListedKey =(path)[force]> 0
00.380935 com.apple.securityd SecError syspolicyd Security Trust evaluate failure: [root BlackListedKey MissingIntermediate WeakSignature]
00.381003 syspolicyd Security SecStaticCode: verification failed (trust result 6, error -2147409652)
00.381007 com.apple.securityd security_exception syspolicyd Security MacOS error: -2147409652
00.381107 com.apple.securityd security_exception syspolicyd Security MacOS error: -2147409652
00.381150 syspolicyd syspolicyd URL failed validity check (-2147409652): <private>
That is repeated for lsd, launchservicesd, tccd three times, then that whole sequence is repeated. Despite these many errors, the app continues to launch without any warning to the user.
重复lsd, launchservicesd, tccd三次,然后重复整个序列。尽管有这些错误,应用程序在没有任何警告的情况下继续启动。
When an app is terminated due to a signature check error, these are the distinctive log entries:
当一个应用程序由于签名检查错误而终止时,这些是独特的日志条目:
00.383124 com.apple.securityd MacOS error: -67030
00.383692 com.apple.MobileFileIntegrity <private>: Broken signature with Team ID fatal.
00.383781 mac_vnode_check_signature: /Applications/SignetTest.app/Contents/MacOS/Signet: code signature validation failed fatally: When validating /Applications/SignetTest.app/Contents/MacOS/Signet:
The code contains a Team ID, but validating its signature failed.
Please check your system log.
00.383800 proc 17245: load code signature error 4 for file "Signet"
and the app is terminated abruptly.
应用程序突然终止。
My conclusions from these observations are therefore:
因此,我从这些观察中得出的结论是:
- Whenever an app is opened in macOS 10.14.2, its signature is checked asynchronously, sometimes several times for different client processes.
- 只要在macOS 10.14.2中打开一个应用程序,它的签名就会被异步检查,有时会针对不同的客户端进程进行多次检查。
- If the signature checks return no error, the app launch proceeds uninterrupted.
- 如果签名检查没有返回错误,应用程序启动将不间断进行。
- f the signature checks return an error, the response is determined by security policy for that app. If it has a quarantine flag, or is running from that path for the first time, the app will normally fail to open, if necessary by crashing out.
- 如果签名检查返回一个错误,则响应由该应用程序的安全策略决定。如果它有一个隔离标志,或第一次从该路径运行,则该应用程序通常将无法打开,如果有必要则会崩溃。
- If an app has run successfully from the same path, and doesn’t have a quarantine flag, signature errors don’t normally result in any app termination or the user being informed. The app normally continues to open as if no error had occurred.
- 如果一个应用程序在同一路径上成功运行,并且没有隔离标志,签名错误通常不会导致任何应用程序终止或通知用户。应用程序通常会继续打开,就像没有发生错误一样。
- Security policy is also influenced by the type of error. For example, running for the first time from a different path appears to be tolerated when the signature error is of a revoked certificate, but not if changes are detected in the Info.plist or executable code.
- 安全策略也会受到错误类型的影响。例如,当签名错误是一个已撤销的证书时,首次从不同的路径运行似乎是可以容忍的,但如果在Info中检测到更改,则不能容忍。plist或可执行代码。
- Provided that it doesn’t result in setting the quarantine flag or altering the app’s path, an app can modify its own bundle, and it could be modified by another process, without re-signing the app; the user should still be able to open that app after modification, and not be alerted to such change. This also appears to apply to apps which have been notarized, at present.
- 如果不设置隔离标志或改变应用程序的路径,应用程序可以修改自己的包,也可以由另一个进程修改,而无需重新签署应用程序;在修改之后,用户应该仍然能够打开该应用程序,而不会收到此类更改的警告。这似乎也适用于目前已经公证的应用程序。
- Apps which wish to be protected from modification need to use other mechanisms (permissions, SIP) and shouldn’t expect their signatures to protect them.
- 希望被保护不受修改的应用程序需要使用其他机制(权限、SIP),不应该指望它们的签名来保护它们。
- For an app which checks it own signature to detect modification, it needs to check not only whether its signature is valid, but also whether that certificate is unchanged.
- 对于一个检查自己的签名来检测修改的应用程序,它不仅需要检查自己的签名是否有效,还需要检查证书是否没有改变。
- Users who discover that an app crashes when it is opened for the first time from a different folder should suspect that it has a signature error as a potential cause for that behaviour.
- 当用户第一次从不同的文件夹打开应用程序时发现它崩溃了,他们应该怀疑它有一个签名错误,可能是导致这种行为的一个潜在原因。