From 569eb0a0ba77a1cb498e703b364e7929056f51d3 Mon Sep 17 00:00:00 2001 From: Melissa Kilby Date: Fri, 2 Aug 2024 00:16:53 +0000 Subject: [PATCH] update(anomalydetection): add some custom behavior profile short-cut fields options Signed-off-by: Melissa Kilby --- plugins/anomalydetection/src/plugin.cpp | 152 ++++++++++++++++++ .../src/plugin_sinsp_filterchecks.h | 5 + plugins/anomalydetection/src/plugin_utils.cpp | 27 +++- .../test/include/test_helpers.h | 6 +- .../anomalydetection/test/src/num/cms.ut.cpp | 12 +- 5 files changed, 192 insertions(+), 10 deletions(-) diff --git a/plugins/anomalydetection/src/plugin.cpp b/plugins/anomalydetection/src/plugin.cpp index a243d993..50c1a4a1 100644 --- a/plugins/anomalydetection/src/plugin.cpp +++ b/plugins/anomalydetection/src/plugin.cpp @@ -1284,6 +1284,158 @@ bool anomalydetection::extract_filterchecks_concat_profile(const falcosecurity:: } break; } + + // + // Custom behavior profile short-cut fields + // + + case plugin_sinsp_filterchecks::TYPE_CUSTOM_ANAME_LINEAGE_CONCAT: + { + if(field.argid < 1) + { + break; + } + m_comm.read_value(tr, thread_entry, tstr); + m_ptid.read_value(tr, thread_entry, ptid); + std::string tstr2; + for(uint32_t j = 0; j < field.argid; j++) + { + try + { + auto lineage = m_thread_table.get_entry(tr, ptid); + m_comm.read_value(tr, lineage, tstr2); + tstr += tstr2; + tstr2.clear(); + if(j == (field.argid - 1)) + { + break; + } + if(ptid == 1) + { + break; + } + m_ptid.read_value(tr, lineage, ptid); + } + catch(const std::exception& e) + { + } + } + break; + } + case plugin_sinsp_filterchecks::TYPE_CUSTOM_AEXE_LINEAGE_CONCAT: + { + if(field.argid < 1) + { + break; + } + m_exe.read_value(tr, thread_entry, tstr); + m_ptid.read_value(tr, thread_entry, ptid); + std::string tstr2; + for(uint32_t j = 0; j < field.argid; j++) + { + try + { + auto lineage = m_thread_table.get_entry(tr, ptid); + m_exe.read_value(tr, lineage, tstr2); + tstr += tstr2; + tstr2.clear(); + if(j == (field.argid - 1)) + { + break; + } + if(ptid == 1) + { + break; + } + m_ptid.read_value(tr, lineage, ptid); + } + catch(const std::exception& e) + { + } + } + break; + } + case plugin_sinsp_filterchecks::TYPE_CUSTOM_AEXEPATH_LINEAGE_CONCAT: + { + if(field.argid < 1) + { + break; + } + m_exepath.read_value(tr, thread_entry, tstr); + m_ptid.read_value(tr, thread_entry, ptid); + std::string tstr2; + for(uint32_t j = 0; j < field.argid; j++) + { + try + { + auto lineage = m_thread_table.get_entry(tr, ptid); + m_exepath.read_value(tr, lineage, tstr2); + tstr += tstr2; + tstr2.clear(); + if(j == (field.argid - 1)) + { + break; + } + if(ptid == 1) + { + break; + } + m_ptid.read_value(tr, lineage, ptid); + } + catch(const std::exception& e) + { + } + } + break; + } + case plugin_sinsp_filterchecks::TYPE_CUSTOM_FDNAME_PART1: + case plugin_sinsp_filterchecks::TYPE_CUSTOM_FDNAME_PART2: + { + switch(evt.get_type()) + { + case PPME_SYSCALL_OPEN_X: + case PPME_SYSCALL_CREAT_X: + case PPME_SYSCALL_OPENAT_2_X: + case PPME_SYSCALL_OPENAT2_X: + case PPME_SYSCALL_OPEN_BY_HANDLE_AT_X: + { + break; + } + case PPME_SOCKET_ACCEPT_5_X: + case PPME_SOCKET_ACCEPT4_6_X: + case PPME_SOCKET_CONNECT_X: + { + auto fd_table = m_thread_table.get_subtable( + tr, m_fds, thread_entry, + st::SS_PLUGIN_ST_INT64); + m_lastevent_fd_field.read_value(tr, thread_entry, tint64); + auto fd_entry = fd_table.get_entry(tr, tint64); + m_fd_name_value.read_value(tr, fd_entry, tstr); + std::string delimiter = "->"; + size_t pos = tstr.find(delimiter); + if (pos != std::string::npos) + { + if (field.id == plugin_sinsp_filterchecks::TYPE_CUSTOM_FDNAME_PART1) + { + tstr = tstr.substr(0, pos); + + } else + { + tstr = tstr.substr(pos + delimiter.length()); + } + } else + { + tstr.clear(); + } + break; + } + default: + // Clear the entire profile when invoking the fd related profile for non fd syscalls + behavior_profile_concat_str.clear(); + } + break; + } + default: break; } diff --git a/plugins/anomalydetection/src/plugin_sinsp_filterchecks.h b/plugins/anomalydetection/src/plugin_sinsp_filterchecks.h index e221b6b1..ca5610f6 100644 --- a/plugins/anomalydetection/src/plugin_sinsp_filterchecks.h +++ b/plugins/anomalydetection/src/plugin_sinsp_filterchecks.h @@ -178,6 +178,11 @@ enum check_type TYPE_FSPATH_SOURCERAW, TYPE_FSPATH_TARGET, TYPE_FSPATH_TARGETRAW, + TYPE_CUSTOM_ANAME_LINEAGE_CONCAT, + TYPE_CUSTOM_AEXE_LINEAGE_CONCAT, + TYPE_CUSTOM_AEXEPATH_LINEAGE_CONCAT, + TYPE_CUSTOM_FDNAME_PART1, + TYPE_CUSTOM_FDNAME_PART2, }; } diff --git a/plugins/anomalydetection/src/plugin_utils.cpp b/plugins/anomalydetection/src/plugin_utils.cpp index b7c832eb..fc0c8b5d 100644 --- a/plugins/anomalydetection/src/plugin_utils.cpp +++ b/plugins/anomalydetection/src/plugin_utils.cpp @@ -173,6 +173,11 @@ static const filtercheck_field_info sinsp_filter_check_fields[] = {PT_CHARBUF, EPF_NONE, PF_NA, "fs.path.sourceraw", "Source path for Filesystem-related operation", "For any event type that deals with a filesystem path, and specifically for a source and target like mv, cp, etc, the source path the file syscall is operating on. This path is always the path provided to the syscall and may not be fully resolved."}, {PT_CHARBUF, EPF_NONE, PF_NA, "fs.path.target", "Target path for Filesystem-related operation", "For any event type that deals with a filesystem path, and specifically for a target and target like mv, cp, etc, the target path the file syscall is operating on. This path is always fully resolved, prepending the thread cwd when needed."}, {PT_CHARBUF, EPF_NONE, PF_NA, "fs.path.targetraw", "Target path for Filesystem-related operation", "For any event type that deals with a filesystem path, and specifically for a target and target like mv, cp, etc, the target path the file syscall is operating on. This path is always the path provided to the syscall and may not be fully resolved."}, + {PT_CHARBUF, EPF_ANOMALY_PLUGIN | EPF_ARG_REQUIRED, PF_NA, "custom.proc.aname.lineage.join", "Custom concat lineage", "[Incubating] String concatenate the process lineage to achieve better performance. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future."}, + {PT_CHARBUF, EPF_ANOMALY_PLUGIN | EPF_ARG_REQUIRED, PF_NA, "custom.proc.aexe.lineage.join", "Custom concat lineage", "[Incubating] String concatenate the process lineage to achieve better performance. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future."}, + {PT_CHARBUF, EPF_ANOMALY_PLUGIN | EPF_ARG_REQUIRED, PF_NA, "custom.proc.aexepath.lineage.join", "Custom concat lineage", "[Incubating] String concatenate the process lineage to achieve better performance. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future."}, + {PT_CHARBUF, EPF_ANOMALY_PLUGIN | EPF_NONE, PF_NA, "custom.fd.name.part1", "Custom fd 'ip:port' part1", "[Incubating] For fd related network events only. Part 1 as string of the ip tuple in the format 'ip:port', e.g '172.40.111.222:54321' given fd.name '172.40.111.222:54321->142.251.111.147:443'. It may be dperecated in the future."}, + {PT_CHARBUF, EPF_ANOMALY_PLUGIN | EPF_NONE, PF_NA, "custom.fd.name.part2", "Custom fd 'ip:port' part1", "[Incubating] For fd related network events only. Part 2 as string of the ip tuple in the format 'ip:port', e.g.'142.251.111.147:443' given fd.name '172.40.111.222:54321->142.251.111.147:443'. This is a custom plugin specific field for the anomaly behavior profiles only. It may be dperecated in the future."}, }; // Temporary workaround; not as robust as libsinsp/eventformatter; @@ -196,8 +201,10 @@ const std::vector get_profile_fields(const std: while (iter != end) { + // todo revisit this helper auto rawfield = iter->str().substr(1); std::string fieldname = rawfield; + bool found_match = false; for (size_t i = 0; i < sizeof(sinsp_filter_check_fields) / sizeof(sinsp_filter_check_fields[0]); ++i) { id = static_cast(i); @@ -206,7 +213,11 @@ const std::vector get_profile_fields(const std: id == plugin_sinsp_filterchecks::TYPE_ANAME || id == plugin_sinsp_filterchecks::TYPE_AEXE || id == plugin_sinsp_filterchecks::TYPE_AEXEPATH || - id == plugin_sinsp_filterchecks::TYPE_ACMDLINE) + id == plugin_sinsp_filterchecks::TYPE_ACMDLINE || + id == plugin_sinsp_filterchecks::TYPE_CUSTOM_ANAME_LINEAGE_CONCAT|| + id == plugin_sinsp_filterchecks::TYPE_CUSTOM_AEXE_LINEAGE_CONCAT || + id == plugin_sinsp_filterchecks::TYPE_CUSTOM_AEXEPATH_LINEAGE_CONCAT + ) { size_t start_pos = rawfield.find('['); size_t end_pos = rawfield.find(']'); @@ -227,8 +238,17 @@ const std::vector get_profile_fields(const std: } if (std::string(sinsp_filter_check_fields[i].m_name) == fieldname) { + found_match = true; if ((sinsp_filter_check_fields[i].m_flags & EPF_ANOMALY_PLUGIN)) { + if ((id == plugin_sinsp_filterchecks::TYPE_CUSTOM_ANAME_LINEAGE_CONCAT|| + id == plugin_sinsp_filterchecks::TYPE_CUSTOM_AEXE_LINEAGE_CONCAT || + id == plugin_sinsp_filterchecks::TYPE_CUSTOM_AEXEPATH_LINEAGE_CONCAT) + && argid == 0) + { + plugin_anomalydetection::utils::log_error("Usage of behavior profile field: '" + fieldname + "' requires an argument greater than 0 indicating the level of parent lineage traversal, e.g. '%custom.proc.aname.lineage.join[7]' or '%custom.proc.aexe.lineage.join[7]' or '%custom.proc.aexepath.lineage.join[7]' exiting..."); + exit(1); + } fields.emplace_back(plugin_sinsp_filterchecks_field{ id, argid, @@ -243,6 +263,11 @@ const std::vector get_profile_fields(const std: argid = 0; argname.clear(); } + if (!found_match) + { + plugin_anomalydetection::utils::log_error("Remove the following invalid or mistyped behavior profile field: '" + fieldname + "' exiting..."); + exit(1); + } ++iter; } return fields; diff --git a/plugins/anomalydetection/test/include/test_helpers.h b/plugins/anomalydetection/test/include/test_helpers.h index 4a2b931e..c23234bb 100644 --- a/plugins/anomalydetection/test/include/test_helpers.h +++ b/plugins/anomalydetection/test/include/test_helpers.h @@ -16,11 +16,11 @@ limitations under the License. */ #define INIT_CONFIG "{\"count_min_sketch\":{\"enabled\":true,\"n_sketches\":3,\"gamma_eps\":[[0.001,0.0001],[0.001,0.0001],[0.001,0.0001]],\"behavior_profiles\":[\ -{\"fields\":\"%container.id %proc.is_vpgid_leader %proc.is_sid_leader %proc.exe_ino %proc.exe_ino.ctime %proc.exe_ino.mtime %proc.is_exe_writable %proc.is_exe_upper_layer %proc.is_exe_from_memfd %proc.cmdnargs %proc.cmdlenargs %proc.env[HOME] %proc.exeline %proc.name %proc.pname %proc.exepath %proc.pexepath %proc.tty %proc.vpid %proc.pvid]\",\ +{\"fields\":\"%container.id %proc.is_vpgid_leader %proc.is_sid_leader %proc.exe_ino %proc.exe_ino.ctime %proc.exe_ino.mtime %proc.is_exe_writable %proc.is_exe_upper_layer %proc.is_exe_from_memfd %proc.cmdnargs %proc.cmdlenargs %proc.env[HOME] %proc.exeline %proc.name %proc.pname %proc.exepath %proc.pexepath %proc.tty %proc.vpid %proc.pvpid\",\ \"event_codes\":[293,331]},\ -{\"fields\":\"%proc.pid %fd.num %fd.name %fd.directory %fd.filename %fd.dev %fd.ino %fd.nameraw\",\ +{\"fields\":\"%proc.pid %custom.fd.name.part1 %custom.fd.name.part2 %fd.num %fd.name %fd.directory %fd.filename %fd.dev %fd.ino %fd.nameraw\",\ \"event_codes\":[3,307,327,23]},\ -{\"fields\":\"%container.id %proc.cmdline %proc.acmdline %proc.pcmdline %proc.acmdline[1] %proc.name %proc.aname[0] %proc.aname[1] %proc.aname[2] %proc.aname[3] %proc.aname[4] %proc.aname[5] %proc.aname[6] %proc.aname[7] %proc.pid %proc.apid[0] %proc.apid[1] %proc.apid[2] %proc.apid[3] %proc.apid[4] %proc.apid[5] %proc.apid[6] %proc.apid[7] %proc.exepath %proc.aexepath[0] %proc.aexepath[1] %proc.aexepath[2] %proc.aexepath[3] %proc.aexepath[4] %proc.aexepath[5] %proc.aexepath[6] %proc.aexepath[7] %proc.vpgid %proc.vpgid.name %proc.vpgid.exe %proc.vpgid.exepath %proc.sid %proc.sname %proc.sid.exe %proc.sid.exepath\",\ +{\"fields\":\"%container.id %custom.proc.aname.lineage.join[7] %custom.proc.aexe.lineage.join[7] %custom.proc.aexepath.lineage.join[7] %proc.cmdline %proc.acmdline %proc.pcmdline %proc.acmdline[1] %proc.name %proc.aname[0] %proc.aname[1] %proc.aname[2] %proc.aname[3] %proc.aname[4] %proc.aname[5] %proc.aname[6] %proc.aname[7] %proc.pid %proc.apid[0] %proc.apid[1] %proc.apid[2] %proc.apid[3] %proc.apid[4] %proc.apid[5] %proc.apid[6] %proc.apid[7] %proc.exepath %proc.aexepath[0] %proc.aexepath[1] %proc.aexepath[2] %proc.aexepath[3] %proc.aexepath[4] %proc.aexepath[5] %proc.aexepath[6] %proc.aexepath[7] %proc.vpgid %proc.vpgid.name %proc.vpgid.exe %proc.vpgid.exepath %proc.sid %proc.sname %proc.sid.exe %proc.sid.exepath\",\ \"event_codes\":[293,331]}]}}" #define ASSERT_PLUGIN_INITIALIZATION(p_o, p_l) \ diff --git a/plugins/anomalydetection/test/src/num/cms.ut.cpp b/plugins/anomalydetection/test/src/num/cms.ut.cpp index 18aeaab1..30eb6e3c 100644 --- a/plugins/anomalydetection/test/src/num/cms.ut.cpp +++ b/plugins/anomalydetection/test/src/num/cms.ut.cpp @@ -103,10 +103,10 @@ TEST_F(sinsp_with_test_input, plugin_anomalydetection_filterchecks_fields) ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch[2]", pl_flist), "1"); ASSERT_TRUE(field_exists(evt, "anomaly.count_min_sketch.profile", pl_flist)); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile", pl_flist), "1024204816762626980000045881676262698000004577110229/home/user/bin/test-exe -c 'echo aGVsbG8K | base64 -d'test-exeinit/bin/test-exe/sbin/init3481820"); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[0]", pl_flist), "1024204816762626980000045881676262698000004577110229/home/user/bin/test-exe -c 'echo aGVsbG8K | base64 -d'test-exeinit/bin/test-exe/sbin/init3481820"); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile", pl_flist), "1024204816762626980000045881676262698000004577110229/home/user/bin/test-exe -c 'echo aGVsbG8K | base64 -d'test-exeinit/bin/test-exe/sbin/init34818201"); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[0]", pl_flist), "1024204816762626980000045881676262698000004577110229/home/user/bin/test-exe -c 'echo aGVsbG8K | base64 -d'test-exeinit/bin/test-exe/sbin/init34818201"); ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[1]", pl_flist), ""); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[2]", pl_flist), "test-exe -c 'echo aGVsbG8K | base64 -d'test-exe -c 'echo aGVsbG8K | base64 -d'initinittest-exetest-exeinit20201/bin/test-exe/bin/test-exe/sbin/init20test-exe/bin/test-exe/bin/test-exe0init/sbin/init/sbin/init"); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[2]", pl_flist), "test-exeinit/bin/test-exe/sbin/init/bin/test-exe/sbin/inittest-exe -c 'echo aGVsbG8K | base64 -d'test-exe -c 'echo aGVsbG8K | base64 -d'initinittest-exetest-exeinit20201/bin/test-exe/bin/test-exe/sbin/init20test-exe/bin/test-exe/bin/test-exe0init/sbin/init/sbin/init"); } TEST_F(sinsp_with_test_input, plugin_anomalydetection_filterchecks_fields_proc_lineage) @@ -133,7 +133,7 @@ TEST_F(sinsp_with_test_input, plugin_anomalydetection_filterchecks_fields_proc_l add_event_advance_ts(increasing_ts(), p6_t1_tid, PPME_SYSCALL_EXECVE_19_E, 1, "/usr/bin/p6_t1_exepath"); auto evt = add_event_advance_ts(increasing_ts(), p6_t1_tid, PPME_SYSCALL_EXECVE_19_X, 27, (int64_t)0, "/usr/bin/p6_t1_exepath", scap_const_sized_buffer{argsv.data(), argsv.size()}, p6_t1_tid, p6_t1_tid, p6_t1_ptid, "", not_relevant_64, not_relevant_64, not_relevant_64, (uint32_t)29612, (uint32_t)4, (uint32_t)0, "p6_t1_comm", empty_bytebuf, empty_bytebuf, (int32_t)34818, pgid, loginuid, (int32_t) PPM_EXE_WRITABLE, not_relevant_64, not_relevant_64, not_relevant_64, not_relevant_64, not_relevant_64, not_relevant_64, euid); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[2]", pl_flist), "p6_t1_comm -c cat testp6_t1_comm -c cat testp5_t1_comm -c cat testp5_t1_comm -c cat testp6_t1_commp6_t1_commp5_t1_commp4_t1_commp3_t1_commp2_t1_comminit8787827672251/usr/bin/p6_t1_exepath/usr/bin/p6_t1_exepath/usr/bin/p5_t1_exepath/usr/bin/p4_t1_exepath/usr/bin/p3_t1_exepath/usr/bin/p2_t1_exepath/sbin/init9999p5_t1_comm/usr/bin/p5_t1_exepath/usr/bin/p5_t1_exepath0init/sbin/init/sbin/init"); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[2]", pl_flist), "p6_t1_commp5_t1_commp4_t1_commp3_t1_commp2_t1_comminit/usr/bin/p6_t1_exepath/usr/bin/p5_t1_exepath/p4_t1_exepath/p3_t1_exepath/p2_t1_exepath/sbin/init/usr/bin/p6_t1_exepath/usr/bin/p5_t1_exepath/usr/bin/p4_t1_exepath/usr/bin/p3_t1_exepath/usr/bin/p2_t1_exepath/sbin/initp6_t1_comm -c cat testp6_t1_comm -c cat testp5_t1_comm -c cat testp5_t1_comm -c cat testp6_t1_commp6_t1_commp5_t1_commp4_t1_commp3_t1_commp2_t1_comminit8787827672251/usr/bin/p6_t1_exepath/usr/bin/p6_t1_exepath/usr/bin/p5_t1_exepath/usr/bin/p4_t1_exepath/usr/bin/p3_t1_exepath/usr/bin/p2_t1_exepath/sbin/init9999p5_t1_comm/usr/bin/p5_t1_exepath/usr/bin/p5_t1_exepath0init/sbin/init/sbin/init"); } TEST_F(sinsp_with_test_input, plugin_anomalydetection_filterchecks_fields_fd) @@ -193,7 +193,7 @@ TEST_F(sinsp_with_test_input, plugin_anomalydetection_filterchecks_fields_fd_net ASSERT_EQ(get_field_as_string(evt, "fd.cip"), "172.40.111.222"); ASSERT_EQ(get_field_as_string(evt, "fd.sip"), "142.251.111.147"); ASSERT_EQ(get_field_as_string(evt, "fd.num"), "8"); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[1]", pl_flist), "18172.40.111.222:54321->142.251.111.147:44300"); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[1]", pl_flist), "1172.40.111.222:54321142.251.111.147:4438172.40.111.222:54321->142.251.111.147:44300"); client = test_utils::fill_sockaddr_in(DEFAULT_CLIENT_PORT, DEFAULT_IPV4_CLIENT_STRING); std::vector st = test_utils::pack_socktuple(reinterpret_cast(&client), reinterpret_cast(&server)); @@ -207,5 +207,5 @@ TEST_F(sinsp_with_test_input, plugin_anomalydetection_filterchecks_fields_fd_net ASSERT_EQ(get_field_as_string(evt, "fd.lip"), "142.251.111.147"); ASSERT_EQ(get_field_as_string(evt, "fd.cip"), "172.40.111.222"); ASSERT_EQ(get_field_as_string(evt, "fd.sip"), "142.251.111.147"); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[1]", pl_flist), "16172.40.111.222:54321->142.251.111.147:44300"); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[1]", pl_flist), "1172.40.111.222:54321142.251.111.147:4436172.40.111.222:54321->142.251.111.147:44300"); }