Skip to content

Instantly share code, notes, and snippets.

@pudquick
Created April 19, 2019 21:52
Show Gist options
  • Save pudquick/c102972d24bdfc5aa7254219ba0db9ca to your computer and use it in GitHub Desktop.
Save pudquick/c102972d24bdfc5aa7254219ba0db9ca to your computer and use it in GitHub Desktop.
locally checking profile signing information
#!/usr/bin/python
# So the first thing we need to do is get the mdmclient view of the profiles
import subprocess, objc
from Foundation import NSPropertyListSerialization, NSPropertyListMutableContainers, NSBundle
Security = NSBundle.bundleWithIdentifier_('com.apple.security')
S_functions = [
('SecCertificateCreateWithData', '@@@'),
('SecCertificateCopyValues', '@@^@o^@'),
]
objc.loadBundleFunctions(Security, globals(), S_functions)
try:
profile_info = subprocess.check_output(['/usr/libexec/mdmclient', 'QueryInstalledProfiles'])
except:
profile_info = ""
if profile_info and ("will return:" in profile_info):
try:
profile_next = buffer(profile_info.split('will return: ',1)[-1])
mdm_profiles, _, error = NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription_(profile_next, NSPropertyListMutableContainers, None, None)
except:
mdm_profiles = []
else:
mdm_profiles = []
# Then the next thing we need to do is grab the output from profiles itself
try:
profile_next = subprocess.check_output(['/usr/bin/profiles', '-C', '-o', 'stdout-xml'])
except:
profile_next = ""
if profile_next:
try:
std_profiles, _, error = NSPropertyListSerialization.propertyListFromData_mutabilityOption_format_errorDescription_(buffer(profile_next), NSPropertyListMutableContainers, None, None)
except:
std_profiles = {}
else:
std_profiles = {}
std_profiles = std_profiles.get("_computerlevel", [])
# Ok, so now we have both the mdm profiles and the standard profiles and we need to marry it based on ... profile ID?
combined_profiles = dict()
for x in mdm_profiles:
profile_id = tuple([x.get('PayloadUUID', 'uuid'), x.get('PayloadIdentifier', 'id')])
combined_profiles[profile_id] = combined_profiles.get(profile_id, dict())
combined_profiles[profile_id].update(dict(x))
for x in std_profiles:
profile_id = tuple([x.get('ProfileUUID', 'uuid'), x.get('ProfileIdentifier', 'id')])
combined_profiles[profile_id] = combined_profiles.get(profile_id, dict())
combined_profiles[profile_id].update(dict(x))
# Ok, now let's find the one(s) that have a ProfileItems with a PayloadType of 'com.apple.security.scep'
scep_profiles = dict()
for k, v in combined_profiles.items():
for x in v.get('ProfileItems', []):
if x['PayloadType'] == u'com.apple.security.scep':
scep_profiles[k] = v
break
# Now we want to limit it to the profile which
some_scep = None
for k, v in scep_profiles.items():
for x in v.get('ProfileItems', []):
if x['PayloadType'] == u'com.apple.wifi.managed':
# It's a wifi profile, let's check the SSID
if x['PayloadContent']['SSID_STR'] == u'ThatSSID':
# It's ours
some_scep = v
# Ok, now to collect our data!
if some_scep is None:
# No matching profiles found
quit()
# signature information
sign_expire = ""
sign_name = ""
cert_data = some_scep.get('SignerCertificates', [])
if cert_data:
try:
cert_ref = SecCertificateCreateWithData(None, cert_data[0])
cert_details, errors = SecCertificateCopyValues(cert_ref, None, None)
sign_expire = cert_details["2.5.29.24"]['value'].__repr__().split(' ', 1)[0]
sign_name = [x for x in cert_details["2.16.840.1.113741.2.1.1.1.8"]['value'] if x["label"] == "2.5.4.3"][0]["value"]
except:
pass
# does the profile contain a cert for that.site
has_enroll_cert = ""
try:
scep_certs = [x for x in some_scep['ProfileItems'] if x['PayloadType'] == 'com.apple.security.pkcs1']
for x in scep_certs:
if 'that.site' in x.get('PayloadDisplayName', ''):
has_enroll_cert = "1"
except:
pass
@pudquick
Copy link
Author

pudquick commented Apr 19, 2019

Alternate verb

import subprocess
raw_profile_info = subprocess.check_output(['/usr/libexec/mdmclient', 'installedProfiles']).splitlines()

last_uuid = None
signed_profiles = dict()
for i, x in enumerate(raw_profile_info):
    if x.startswith('UUID:'):
        last_uuid = x.strip().split(' ')[-1]
    if 'CMSCertificatesInfo = ' in x:
        cert_data = raw_profile_info[i+2]
        if ('CertData = <' in cert_data) and (last_uuid is not None):
            raw_data = cert_data.split('<')[-1].split('>')[0].replace(' ', '').decode('hex')
            signed_profiles[last_uuid] = raw_data

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment