I can become an Apple, and you too

Public disclosure of vulnerability in third-party verification of the signature code Apple


Unlike some previous works, this vulnerability does not require administrative rights, does not require JIT-code or memory damage to bypass the code signature verification. All that is needed is a correctly formatted Fat / Universal file, and verification of the code signature will show a valid result.

Summary



Affected vendors




The importance of code signing and how it works on macOS / iOS


Code signature is a security construct that uses a public key infrastructure (PKI) to digitally sign compiled code or even scripts to verify the origin and ensure the authenticity of the code. On Windows, you can cryptographically sign almost anything: from .NET binaries to PowerShell scripts. On macOS / iOS, code signing refers primarily to Mach-O binary files and application packages in order to allow only trusted code to be executed in memory.

Antivirus, security and incident response systems, as well as forensic examination tools analyze signatures to identify trusted code among untrusted ones. Signature verification speeds analysis. Various tools use code signature information to implement security measures: these are whitelists, antiviruses, incident response systems and the search for threats. To compromise the code signature in one of the popular operating systems is to undermine the basic security design, on which many routine operations in the field of information security depend.

We already found problems in the code signature ( 1 , 2 , 3 , 4 , 5 ). Unlike some previous works, this vulnerability does not require administrative rights, does not require JIT-code or memory damage to bypass the code signature verification. All that is needed is a correctly formatted Fat / Universal file, and verification of the code signature will show a valid result.

Vulnerability Details


The essence of the vulnerability in unequal verification of the code signature by the loader Mach-O and Code Signing API, which are used incorrectly. This difference can be exploited using a specially crafted Universal / Fat binary file.

What is a Fat / Universal file?

Fat / Universal is a binary format that contains several Mach-O files (executable, dyld, or package), each of which is oriented to a specific CPU architecture (for example, i386, x86_64 or PPC).

The necessary conditions



Without passing the corresponding SecRequirementRef and SecCSFlags , the Code Signing API ( SecCodeCheckValidity ) program interface will check the first binary in the Fat / Universal file for the origin of the signature (for example, Apple) and verify the authenticity of the signature. The API will then check all other binaries in the Fat / Universal file for compliance with Team Identifiers and the authenticity of the signature, but without checking the trust center of the certification authority . The reason why a malicious code or “unsigned” code must be i386 is that the Code Signing API is by default configured to verify first the code signature for the native CPU architecture (x86_64).

One of the reasons why the self-signed code successfully passes the test is because even in the Apple core binaries, the TeamIdentifier field is set to not set . The illustration below shows the valid Mach-O binary signed by Apple (python.x64), next to the self-signed Mach-O (ncat.i386). Both have `TeamIdentifier = not set`.



For example, I signed a binary with the help of a developer ID and tried to combine it in lipo with Apple's binary into one Fat / Universal file. This option code signature does not pass.



My initial PoC is ncat (from nmap), which I called ncat.frankenstein. Here the resulting Fat file contains the Apple-signed binary python x86_64 and the self-signed (adhoc) binary ncat i386. A self-signed binary is easily created with the codesign -s - target_mach-o_or_fat_binary . Here is how it looks in MachOView:



If you run this file, it will start python x86_64:



And the code signature is being verified:



How do I run the ncat self-signed binary file?

This is done by setting an invalid CPU_Type type or a non-native CPU (for example, PPC). Then the Mach-O loader skips the Mach-O binary with a valid signature and executes malicious (not Apple-signed) code:



Then ncat.frankenstein is executed, and the result will be valid :



We published ncat.frankenstein and four other examples so that developers can check for vulnerabilities in their products.

Recommendations


Command line

It depends on how you check the signed code. If you use codesign, you are probably familiar with the following commands:



But for correct verification of this type of abuse you need to add the requirement of an anchor-certificate with the following commands :


This command will show an error when checking the code with someone else's signature:



You can use the spctl command, but it requires careful analysis of the command output. For example, a Mach-O binary with an Apple signature (/ bin / ls) and Safari returns the following:



