Skip to content

Commit

Permalink
update(anomalydetection): add some custom behavior profile short-cut …
Browse files Browse the repository at this point in the history
…fields options

Signed-off-by: Melissa Kilby <[email protected]>
  • Loading branch information
incertum committed Aug 2, 2024
1 parent 6a898a6 commit 569eb0a
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 10 deletions.
152 changes: 152 additions & 0 deletions plugins/anomalydetection/src/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
5 changes: 5 additions & 0 deletions plugins/anomalydetection/src/plugin_sinsp_filterchecks.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}

Expand Down
27 changes: 26 additions & 1 deletion plugins/anomalydetection/src/plugin_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -196,8 +201,10 @@ const std::vector<plugin_sinsp_filterchecks_field> 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<plugin_sinsp_filterchecks::check_type>(i);
Expand All @@ -206,7 +213,11 @@ const std::vector<plugin_sinsp_filterchecks_field> 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(']');
Expand All @@ -227,8 +238,17 @@ const std::vector<plugin_sinsp_filterchecks_field> 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,
Expand All @@ -243,6 +263,11 @@ const std::vector<plugin_sinsp_filterchecks_field> 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;
Expand Down
6 changes: 3 additions & 3 deletions plugins/anomalydetection/test/include/test_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down
12 changes: 6 additions & 6 deletions plugins/anomalydetection/test/src/num/cms.ut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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<uint8_t> st = test_utils::pack_socktuple(reinterpret_cast<sockaddr*>(&client), reinterpret_cast<sockaddr*>(&server));
Expand All @@ -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");
}

0 comments on commit 569eb0a

Please sign in to comment.