Tweak event prioritization logic and defaults

This commit is contained in:
Tad Glines 2020-08-27 15:21:38 -07:00
Родитель 63bf359f99
Коммит 301bdcef86
9 изменённых файлов: 234 добавлений и 31 удалений

Просмотреть файл

@ -25,10 +25,14 @@
class Config {
public:
Config() = default;
explicit Config(std::unordered_map<std::string, std::string> map): _map(map) {}
explicit Config(std::unordered_map<std::string, std::string> map): _map(std::move(map)) {}
void Load(const std::string& path);
void SetString(const std::string& name, const std::string& value) {
_map[name] = value;
}
bool HasKey(const std::string& name) const;
bool GetBool(const std::string& name) const;
double GetDouble(const std::string& name) const;

Просмотреть файл

@ -18,6 +18,54 @@
#include "Logger.h"
#include "Translate.h"
#include "StringUtils.h"
template <typename T>
inline bool field_to_int(const EventRecordField& field, T& val, int base) {
errno = 0;
val = static_cast<T>(strtol(field.RawValuePtr(), nullptr, base));
return errno == 0;
}
template <typename T>
inline bool field_to_uint(const EventRecordField& field, T& val, int base) {
errno = 0;
val = static_cast<T>(strtoul(field.RawValuePtr(), nullptr, base));
return errno == 0;
}
void interpret_syscall_field(std::string& syscall_name, const EventRecord& record) {
static std::string_view SV_SYSCALL = "syscall";
static std::string_view SV_ARCH = "arch";
auto syscall_field = record.FieldByName(SV_SYSCALL);
if (!syscall_field) {
syscall_name = "unknown-syscall()";
return;
}
auto arch_field = record.FieldByName(SV_ARCH);
if (!arch_field) {
syscall_name = "unknown-syscall(" + std::string(syscall_field.RawValue()) + ")";
return;
}
uint32_t arch;
if (!field_to_uint(arch_field, arch, 16)) {
arch = 0;
}
auto mt = ArchToMachine(arch);
if (mt == MachineType::UNKNOWN) {
syscall_name = "unknown-syscall(" + std::string(syscall_field.RawValue()) + ")";
return;
}
int syscall;
if (field_to_int(syscall_field, syscall, 10)) {
SyscallToName(mt, syscall, syscall_name);
} else {
syscall_name = "unknown-syscall(" + std::string(syscall_field.RawValue()) + ")";
}
}
bool EventPrioritizer::LoadFromConfig(Config& config) {
@ -38,13 +86,35 @@ bool EventPrioritizer::LoadFromConfig(Config& config) {
auto rt_name = std::string(it->name.GetString(), it->name.GetStringLength());
auto rt = RecordNameToType(rt_name);
if (rt == RecordType::UNKNOWN) {
Logger::Warn("Invalid Record Type Name in 'event_priority_by_record_type' in config: %s", rt_name.c_str());
Logger::Warn("Invalid Record Type Name in 'event_priority_by_record_type' in config: %s",
rt_name.c_str());
return false;
}
_record_type_priorities.emplace(std::make_pair(rt, it->value.GetUint()));
}
}
if (config.HasKey("event_priority_by_record_type_category")) {
auto doc = config.GetJSON("event_priority_by_record_type_category");
if (!doc.IsObject()) {
return false;
}
for (auto it = doc.MemberBegin(); it != doc.MemberEnd(); ++it) {
if (!it->name.IsString() || !it->value.IsInt()) {
Logger::Warn("Invalid value in 'event_priority_by_record_type' in config");
return false;
}
auto rt_name = std::string(it->name.GetString(), it->name.GetStringLength());
auto rt = RecordTypeCategoryNameToCategory(rt_name);
if (rt == RecordTypeCategory::UNKNOWN) {
Logger::Warn("Invalid Record Type Category Name in 'event_priority_by_record_type_category' in config: %s",
rt_name.c_str());
return false;
}
_record_type_category_priorities.emplace(std::make_pair(rt, it->value.GetUint()));
}
}
if (config.HasKey("event_priority_by_syscall")) {
auto doc = config.GetJSON("event_priority_by_syscall");
if (!doc.IsObject()) {
@ -55,17 +125,8 @@ bool EventPrioritizer::LoadFromConfig(Config& config) {
Logger::Warn("Invalid value in 'event_priority_by_syscall' in config");
return false;
}
auto sc = std::string(it->name.GetString(), it->name.GetStringLength());
auto sc_num = SyscallNameToNumber(DetectMachine(), sc);
if (sc_num < 0) {
errno = 0;
sc_num = static_cast<int>(strtol(sc.c_str(), nullptr, 10));
if (errno != 0) {
Logger::Warn("Invalid Syscall in 'event_priority_by_syscall' in config: %s", sc.c_str());
return false;
}
}
_syscall_priorities.emplace(std::make_pair(sc_num, it->value.GetUint()));
auto sc_name = std::string(it->name.GetString(), it->name.GetStringLength());
_syscall_priorities.emplace(std::make_pair(sc_name, it->value.GetUint()));
}
}
@ -73,27 +134,34 @@ bool EventPrioritizer::LoadFromConfig(Config& config) {
}
uint16_t EventPrioritizer::Prioritize(const Event& event) {
static std::string_view SV_SYSCALL = "syscall";
static std::string S_STAR = "*";
auto rec1 = event.begin();
if (static_cast<RecordType>(rec1.RecordType()) == RecordType::SYSCALL) {
auto syscall_field = rec1.FieldByName(SV_SYSCALL);
if (syscall_field) {
errno = 0;
int syscall = static_cast<int>(strtol(syscall_field.RawValuePtr(), nullptr, 10));
if (errno == 0) {
auto itr = _syscall_priorities.find(syscall);
if (itr != _syscall_priorities.end()) {
return itr->second;
}
}
if (static_cast<RecordType>(rec1.RecordType()) == RecordType::AUOMS_EXECVE) {
} else if (static_cast<RecordType>(rec1.RecordType()) == RecordType::SYSCALL ||
static_cast<RecordType>(rec1.RecordType()) == RecordType::AUOMS_SYSCALL) {
_syscall_name.resize(0);
interpret_syscall_field(_syscall_name, rec1);
auto itr = _syscall_priorities.find(_syscall_name);
if (itr != _syscall_priorities.end()) {
return itr->second;
}
itr = _syscall_priorities.find(S_STAR);
if (itr != _syscall_priorities.end()) {
return itr->second;
}
} else {
auto itr = _record_type_priorities.find(static_cast<RecordType>(rec1.RecordType()));
if (itr != _record_type_priorities.end()) {
return itr->second;
}
auto rtc = RecordTypeToCategory(static_cast<RecordType>(rec1.RecordType()));
auto itr2 = _record_type_category_priorities.find(rtc);
if (itr2 != _record_type_category_priorities.end()) {
return itr2->second;
}
}
return _default_priority;

Просмотреть файл

@ -25,7 +25,7 @@
class EventPrioritizer: public IEventPrioritizer {
public:
EventPrioritizer(uint16_t default_priority): _default_priority(default_priority) {}
explicit EventPrioritizer(uint16_t default_priority): _default_priority(default_priority) {}
bool LoadFromConfig(Config& config);
@ -34,7 +34,9 @@ public:
private:
uint16_t _default_priority;
std::unordered_map<RecordType, uint16_t> _record_type_priorities;
std::unordered_map<int, uint16_t> _syscall_priorities;
std::unordered_map<RecordTypeCategory, uint16_t> _record_type_category_priorities;
std::unordered_map<std::string, uint16_t> _syscall_priorities;
std::string _syscall_name;
};

Просмотреть файл

@ -233,6 +233,8 @@ bool InterpretSockaddrField(std::string& out, const EventRecord& record, const E
}
bool InterpretField(std::string& out, const EventRecord& record, const EventRecordField& field, field_type_t field_type) {
static std::string_view SV_ARCH = "arch";
switch (field_type) {
case field_type_t::ARCH: {
uint32_t arch;
@ -249,9 +251,9 @@ bool InterpretField(std::string& out, const EventRecord& record, const EventReco
return true;
}
case field_type_t::SYSCALL: {
auto arch_field = record.FieldByName("arch");
auto arch_field = record.FieldByName(SV_ARCH);
if (!arch_field) {
out = "unknown-syscall(" + std::string() + ")";
out = "unknown-syscall(" + std::string(field.RawValue()) + ")";
return true;
}
uint32_t arch;

Просмотреть файл

@ -259,8 +259,65 @@ enum class RecordType: int {
AUOMS_EXECVE = 14688,
};
enum class RecordTypeCategory: int {
UNKNOWN = 0,
KERNEL = 1,
USER_MSG = 2,
DAEMON = 3,
EVENT = 4,
SELINUX = 5,
APPARMOR = 6,
KERN_CRYPTO_MSG = 7,
KERN_ANOM_MSG = 8,
INTEGRITY_MSG = 9,
ANOM_MSG = 10,
ANOM_RESP = 11,
USER_LSPP_MSG = 12,
CRYPTO_MSG = 13,
VIRT_MSG = 14,
USER_MSG2 = 15,
AUOMS_MSG = 16,
};
constexpr bool IsSingleRecordEvent(RecordType rtype) {
return rtype != RecordType::EOE && (rtype < RecordType::FIRST_EVENT || rtype >= RecordType::FIRST_ANOM_MSG || rtype == RecordType::KERNEL);
}
constexpr RecordTypeCategory RecordTypeToCategory(RecordType rtype) {
if (rtype < RecordType::FIRST_USER_MSG) {
return RecordTypeCategory::KERNEL;
} else if (rtype >= RecordType::FIRST_USER_MSG && rtype <= RecordType::LAST_USER_MSG) {
return RecordTypeCategory::USER_MSG;
} else if (rtype >= RecordType::FIRST_DAEMON && rtype <= RecordType::LAST_DAEMON) {
return RecordTypeCategory::DAEMON;
} else if (rtype >= RecordType::FIRST_EVENT && rtype <= RecordType::LAST_EVENT) {
return RecordTypeCategory::EVENT;
} else if (rtype >= RecordType::FIRST_SELINUX && rtype <= RecordType::LAST_SELINUX) {
return RecordTypeCategory::SELINUX;
} else if (rtype >= RecordType::FIRST_APPARMOR && rtype <= RecordType::LAST_APPARMOR) {
return RecordTypeCategory::APPARMOR;
} else if (rtype >= RecordType::FIRST_KERN_CRYPTO_MSG && rtype <= RecordType::LAST_KERN_CRYPTO_MSG) {
return RecordTypeCategory::KERN_CRYPTO_MSG;
} else if (rtype >= RecordType::FIRST_KERN_ANOM_MSG && rtype <= RecordType::LAST_KERN_ANOM_MSG) {
return RecordTypeCategory::KERN_ANOM_MSG;
} else if (rtype >= RecordType::INTEGRITY_FIRST_MSG && rtype <= RecordType::INTEGRITY_LAST_MSG) {
return RecordTypeCategory::INTEGRITY_MSG;
} else if (rtype >= RecordType::FIRST_ANOM_MSG && rtype <= RecordType::LAST_ANOM_MSG) {
return RecordTypeCategory::ANOM_MSG;
} else if (rtype >= RecordType::FIRST_ANOM_RESP && rtype <= RecordType::LAST_ANOM_RESP) {
return RecordTypeCategory::ANOM_RESP;
} else if (rtype >= RecordType::FIRST_USER_LSPP_MSG && rtype <= RecordType::LAST_USER_LSPP_MSG) {
return RecordTypeCategory::USER_LSPP_MSG;
} else if (rtype >= RecordType::FIRST_CRYPTO_MSG && rtype <= RecordType::LAST_CRYPTO_MSG) {
return RecordTypeCategory::CRYPTO_MSG;
} else if (rtype >= RecordType::FIRST_VIRT_MSG && rtype <= RecordType::LAST_VIRT_MSG) {
return RecordTypeCategory::VIRT_MSG;
} else if (rtype >= RecordType::FIRST_USER_MSG2 && rtype <= RecordType::LAST_USER_MSG2) {
return RecordTypeCategory::USER_MSG2;
} else if (rtype >= RecordType::FIRST_AUOMS_MSG && rtype <= RecordType::LAST_AUOMS_MSG) {
return RecordTypeCategory::AUOMS_MSG;
} else {
return RecordTypeCategory::UNKNOWN;
}
}
#endif //AUOMS_RECORDTYPE_H

Просмотреть файл

@ -39,6 +39,8 @@ int SyscallNameToNumber(MachineType mtype, const std::string_view& syscall_name)
std::string_view RecordTypeToName(RecordType code, std::string& unknown_str);
std::string RecordTypeToName(RecordType code);
RecordType RecordNameToType(const std::string_view& name);
std::string RecordTypeCategoryToName(RecordTypeCategory code);
RecordTypeCategory RecordTypeCategoryNameToCategory(const std::string_view& name);
field_type_t FieldNameToType(const std::string_view& name);
field_type_t FieldNameToType(RecordType rtype, const std::string_view& name, const std::string_view& val);

Просмотреть файл

@ -226,6 +226,26 @@ static StringTable<RecordType> s_record_type_table(RecordType ::UNKNOWN, {
{"AUOMS_EXECVE", RecordType::AUOMS_EXECVE},
});
static StringTable<RecordTypeCategory> s_record_type_category_table(RecordTypeCategory::UNKNOWN, {
{"UNKNOWN", RecordTypeCategory::UNKNOWN},
{"KERNEL", RecordTypeCategory::KERNEL},
{"USER_MSG", RecordTypeCategory::USER_MSG},
{"DAEMON", RecordTypeCategory::DAEMON},
{"EVENT", RecordTypeCategory::EVENT},
{"SELINUX", RecordTypeCategory::SELINUX},
{"APPARMOR", RecordTypeCategory::APPARMOR},
{"KERN_CRYPTO_MSG", RecordTypeCategory::KERN_CRYPTO_MSG},
{"KERN_ANOM_MSG", RecordTypeCategory::KERN_ANOM_MSG},
{"INTEGRITY_MSG", RecordTypeCategory::INTEGRITY_MSG},
{"ANOM_MSG", RecordTypeCategory::ANOM_MSG},
{"ANOM_RESP", RecordTypeCategory::ANOM_RESP},
{"USER_LSPP_MSG", RecordTypeCategory::USER_LSPP_MSG},
{"CRYPTO_MSG", RecordTypeCategory::CRYPTO_MSG},
{"VIRT_MSG", RecordTypeCategory::VIRT_MSG},
{"USER_MSG2", RecordTypeCategory::USER_MSG2},
{"AUOMS_MSG", RecordTypeCategory::AUOMS_MSG},
});
std::string_view RecordTypeToName(RecordType code, std::string& unknown_str) {
auto str = s_record_type_table.ToString(code);
if (str.empty()) {
@ -263,3 +283,15 @@ RecordType RecordNameToType(const std::string_view& name) {
return s_record_type_table.ToInt(name);
}
}
std::string RecordTypeCategoryToName(RecordTypeCategory code) {
std::string str(s_record_type_category_table.ToString(code));
if (str.empty()) {
str = "UNKNOWN";
}
return str;
}
RecordTypeCategory RecordTypeCategoryNameToCategory(const std::string_view& name) {
return s_record_type_category_table.ToInt(name);
}

Просмотреть файл

@ -274,7 +274,27 @@ int main(int argc, char**argv) {
Logger::OpenSyslog("auoms", LOG_DAEMON);
}
auto event_prioritizer = std::make_shared<EventPrioritizer>(num_priorities-1);
if (!config.HasKey("event_priority_by_syscall")) {
config.SetString("event_priority_by_syscall", R"json({"execve":2,"execveat":2,"*":3})json");
}
if (!config.HasKey("event_priority_by_record_type")) {
config.SetString("event_priority_by_record_type", R"json({"AUOMS_EXECVE":2,"AUOMS_SYSCALL":3,"AUOMS_PROCESS_INVENTORY":1})json");
}
if (!config.HasKey("event_priority_by_record_type_category")) {
config.SetString("event_priority_by_record_type_category", R"json({"AUOMS_MSG":0, "USER_MSG":1,"SELINUX":1,"APPARMOR":1})json");
}
int default_priority = 4;
if (config.HasKey("default_event_priority")) {
default_priority = static_cast<uint16_t>(config.GetUint64("default_event_priority"));
}
if (default_priority > num_priorities-1) {
default_priority = num_priorities-1;
}
auto event_prioritizer = std::make_shared<EventPrioritizer>(default_priority);
if (!event_prioritizer->LoadFromConfig(config)) {
Logger::Error("Failed to load EventPrioritizer config, exiting");
exit(1);

Просмотреть файл

@ -457,7 +457,23 @@ int main(int argc, char**argv) {
Logger::OpenSyslog("auomscollect", LOG_DAEMON);
}
auto event_prioritizer = std::make_shared<EventPrioritizer>(num_priorities-1);
if (!config.HasKey("event_priority_by_syscall")) {
config.SetString("event_priority_by_syscall", R"json({"execve":2,"execveat":2,"*":3})json");
}
if (!config.HasKey("event_priority_by_record_type_category")) {
config.SetString("event_priority_by_record_type_category", R"json({"AUOMS_MSG":0, "USER_MSG":1,"SELINUX":1,"APPARMOR":1})json");
}
int default_priority = 4;
if (config.HasKey("default_event_priority")) {
default_priority = static_cast<uint16_t>(config.GetUint64("default_event_priority"));
}
if (default_priority > num_priorities-1) {
default_priority = num_priorities-1;
}
auto event_prioritizer = std::make_shared<EventPrioritizer>(default_priority);
if (!event_prioritizer->LoadFromConfig(config)) {
Logger::Error("Failed to load EventPrioritizer config, exiting");
exit(1);