Tweak event prioritization logic and defaults
This commit is contained in:
Родитель
63bf359f99
Коммит
301bdcef86
6
Config.h
6
Config.h
|
@ -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 (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;
|
||||
|
|
57
RecordType.h
57
RecordType.h
|
@ -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);
|
||||
}
|
||||
|
|
22
auoms.cpp
22
auoms.cpp
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче