Apps can opt-in to Gatekeeper and Xprotect protection by
adding LSFileQuarantineEnabled to their Contents/Info.plist. This means that any files created by that app will get tagged with the apple quarantine
HFS+ extended attribute.
For example, here's what chrome looks like when downloaded with Safari:
$ ls -l@eOd Downloads/googlechrome.dmg
-rw-r--r--@ 1 user group - 39937778 Apr 16 11:31 Downloads/googlechrome.dmg
com.apple.diskimages.fsck 20
com.apple.diskimages.recentcksum 79
com.apple.metadata:kMDItemDownloadedDate 53
com.apple.metadata:kMDItemWhereFroms 210
com.apple.quarantine 57
and the same file downloaded with curl (which isn't a cocoa app and hence can't opt-in):
$ curl -o chrome_curl.dmg -L https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 38.0M 100 38.0M 0 0 15.7M 0 0:00:02 0:00:02 --:--:-- 18.2M
$ ls -l@eOd chrome_curl.dmg
-rw-r--r-- 1 user group - 39937627 Apr 20 14:47 chrome_curl.dmg
Looking at the contents of the extended attributes we see a bunch of interesting metadata, including the HTTP referrer in a binary plist inside 'com.apple.metadata:kMDItemWhereFroms' and the quaratine attribute in 'com.apple.quarantine'.
$ xattr -l Downloads/googlechrome.dmg
com.apple.diskimages.fsck: |?W??\<!*
?#Z???r??u
com.apple.diskimages.recentcksum: i:325165 on 3A5356B1-31CB-32FB-AFC7-DBE23A5C1547 @ 1334601060 - CRC32:$AE7BD4AF
com.apple.metadata:kMDItemDownloadedDate:
00000000 62 70 6C 69 73 74 30 30 A1 01 33 41 B5 42 0E 78 |bplist00..3A.B.x|
00000010 17 F3 17 08 0A 00 00 00 00 00 00 01 01 00 00 00 |................|
00000020 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 |................|
00000030 00 00 00 00 13 |.....|
00000035
com.apple.metadata:kMDItemWhereFroms:
00000000 62 70 6C 69 73 74 30 30 A2 01 02 5F 10 3D 68 74 |bplist00..._.=ht|
00000010 74 70 73 3A 2F 2F 64 6C 2E 67 6F 6F 67 6C 65 2E |tps://dl.google.|
00000020 63 6F 6D 2F 63 68 72 6F 6D 65 2F 6D 61 63 2F 73 |com/chrome/mac/s|
00000030 74 61 62 6C 65 2F 47 47 52 4D 2F 67 6F 6F 67 6C |table/GGRM/googl|
00000040 65 63 68 72 6F 6D 65 2E 64 6D 67 5F 10 61 68 74 |echrome.dmg_.aht|
00000050 74 70 73 3A 2F 2F 77 77 77 2E 67 6F 6F 67 6C 65 |tps://www.google|
00000060 2E 63 6F 6D 2F 63 68 72 6F 6D 65 3F 26 62 72 61 |.com/chrome?&bra|
00000070 6E 64 3D 43 48 4D 41 26 75 74 6D 5F 63 61 6D 70 |nd=CHMA&utm_camp|
00000080 61 69 67 6E 3D 65 6E 26 75 74 6D 5F 73 6F 75 72 |aign=en&utm_sour|
00000090 63 65 3D 65 6E 2D 68 61 2D 6E 61 2D 75 73 2D 62 |ce=en-ha-na-us-b|
000000A0 6B 26 75 74 6D 5F 6D 65 64 69 75 6D 3D 68 61 08 |k&utm_medium=ha.|
000000B0 0B 4B 00 00 00 00 00 00 01 01 00 00 00 00 00 00 |.K..............|
000000C0 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
000000D0 00 AF |..|
000000d2
com.apple.quarantine: 0002;4f91d6f8;Safari;A89FCF40-0748-46BE-9C5E-1599A280E9D6
Breaking down this string based on the description in:
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Headers/LSQuarantine.h
- 0002: kLSQuarantineType (I think), one of:
- kLSQuarantineTypeWebDownload
- kLSQuarantineTypeOtherDownload
- kLSQuarantineTypeEmailAttachment
- kLSQuarantineTypeInstantMessageAttachment
- kLSQuarantineTypeCalendarEventAttachment
- kLSQuarantineTypeOtherAttachment
- 4f91d6f8: LSQuarantineTimeStamp, seconds since epoch timestamp in hex, print with 'date -r 0x4f91d6f8'
- Safari: kLSQuarantineAgentName, the name of the process that wrote the file, or whatever the process sets via the API.
- A89FCF40-0748-46BE-9C5E-1599A280E9D6: a UUID. The key (LSQuarantineEventIdentifier) used for entries in the SQLite DB.
Wait, what SQLite DB? The one here:
$ sqlite3 /Users/auser/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2
sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE LSQuarantineEvent ( LSQuarantineEventIdentifier TEXT PRIMARY KEY NOT NULL, LSQuarantineTimeStamp REAL, LSQuarantineAgentBundleIdentifier TEXT, LSQuarantineAgentName TEXT, LSQuarantineDataURLString TEXT, LSQuarantineSenderName TEXT, LSQuarantineSenderAddress TEXT, LSQuarantineTypeNumber INTEGER, LSQuarantineOriginTitle TEXT, LSQuarantineOriginURLString TEXT, LSQuarantineOriginAlias BLOB );
INSERT INTO "LSQuarantineEvent" VALUES('A89FCF40-0748-46BE-9C5E-1599A280E9D6',356650616.054473,'com.apple.Safari','Safari','https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg',NULL,NULL,0,NULL,'https://www.google.com/',NULL);
CREATE INDEX LSQuarantineEventIndex ON LSQuarantineEvent ( LSQuarantineEventIdentifier );
COMMIT;
Note the NULL fields, which are optional fields that can be filled in by the developer who writes the file. The OS writes LSQuarantineAgentNameKey, LSQuarantineAgentBundleIdentifierKey, and LSQuarantineTimeStampKey by default. Chrome
adds LSQuarantineDataURLString and LSQuarantineOriginURLString.
Apple said in the
Leopard Launch Services release notes:
When the Launch Services API is used to open a quarantined file and the file appears to be an application, script, or other executable file type, Launch Services will display an alert to confirm the user understands the file is some kind of application. If the file is opened, the quarantine properties are automatically cleared by Launch Services if the user has write access to the file.
So translating this to the Gatekeeper world, with the default settings Gatekeeper will block execution and fire an alert if:
- The file is opened with Launch Services (e.g. from the finder via user action, from another cocoa app, or as a mime handler). Excludes executables/installers run from the commandline, or programmatically via POSIX APIs. 'UnsafeExecutable' may play a role here (needs checking).
- The file has the quarantine xattr set.
- The file is not signed by apple or an apple developer cert.
Xprotect follows similar logic, and checks files against the attributes in
/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/XProtect.plist
to determine if the file is known-bad.
No comments:
Post a Comment