And here is the result of an application signed by Apple:



Note the line “(the code is valid but doesn’t seem to be an app)” for / bin / ls, which does not pass the test. For comparison, here is the result of the Fat / Universal ncat.frankenstein file:



The file ncat.frankenstein Fat / Universal does not indicate that the code is valid. Thus, I cannot recommend spctl to manually check the Mach-O standalone binaries. Just use codesign with the appropriate flags.

For developers

As a rule, developers check Mach-O or Fat / Universal binaries using the SecStaticCodeCheckValidityWithErrors () or SecStaticCodeCheckValidity () API with the following flags:


These flags must ensure that all loaded code in the Mach-O or Fat / Universal file is cryptographically signed. However, these default APIs do not provide proper validation, so third-party developers need to isolate each architecture in the Fat / Universal file and verify that identities are the same and cryptographically secure.

The best way to check each nested architecture in the Fat / Universal file is to first call SecRequirementCreateWithString with the requirement “anchor apple”, then SecStaticCodeCheckValidity with flags kSecCSDefaultFlags | kSecCSCheckNestedCode | kSecCSCheckAllArchitectures | kSecCSEnforceRevocationChecks with reference to the requirement; as shown in the WhatsYourSign patched source code.

By passing the “anchor apple” to the SecRequirmentCreateWithString function, this call acts like the codesign -vv -R='anchor apple' command, requiring the Apple Software Signing trust chain for all nested binaries in the Fat / Universal file. In addition, by passing flags and a SecStaticCodeCheckValidity requirement, all architectures are checked for this requirement, and revocation checks are applied.

Demonstrations


Apple's codesign tool and the need to use the -R flag.



LittleSnitch - checking the file Fat / Universal on the disk fails, but LittleSnitch correctly checks the process in memory.





LittleFlocker - F-Secure bought LittleFlocker, and now it's called xFence.



F-Secure xFence (formerly LittleFlocker)



Objective-See Tools

TaskExplorer





Whatsourseign



Facebook OSquery is the result of testing malware samples and / bin / ls as a valid example.



The issuance of Google Santa - Fileinfo shows that ncat.frankenstein is in the white list:



Disable execution of ncat (unsigned) and enable execution of ncat.frankenstein:



Santa.log with a demonstration of events from the previous example:



Carbon Black Response



VirusTotal is an example of bash_ppc_adhoc before installing a patch in VirusTotal:



Disclosure terms


02.22.2018: Report and PoC were sent to Apple to bypass third-party security systems.

03/01/2018: Apple responded that third-party developers should use the kSecCSCheckAllArchitectures and kSecCSStrictValidate with the SecStaticCodeCheckValidity API, and the developer documentation will be updated accordingly.

03/06/2018: A report and PoC were sent to Apple to bypass the flags and strictly check codesign .

03/16/2018: Additional information has been sent to Apple.

03/20/2018: Apple stated that it does not see this as a security issue that should be addressed directly.

03/29/2018: Apple stated that the documentation could be updated, but "[...] third-party developers should do additional work to check that all identities in the universal binary are the same if they want to present a meaningful result."

04/02/2018: first contact with CERT / CC and subsequent collaboration to clarify the scope and impact of the vulnerability.

04/09/2018: All known third-party developers affected by the vulnerability are notified in coordination with CERT / CC.

04/18/2018: Last contact with CERT / CC with the recommendation that public blog information is best suited for notifying other third-party developers who use Apple’s code signing API in private.

06/05/2018: final contact with developers before publication.

12.06.2018: disclosure of information.

Finally


Thanks to all third-party developers for their hard work and professionalism in solving this issue. Code signature vulnerabilities are especially demoralizing bugs, especially for companies that are trying to provide security better than the default in the operating system.



PROMOTION GMO GlobalSign Russia for Habr subscribers


For more information, please contact the GlobalSign manager by phone: +7 (499) 678 2210, or fill out the form on the website, specifying the promotional code CS002HBFR.

Source: https://habr.com/ru/post/414011/


All Articles