On Jul 12, 2013, at 12:19 PM, Jacobsen, Jasen W. <jasenj1@mitre.org> wrote:
What about non application things like libraries, printer drivers or browser plug-ins?
Off the top of my head you could use simple scripting tools like 'lpinfo -m’ to list all the printer drivers on the system. I think in most cases things like library versions come when you are looking for a specific version though to validate you are beyond a vulnerable level.
And can you elaborate a little on "use a metadata query and launch services to locate the apps"? Perhaps there are other OS X capabilities that OVAL should make available to system auditors.
Sure. If you are scripting things then you can use the mdfind command to find apps. For example, mdfind "kMDItemContentTypeTree == 'com.apple.application’" Is going to instantly find every app on your disks, regardless of where it is stored. You can then loop through them and read the info.plists. To my mind though it’s easier to do in Objective-C or some other object oriented language than it is to mash all that data around in a bash script. This is some really rough sample stuff code. Note that in the results processing you could also use NSString *appVersion = [theResult valueForAttribute:(NSString *)kMDItemVersion]; in an effort to not rely on needing to read each plist, but reading the plist lets us cover a use case for if developers don’t fill in both the short version string and the bundle version string. Starting the search: - (void)findApps { //Start our timer self.startDate = [NSDate timeIntervalSinceReferenceDate]; // Create the metadata query instance. The metadataSearch @property is // declared as retain self.metadataSearch=[[NSMetadataQuery alloc] init]; // Register the notifications for the completion updates [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryDidUpdate:) name:NSMetadataQueryDidUpdateNotification object:self.metadataSearch]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(initalGatherComplete:) name:NSMetadataQueryDidFinishGatheringNotification object:self.metadataSearch]; // Configure the search predicate to find all apps using the com.apple.application UTI NSPredicate *searchPredicate; searchPredicate=[NSPredicate predicateWithFormat:@"kMDItemContentTypeTree == 'com.apple.application'"]; [self.metadataSearch setPredicate:searchPredicate]; // Set the search scope to local disks NSArray *searchScopes; searchScopes=@[NSMetadataQueryLocalComputerScope]; [self.metadataSearch setSearchScopes:searchScopes]; // Begin the asynchronous query [self.metadataSearch startQuery]; } Then processing the results: // Method invoked when the initial query gathering is completed - (void)initalGatherComplete:sender; { // Stop the query, the single pass is completed. [self.metadataSearch stopQuery]; // Iterate the results and find our info. NSUInteger i=0; for (i=0; i < [self.metadataSearch resultCount]; i++) { NSMetadataItem *theResult = [self.metadataSearch resultAtIndex:i]; NSString *appPath = [theResult valueForAttribute:(NSString *)kMDItemPath]; // Use launch services to retrieve info and filter out invisibles and aliases // Launch Services is CF so we need to bridge to a CFURLRef CFURLRef appURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)appPath, kCFURLPOSIXPathStyle, YES); // Create our LSItemInfoRecord LSItemInfoRecord itemInfoRecord; // Pass in our CFURLRef and filter out invisibles and aliases LSCopyItemInfoForURL(appURL, kLSRequestBasicFlagsOnly | kLSRequestAppTypeFlags, &itemInfoRecord); //We don't need the appURL anymore so set it free CFRelease(appURL); if ((itemInfoRecord.flags & kLSItemInfoIsApplication) && !(itemInfoRecord.flags & kLSItemInfoIsInvisible) && !(itemInfoRecord.flags & kLSItemInfoIsAliasFile)) { // Make some strings to hold our data NSString *nameString = nil, *versionString = nil; // Make sure it really is an app bundle if (itemInfoRecord.flags & kLSItemInfoIsContainer) { // Get info for app bundles // Load in the Info.plist and read the keys NSDictionary *infoDictionary = [NSDictionary dictionaryWithContentsOfFile: [appPath stringByAppendingPathComponent: @"/Contents/Info.plist"]]; nameString = infoDictionary[@"CFBundleName"]; versionString = infoDictionary[@"CFBundleShortVersionString"]; if (!versionString) { versionString = infoDictionary[@"CFBundleVersion"]; } //Add our info to a mutable dict. NSDictionary *dict = @{@"appName": nameString, @"appVersion": versionString}; } } } // Remove the notifications to clean up after ourselves. // Also release the metadataQuery. // When the Query is removed the query results are also lost. [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidUpdateNotification object:self.metadataSearch]; [[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:self.metadataSearch]; self.metadataSearch=nil; //Stop our timer and figure how long that took NSTimeInterval totalTime; self.stopDate = [NSDate timeIntervalSinceReferenceDate]; self.theText = [NSString stringWithFormat:@"App search took: %.4f seconds", (totalTime = self.stopDate - self.startDate)]; }