mirror of
https://github.com/google/santa.git
synced 2026-04-24 03:00:12 -04:00
Adopt new ES APIs to watch target paths in tamper client (#984)
This commit is contained in:
@@ -295,6 +295,7 @@ objc_library(
|
||||
":Metrics",
|
||||
":SNTEndpointSecurityClient",
|
||||
":SNTEndpointSecurityEventHandler",
|
||||
":WatchItemPolicy",
|
||||
"//Source/common:SNTLogging",
|
||||
],
|
||||
)
|
||||
@@ -1185,6 +1186,7 @@ santa_unit_test(
|
||||
":Metrics",
|
||||
":MockEndpointSecurityAPI",
|
||||
":SNTEndpointSecurityTamperResistance",
|
||||
":WatchItemPolicy",
|
||||
"//Source/common:SNTLogging",
|
||||
"//Source/common:TestUtils",
|
||||
"@OCMock",
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/qos.h>
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "Source/common/BranchPrediction.h"
|
||||
#import "Source/common/SNTConfigurator.h"
|
||||
#import "Source/common/SNTLogging.h"
|
||||
@@ -40,6 +44,9 @@ using santa::santad::event_providers::endpoint_security::EndpointSecurityAPI;
|
||||
using santa::santad::event_providers::endpoint_security::EnrichedMessage;
|
||||
using santa::santad::event_providers::endpoint_security::Message;
|
||||
|
||||
constexpr std::string_view kProtectedFiles[] = {"/private/var/db/santa/rules.db",
|
||||
"/private/var/db/santa/events.db"};
|
||||
|
||||
@interface SNTEndpointSecurityClient ()
|
||||
@property int64_t deadlineMarginMS;
|
||||
@end
|
||||
@@ -296,12 +303,28 @@ using santa::santad::event_providers::endpoint_security::Message;
|
||||
});
|
||||
}
|
||||
|
||||
+ (bool)isDatabasePath:(const std::string_view)path {
|
||||
+ (std::set<std::string>)getProtectedPaths {
|
||||
std::set<std::string> protectedPathsCopy;
|
||||
|
||||
for (size_t i = 0; i < sizeof(kProtectedFiles) / sizeof(kProtectedFiles[0]); i++) {
|
||||
protectedPathsCopy.insert(std::string(kProtectedFiles[i]));
|
||||
}
|
||||
|
||||
return protectedPathsCopy;
|
||||
}
|
||||
|
||||
+ (bool)isProtectedPath:(const std::string_view)path {
|
||||
// TODO(mlw): These values should come from `SNTDatabaseController`. But right
|
||||
// now they live as NSStrings. We should make them `std::string_view` types
|
||||
// in order to use them here efficiently, but will need to make the
|
||||
// `SNTDatabaseController` an ObjC++ file.
|
||||
return (path == "/private/var/db/santa/rules.db" || path == "/private/var/db/santa/events.db");
|
||||
for (size_t i = 0; i < sizeof(kProtectedFiles) / sizeof(kProtectedFiles[0]); i++) {
|
||||
if (path == kProtectedFiles[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -86,7 +86,8 @@
|
||||
|
||||
- (bool)clearCache;
|
||||
|
||||
+ (bool)isDatabasePath:(const std::string_view)path;
|
||||
+ (std::set<std::string>)getProtectedPaths;
|
||||
+ (bool)isProtectedPath:(const std::string_view)path;
|
||||
+ (bool)populateAuditTokenSelf:(audit_token_t *)tok;
|
||||
|
||||
@end
|
||||
|
||||
@@ -413,11 +413,11 @@ using santa::santad::event_providers::endpoint_security::Message;
|
||||
XCTBubbleMockVerifyAndClearExpectations(mockESApi.get());
|
||||
}
|
||||
|
||||
- (void)testIsDatabasePath {
|
||||
XCTAssertTrue([SNTEndpointSecurityClient isDatabasePath:"/private/var/db/santa/rules.db"]);
|
||||
XCTAssertTrue([SNTEndpointSecurityClient isDatabasePath:"/private/var/db/santa/events.db"]);
|
||||
- (void)testIsProtectedPath {
|
||||
XCTAssertTrue([SNTEndpointSecurityClient isProtectedPath:"/private/var/db/santa/rules.db"]);
|
||||
XCTAssertTrue([SNTEndpointSecurityClient isProtectedPath:"/private/var/db/santa/events.db"]);
|
||||
|
||||
XCTAssertFalse([SNTEndpointSecurityClient isDatabasePath:"/not/a/db/path"]);
|
||||
XCTAssertFalse([SNTEndpointSecurityClient isProtectedPath:"/not/a/db/path"]);
|
||||
}
|
||||
|
||||
- (void)testProcessMessageHandlerBadEventType {
|
||||
|
||||
@@ -18,10 +18,12 @@
|
||||
#include <string.h>
|
||||
|
||||
#import "Source/common/SNTLogging.h"
|
||||
#include "Source/santad/DataLayer/WatchItemPolicy.h"
|
||||
#include "Source/santad/EventProviders/EndpointSecurity/Message.h"
|
||||
#include "Source/santad/Metrics.h"
|
||||
|
||||
using santa::santad::EventDisposition;
|
||||
using santa::santad::data_layer::WatchItemPathType;
|
||||
using santa::santad::event_providers::endpoint_security::EndpointSecurityAPI;
|
||||
using santa::santad::event_providers::endpoint_security::Message;
|
||||
using santa::santad::logs::endpoint_security::Logger;
|
||||
@@ -56,7 +58,7 @@ static constexpr std::string_view kSantaKextIdentifier = "com.google.santa-drive
|
||||
switch (esMsg->event_type) {
|
||||
case ES_EVENT_TYPE_AUTH_UNLINK: {
|
||||
if ([SNTEndpointSecurityTamperResistance
|
||||
isDatabasePath:esMsg->event.unlink.target->path.data]) {
|
||||
isProtectedPath:esMsg->event.unlink.target->path.data]) {
|
||||
result = ES_AUTH_RESULT_DENY;
|
||||
LOGW(@"Preventing attempt to delete Santa databases!");
|
||||
}
|
||||
@@ -65,7 +67,7 @@ static constexpr std::string_view kSantaKextIdentifier = "com.google.santa-drive
|
||||
|
||||
case ES_EVENT_TYPE_AUTH_RENAME: {
|
||||
if ([SNTEndpointSecurityTamperResistance
|
||||
isDatabasePath:esMsg->event.rename.source->path.data]) {
|
||||
isProtectedPath:esMsg->event.rename.source->path.data]) {
|
||||
result = ES_AUTH_RESULT_DENY;
|
||||
LOGW(@"Preventing attempt to rename Santa databases!");
|
||||
break;
|
||||
@@ -73,7 +75,7 @@ static constexpr std::string_view kSantaKextIdentifier = "com.google.santa-drive
|
||||
|
||||
if (esMsg->event.rename.destination_type == ES_DESTINATION_TYPE_EXISTING_FILE) {
|
||||
if ([SNTEndpointSecurityTamperResistance
|
||||
isDatabasePath:esMsg->event.rename.destination.existing_file->path.data]) {
|
||||
isProtectedPath:esMsg->event.rename.destination.existing_file->path.data]) {
|
||||
result = ES_AUTH_RESULT_DENY;
|
||||
LOGW(@"Preventing attempt to overwrite Santa databases!");
|
||||
break;
|
||||
@@ -108,9 +110,20 @@ static constexpr std::string_view kSantaKextIdentifier = "com.google.santa-drive
|
||||
}
|
||||
|
||||
- (void)enable {
|
||||
// TODO(mlw): For macOS 13, use new mute and invert APIs to limit the
|
||||
// messages sent for these events to the Santa-specific directories
|
||||
// checked in the `handleMessage:` method.
|
||||
[super enableTargetPathWatching];
|
||||
[super unmuteEverything];
|
||||
|
||||
// Get the set of protected paths
|
||||
std::set<std::string> protectedPaths = [SNTEndpointSecurityTamperResistance getProtectedPaths];
|
||||
|
||||
// Iterate the set, and create a vector of literals to mute
|
||||
std::vector<std::pair<std::string, WatchItemPathType>> watchPaths;
|
||||
for (const auto &path : protectedPaths) {
|
||||
watchPaths.push_back({path, WatchItemPathType::kLiteral});
|
||||
}
|
||||
|
||||
// Begin watching the protected set
|
||||
[super muteTargetPaths:watchPaths];
|
||||
|
||||
[super subscribeAndClearCache:{
|
||||
ES_EVENT_TYPE_AUTH_KEXTLOAD,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <set>
|
||||
|
||||
#include "Source/common/TestUtils.h"
|
||||
#include "Source/santad/DataLayer/WatchItemPolicy.h"
|
||||
#include "Source/santad/EventProviders/EndpointSecurity/Client.h"
|
||||
#include "Source/santad/EventProviders/EndpointSecurity/Message.h"
|
||||
#include "Source/santad/EventProviders/EndpointSecurity/MockEndpointSecurityAPI.h"
|
||||
@@ -31,6 +32,7 @@
|
||||
#import "Source/santad/Metrics.h"
|
||||
|
||||
using santa::santad::EventDisposition;
|
||||
using santa::santad::data_layer::WatchItemPathType;
|
||||
using santa::santad::event_providers::endpoint_security::Client;
|
||||
using santa::santad::event_providers::endpoint_security::Message;
|
||||
|
||||
@@ -61,6 +63,15 @@ static constexpr std::string_view kSantaKextIdentifier = "com.google.santa-drive
|
||||
.WillOnce(testing::Return(true)))
|
||||
.WillOnce(testing::Return(true));
|
||||
|
||||
// Setup mocks to handle inverting target path muting
|
||||
EXPECT_CALL(*mockESApi, InvertTargetPathMuting).WillOnce(testing::Return(true));
|
||||
EXPECT_CALL(*mockESApi, UnmuteAllPaths).WillOnce(testing::Return(true));
|
||||
EXPECT_CALL(*mockESApi, UnmuteAllTargetPaths).WillOnce(testing::Return(true));
|
||||
|
||||
// Setup mocks to handle muting the rules db and events db
|
||||
EXPECT_CALL(*mockESApi, MuteTargetPath(testing::_, testing::_, WatchItemPathType::kLiteral))
|
||||
.WillRepeatedly(testing::Return(true));
|
||||
|
||||
SNTEndpointSecurityTamperResistance *tamperClient =
|
||||
[[SNTEndpointSecurityTamperResistance alloc] initWithESAPI:mockESApi
|
||||
metrics:nullptr
|
||||
|
||||
Reference in New Issue
Block a user