Falco's maintainers, with support from Cloud Native Computing Foundation, engaged with Quarkslab to perform an audit of Falco, an open-source cloud-native runtime security tool. The goal of the audit was to assist the Falco maintainers to increase their security posture using static and dynamic analysis (fuzzing in particular) and was organized by Open Source Technology Improvement Fund, Inc.
Falco makes it easy to consume kernel events and enrich those events with information from Kubernetes and the rest of the cloud-native stack. It monitors system calls to secure a system, by:
- parsing the Linux system calls from the kernel at runtime;
- asserting the stream against a powerful rules engine;
- alerting when a rule is violated.
The project ships with a default set of rules ready to be consumed by end-users to secure their Kubernetes clusters. However, users can write their own rules using a syntax created by the project for specific needs.
The full report of the assessment can be found in the Falco GitHub repository. All important findings were patched following the audit.
This report describes the steps and research conducted by Quarkslab’s engineers on static analysis and fuzzing. More specifically, our engineers identified in Syzkaller an interesting option for blackbox fuzzing of Falco's solution, making it possible to challenge both the driver and userland application at a high rate of events, and being able to trigger complex syscall chains. Falco showed no weakness in dealing with a large amount of unusual events, despite long fuzzing sessions. A way to improve this fuzzing solution would be to add userland process coverage to the syzkaller-based harness, to better guide the fuzzer.
The scope of this audit was mainly the userspace part of Falco, distributed in the falcosecurity/falco and falcosecurity/libs repositories on GitHub. We investigated also the kernel module, although it was not the focus of the audit. The dependencies and the plugins of Falco were left out of scope. The eBPF drivers of Falco also were not reviewed.
The table below summarizes the findings of the audit. A total of 19 vulnerabilities were found, of which 1 had medium severity and 9 had low severity.
|MEDIUM 1||Potential buffer overflow due to not null terminated output of readlink in libscap/scap_proc_file_root||Buffer overflow||Medium|
|LOW 1||Memory leak on error structure in libscap/engine/bpf/scap_bpf.c:513||Memory Leak||Low|
|LOW 2||Resource leak on pfile in libscap/engine/kmod/scap_kmod.c:67||Resource Leak||Low|
|LOW 3||Memory leak on handle structure in libscap/scap.c:146||Memory Leak||Low|
|LOW 4||Memory leak on pAdapterInfo structure in libscap/windows_hal.c:342||Memory Leak||Low|
|LOW 5||Multiple unchecked return value from malloc, calloc and realloc||Null dereference||Low|
|LOW 6||Multiple unchecked return value from localtime, sinsp_threadinfo::get_fd_table and scap_write_proclist_begin that can return Nullptr||Null dereference||Low|
|LOW 7||Double free in libscap/scap.c function scap_open||Double free||Low|
|LOW 8||Garbage return value from stack in libsinsp/sinsp.cpp||Garbage return value||Low|
|LOW 9||Four null terminations of buffers written out of range by one in libscap/scan_fds.c||Buffer overflow||Low|
|INFO 1||Multiple bad handling of realloc return value in libsinsp/filterchecks.cpp||Memory Leak||Info|
|INFO 2||Missing va_end() after va_copy() in test file sinsp_with_test_input.h||Incorrect handling of variadic macros||Info|
|INFO 3||Returned heap allocated buffer resolved after being deallocated||Return pointer on freed memory||Info|
|INFO 4||Multiple potential Null pointer dereferences in macro HASH_ADD_INT64||Null dereference||Info|
|INFO 5||Resource leak in libsinsp example libsinsp/examples/test.cpp||Resource leak||Info|
|INFO 6||Dangerous construct in a vforked process in libscap/engine/gvisor/runsc.cpp||Incorrect use of vfork||Info|
|INFO 7||Buffer overflow with not null terminated output of readlink in debug code in libsinsp/parsers.cpp||Buffer overflow||Info|
|INFO 8||Return value in various usage of readlink not checked which could lead to write to a different file||Unchecked return value||Info|
|INFO 9||Multiple crashes in the parsing of scap files and event buffer with malformed files||Null dereference||Info|
Fuzzing the core of Falco proved to be non-trivial because of the complexity of the events parser inputs. We approached this problem with different strategies. First trying to fuzz specifically some parsers with libprotobuf-mutator and highly structured fuzzing. Then doing black box fuzzing of Falco and its driver via syzkaller. And finally trying mutational fuzzing using the scap file format. Although all of these approaches have limitations, we think the syzkaller and libprotobuf-mutator techniques could be useful to discover real bugs.
To conclude, Quarkslab provided several leads and strategies on how to implement static and dynamic security analysis of the Falco project in the limited amount of time dedicated to the project. The audit also unveiled some issues in the codebase, thanks to the automated tools and the manual investigations, but nothing critical or exploitable in the end. Overall, it was a pleasure to work with the Falco maintainers, who were very helpful and willing to make the project more secure.
If you would like to learn more about our security audits and explore how we can help you, get in touch with us!