Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

santad: add critical system binaries #296

Merged
merged 3 commits into from Sep 20, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 4 additions & 4 deletions Podfile.lock
Expand Up @@ -7,11 +7,11 @@ PODS:
- MOLCertificate (1.9)
- MOLCodesignChecker (1.10):
- MOLCertificate (~> 1.8)
- MOLFCMClient (1.7):
- MOLFCMClient (1.8):
- MOLAuthenticatingURLSession (~> 2.4)
- MOLXPCConnection (1.2):
- MOLCodesignChecker (~> 1.9)
- OCMock (3.4.1)
- OCMock (3.4.2)

DEPENDENCIES:
- FMDB
Expand All @@ -37,9 +37,9 @@ SPEC CHECKSUMS:
MOLAuthenticatingURLSession: c238aa1c9a7b1077eb39a6f40204bfe76a7d204e
MOLCertificate: e9e88a396c57032cab847f51a46e20c730cd752a
MOLCodesignChecker: b0d5db9d2f9bd94e0fd093891a5d40e5ad77cbc0
MOLFCMClient: ee45348909351f232e2759c580329072ae7e02d4
MOLFCMClient: 2bfbacd45cc11e1ca3c077e97b80401c4e4a54f1
MOLXPCConnection: c27af5cb1c43b18319698b0e568a8ddc2fc1e306
OCMock: 2cd0716969bab32a2283ff3a46fd26a8c8b4c5e3
OCMock: ebe9ee1dca7fbed0ff9193ac0b3e2d8862ea56f6

PODFILE CHECKSUM: ddca043a7ace9ec600c108621c56d13a50d17236

Expand Down
9 changes: 9 additions & 0 deletions Source/santad/DataLayer/SNTRuleTable.h
Expand Up @@ -17,6 +17,7 @@
#import "SNTCommonEnums.h"
#import "SNTDatabaseTable.h"

@class SNTCachedDecision;
@class SNTRule;
@class SNTNotificationMessage;

Expand Down Expand Up @@ -88,4 +89,12 @@
///
- (void)removeOutdatedTransitiveRules;


///
/// A map of a file hashes to cached decisions. This is used to pre-validate and whitelist
/// certain critical system binaries that are integral to Santa's functionality.
///
@property(readonly, nonatomic)
NSDictionary<NSString *, SNTCachedDecision *> *criticalSystemBinaries;

@end
31 changes: 30 additions & 1 deletion Source/santad/DataLayer/SNTRuleTable.m
Expand Up @@ -17,7 +17,9 @@
#import <MOLCertificate/MOLCertificate.h>
#import <MOLCodesignChecker/MOLCodesignChecker.h>

#import "SNTCachedDecision.h"
#import "SNTConfigurator.h"
#import "SNTFileInfo.h"
#import "SNTLogging.h"
#import "SNTRule.h"

Expand All @@ -31,6 +33,7 @@ @interface SNTRuleTable ()
@property NSString *santadCertSHA;
@property NSString *launchdCertSHA;
@property NSDate *lastTransitiveRuleCulling;
@property NSDictionary *criticalSystemBinaries;
@end

@implementation SNTRuleTable
Expand Down Expand Up @@ -64,7 +67,8 @@ - (uint32_t)initializeDatabase:(FMDatabase *)db fromVersion:(uint32_t)version {
// Save hashes of the signing certs for launchd and santad.
// Used to ensure rules for them are not removed.
self.santadCertSHA = [[[[MOLCodesignChecker alloc] initWithSelf] leafCertificate] SHA256];
self.launchdCertSHA = [[[[MOLCodesignChecker alloc] initWithPID:1] leafCertificate] SHA256];
MOLCodesignChecker *launchdCSInfo = [[MOLCodesignChecker alloc] initWithPID:1];
self.launchdCertSHA = launchdCSInfo.leafCertificate.SHA256;

// Ensure the certificates used to sign the running launchd/santad are whitelisted.
// If they weren't previously and the database is not new, log an error.
Expand All @@ -87,6 +91,31 @@ - (uint32_t)initializeDatabase:(FMDatabase *)db fromVersion:(uint32_t)version {
self.launchdCertSHA, @(SNTRuleStateWhitelist), @(SNTRuleTypeCertificate)];
}

// Setup critical system binaries
// TODO(tburgin): Add the Santa components to this feature and remove the santadCertSHA rule.
NSMutableDictionary *bins = [NSMutableDictionary dictionary];
for (NSString *path in @[ @"/usr/libexec/trustd" ]) {
SNTFileInfo *binInfo = [[SNTFileInfo alloc] initWithPath:path];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this fail the right way if there's no file at path? I'm guessing csInfo will end up nil and then the call to signingInformationMatches: will return NO?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if csInfo is nil, sending any message to it will return nil.

MOLCodesignChecker *csInfo = [binInfo codesignCheckerWithError:NULL];

// Make sure the critical system binary is signed by the same chain as launchd.
if ([csInfo signingInformationMatches:launchdCSInfo]) {
SNTCachedDecision *cd = [[SNTCachedDecision alloc] init];

cd.decision = SNTEventStateAllowBinary;
cd.decisionExtra = @"critical system binary";
cd.sha256 = binInfo.SHA256;

// Not needed, but nice for logging.
cd.certSHA256 = csInfo.leafCertificate.SHA256;
cd.certCommonName = csInfo.leafCertificate.commonName;

bins[binInfo.SHA256] = cd;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

log error if signing info doesn't match?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea

}

self.criticalSystemBinaries = bins;

return newVersion;
}

Expand Down
15 changes: 11 additions & 4 deletions Source/santad/SNTExecutionController.m
Expand Up @@ -116,21 +116,28 @@ - (void)validateBinaryWithMessage:(santa_message_t)message {
}

// Get codesigning info about the file but only if it's a Mach-O.
// If the binary is a critical system binary, don't check its signiture. The binary was validated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: signiture -> signature

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops

// by santad at startup.
SNTCachedDecision *cd = self.ruleTable.criticalSystemBinaries[binInfo.SHA256];
MOLCodesignChecker *csInfo;
if (binInfo.isMachO) {
if (!cd && binInfo.isMachO) {
NSError *csError;
csInfo = [[MOLCodesignChecker alloc] initWithBinaryPath:binInfo.path
fileDescriptor:binInfo.fileHandle.fileDescriptor
error:&csError];

// Ignore codesigning if there are any errors with the signature.
if (csError) csInfo = nil;
}

// Actually make the decision (and refresh rule access timestamp).
SNTCachedDecision *cd = [self.policyProcessor decisionForFileInfo:binInfo
// If needed, actually make the decision (and refresh rule access timestamp).
if (!cd) {
cd = [self.policyProcessor decisionForFileInfo:binInfo
fileSHA256:nil
certificateSHA256:csInfo.leafCertificate.SHA256];
cd.certCommonName = csInfo.leafCertificate.commonName;
cd.certCommonName = csInfo.leafCertificate.commonName;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might be easier to follow if it were structured as

if (!cd) {
  // declare csInfo
  if (binInfo.isMachO) {
    // get csInfo
  }
  // get cd from policyProcessor
}

instead of having two separate checks for !cd

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


cd.vnodeId = message.vnode_id;

// Formulate an initial action from the decision.
Expand Down