3

I'm using kauth kernel framework in order to get events on files that are being opened in the system.

after filtering out the executable macho files, I'd like to check the signature validation for each such file that it's vnode is represented in vp = (vnode_t) arg1

Looking in xnu source code, I've found out mac_vnode_check_signature in mac_framework.h However it's not part of kernel public api... perhaps there are any alternatives ?

in user-space I've found good API for this called MOLCodesignChecker which is activated in the following way

MOLCodesignChecker *molChecker = [[MOLCodesignChecker alloc] initWithBinaryPath:filePath error:&error];
NSArray *certificates  = molChecker.certificates;
MOLCertificate *cert = [certificates objectAtIndex:i];
// print organization name e.g: "Apple Inc."
printf("signing name = %s", cert.orgName);

UPDATE :

Following pmdj advice below, I've found a way to extract the signature of a running process using csproc_get_blob and csproc_get_teamid to extract the specific field which may represent the vendor (there are also synonyms for vnode instead of process).

However, After calling this method on /usr/sbin/spindump I got NULL pointer (instead of valid string) and it matches the output from user-space command code sign :

codesign -dvvv /usr/sbin/spindump 
Executable=/usr/sbin/spindump
Identifier=com.apple.spindump
Format=Mach-O thin (x86_64)
CodeDirectory v=20100 size=3267 flags=0x0(none) hashes=95+5  location=embedded
Platform identifier=4
Hash type=sha256 size=32
CandidateCDHash sha256=d5bfa6a2a2ad8ffa377c6ef7f7b94c81821821fb
Hash choices=sha256
CDHash=d5bfa6a2a2ad8ffa377c6ef7f7b94c81821821fb
Signature size=4485
Authority=Software Signing
Authority=Apple Code Signing Certification Authority
Authority=Apple Root CA
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements count=1 size=68

As you can see, the TeamIdentifier is not set. I'd like to somehow extract the Authority out of cs_blob in order to get the vendor name (Apple in this case)

Zohar81
  • 4,554
  • 5
  • 29
  • 82
  • Checking the signature of a file in isolation doesn't make sense, as it would be vulnerable from TOCTOU. What are you actually trying to use this for? For example, it makes more sense to check the signature of a running process to authorise some activity, as you know the signature applies to the copy of the code that was actually loaded into memory. (And unfortunately, there are very few public KPIs related to codesigning, none of them officially supported to my knowledge.) – pmdj Sep 04 '18 at 11:54
  • the TOCTOU is not a problem since I'm monitoring every change in the file using kauth framework... come to think of it, It would also be nice to have signature checking for process.. can you tell me what API do you know (even if not supported) ? – Zohar81 Sep 04 '18 at 12:01
  • You can't monitor every file change using kauth: if the file is mmap()ed for writing anywhere, changes just happen without a callback. – pmdj Sep 04 '18 at 12:19
  • That's right if I'm using fileop scope (especially with the bit KAUTH_FILEOP_CLOSE_MODIFIED), but I think that if scanning the vnode scope on all actions, I can cover this hole as well. – Zohar81 Sep 04 '18 at 12:24
  • If you always deny all write actions, then yes, possibly. Kauth doesn't have any way to distinguish between `mmap` and other I/O, so you always have to assume the worst. – pmdj Sep 04 '18 at 12:25
  • 1
    There is the function `struct cs_blob *ubc_cs_blob_get(struct vnode* vp, cpu_type_t cputype, off_t offset)` in the `unsupported` KPI. `cs_blob` is an unsupported struct, and changes from OS version to OS version, but I believe it should have various useful pieces of info. This function only works if the vnode is in the UBC and has had its code signature parsed and verified already. (e.g. is about to be run - I think it should work in the KAUTH_FILEOP_EXEC callback to identify a signed vs unsigned process for example) I've never used this in production code though, so beware of edge cases. – pmdj Sep 04 '18 at 12:27
  • Thanks for the input, I still trying to figure out if there's way to parse this blob and extract the organization name from it ...or perhaps I can verify that it's apple signature by looking at other fields such as `csb_entitilements` ? – Zohar81 Sep 04 '18 at 13:26
  • 1
    `const char *csb_teamid;` in `cs_blob` should be what you want (note that `struct cs_blob` is defined in `ubc_internal.h`) – pmdj Sep 04 '18 at 13:30
  • so apparently Apple signed processes doesn't have valid value in csb_teamid field ... perhaps there are another field to extract the vendor in this case ? – Zohar81 Sep 05 '18 at 07:22
  • The answer seems to lie with the `csb_flags` field of the blob. Executables signed by a 3rd party team will have the team ID set, and `CS_VALID | CS_SIGNED` flags. You should probably also check that `CS_ADHOC` is *not* set, and if you want to only allow production (deployment/developer ID) certs, not "Mac Developer", you will also want to exclude `CS_DEV_CODE`. Apple-signed code on the other hand will not have a team ID but the `CS_PLATFORM_BINARY` flag set. `CS_PLATFORM_PATH` may be set for some legacy executables, I'm not sure though. – pmdj Dec 03 '18 at 21:33
  • I've just made this work on a project, and I'm going to put together a standalone example and write up a proper answer to your question, but this should get you started until then. – pmdj Dec 03 '18 at 21:33
  • @pmdj, Hi, if you still have it, perhaps you can post the example you have. I already found tweak for this, but I'd be happy to hear different approaches. Thanks ! – Zohar81 Jan 29 '19 at 17:50

0 Answers0