2021-08-15 16:53:02 +00:00
# Mobile Verification Toolkit (MVT)
2022-05-08 12:53:50 +00:00
# Copyright (c) 2021-2022 Claudio Guarnieri.
2021-08-15 16:53:02 +00:00
# Use of this software is governed by the MVT License 1.1 that can be found at
# https://license.mvt.re/1.1/
2021-12-16 21:58:36 +00:00
import os
2021-08-15 16:53:02 +00:00
import plistlib
from base64 import b64encode
2022-01-11 15:02:44 +00:00
2021-12-16 16:57:26 +00:00
from mvt . common . utils import convert_timestamp_to_iso
2021-08-15 16:53:02 +00:00
from . . base import IOSExtraction
CONF_PROFILES_DOMAIN = " SysSharedContainerDomain-systemgroup.com.apple.configurationprofiles "
2021-11-19 14:27:51 +00:00
2021-08-15 16:53:02 +00:00
class ConfigurationProfiles ( IOSExtraction ) :
2021-09-10 13:18:13 +00:00
""" This module extracts the full plist data from configuration profiles. """
2021-08-15 16:53:02 +00:00
def __init__ ( self , file_path = None , base_folder = None , output_folder = None ,
fast_mode = False , log = None , results = [ ] ) :
super ( ) . __init__ ( file_path = file_path , base_folder = base_folder ,
output_folder = output_folder , fast_mode = fast_mode ,
log = log , results = results )
2021-12-16 16:57:26 +00:00
def serialize ( self , record ) :
if not record [ " install_date " ] :
return
2021-12-16 21:58:36 +00:00
payload_name = record [ ' plist ' ] . get ( ' PayloadDisplayName ' )
payload_description = record [ ' plist ' ] . get ( ' PayloadDescription ' )
2021-12-16 16:57:26 +00:00
return {
" timestamp " : record [ " install_date " ] ,
" module " : self . __class__ . __name__ ,
" event " : " configuration_profile_install " ,
2021-12-16 21:58:36 +00:00
" data " : f " { record [ ' plist ' ] [ ' PayloadType ' ] } installed: { record [ ' plist ' ] [ ' PayloadUUID ' ] } - { payload_name } : { payload_description } "
2021-12-16 16:57:26 +00:00
}
def check_indicators ( self ) :
if not self . indicators :
return
for result in self . results :
if result [ " plist " ] . get ( " PayloadUUID " ) :
payload_content = result [ " plist " ] [ " PayloadContent " ] [ 0 ]
# Alert on any known malicious configuration profiles in the indicator list.
2022-01-23 14:01:49 +00:00
ioc = self . indicators . check_profile ( result [ " plist " ] [ " PayloadUUID " ] )
if ioc :
2021-12-16 16:57:26 +00:00
self . log . warning ( f " Found a known malicious configuration profile \" { result [ ' plist ' ] [ ' PayloadDisplayName ' ] } \" with UUID ' { result [ ' plist ' ] [ ' PayloadUUID ' ] } ' . " )
2022-01-23 14:01:49 +00:00
result [ " matched_indicator " ] = ioc
2021-12-16 16:57:26 +00:00
self . detected . append ( result )
continue
# Highlight suspicious configuration profiles which may be used to hide notifications.
if payload_content [ " PayloadType " ] in [ " com.apple.notificationsettings " ] :
self . log . warning ( f " Found a potentially suspicious configuration profile \" { result [ ' plist ' ] [ ' PayloadDisplayName ' ] } \" with payload type ' { payload_content [ ' PayloadType ' ] } ' . " )
self . detected . append ( result )
continue
2021-08-15 16:53:02 +00:00
def run ( self ) :
2021-08-15 18:00:29 +00:00
for conf_file in self . _get_backup_files_from_manifest ( domain = CONF_PROFILES_DOMAIN ) :
2021-12-16 21:58:36 +00:00
conf_rel_path = conf_file [ " relative_path " ]
# Filter out all configuration files that are not configuration profiles.
if not conf_rel_path or not os . path . basename ( conf_rel_path ) . startswith ( " profile- " ) :
continue
2021-08-15 16:53:02 +00:00
conf_file_path = self . _get_backup_file_from_id ( conf_file [ " file_id " ] )
if not conf_file_path :
continue
with open ( conf_file_path , " rb " ) as handle :
2021-12-02 15:55:14 +00:00
try :
conf_plist = plistlib . load ( handle )
2022-01-11 15:02:01 +00:00
except Exception :
2021-12-02 15:55:14 +00:00
conf_plist = { }
2021-08-15 16:53:02 +00:00
if " SignerCerts " in conf_plist :
conf_plist [ " SignerCerts " ] = [ b64encode ( x ) for x in conf_plist [ " SignerCerts " ] ]
2022-01-25 19:32:27 +00:00
if " OTAProfileStub " in conf_plist :
if " SignerCerts " in conf_plist [ " OTAProfileStub " ] :
conf_plist [ " OTAProfileStub " ] [ " SignerCerts " ] = [ b64encode ( x ) for x in conf_plist [ " OTAProfileStub " ] [ " SignerCerts " ] ]
2022-03-25 19:36:30 +00:00
if " PayloadContent " in conf_plist [ " OTAProfileStub " ] :
if " EnrollmentIdentityPersistentID " in conf_plist [ " OTAProfileStub " ] [ " PayloadContent " ] :
conf_plist [ " OTAProfileStub " ] [ " PayloadContent " ] [ " EnrollmentIdentityPersistentID " ] = b64encode ( conf_plist [ " OTAProfileStub " ] [ " PayloadContent " ] [ " EnrollmentIdentityPersistentID " ] )
2021-12-02 15:55:14 +00:00
if " PushTokenDataSentToServerKey " in conf_plist :
2021-12-16 16:57:26 +00:00
conf_plist [ " PushTokenDataSentToServerKey " ] = b64encode ( conf_plist [ " PushTokenDataSentToServerKey " ] )
2021-12-02 15:55:14 +00:00
if " LastPushTokenHash " in conf_plist :
2021-12-16 16:57:26 +00:00
conf_plist [ " LastPushTokenHash " ] = b64encode ( conf_plist [ " LastPushTokenHash " ] )
2021-12-02 15:55:14 +00:00
if " PayloadContent " in conf_plist :
2021-12-16 16:57:26 +00:00
for x in range ( len ( conf_plist [ " PayloadContent " ] ) ) :
if " PERSISTENT_REF " in conf_plist [ " PayloadContent " ] [ x ] :
conf_plist [ " PayloadContent " ] [ x ] [ " PERSISTENT_REF " ] = b64encode ( conf_plist [ " PayloadContent " ] [ x ] [ " PERSISTENT_REF " ] )
2022-03-25 19:36:30 +00:00
if " IdentityPersistentRef " in conf_plist [ " PayloadContent " ] [ x ] :
conf_plist [ " PayloadContent " ] [ x ] [ " IdentityPersistentRef " ] = b64encode ( conf_plist [ " PayloadContent " ] [ x ] [ " IdentityPersistentRef " ] )
2021-08-15 16:53:02 +00:00
2021-08-15 17:05:15 +00:00
self . results . append ( {
" file_id " : conf_file [ " file_id " ] ,
" relative_path " : conf_file [ " relative_path " ] ,
" domain " : conf_file [ " domain " ] ,
" plist " : conf_plist ,
2021-12-16 16:57:26 +00:00
" install_date " : convert_timestamp_to_iso ( conf_plist . get ( " InstallDate " ) ) ,
2021-08-15 17:05:15 +00:00
} )
2021-08-15 16:53:02 +00:00
2021-12-02 17:31:07 +00:00
self . log . info ( " Extracted details about %d configuration profiles " , len ( self . results ) )