Audit of Falco, the open-source cloud-native runtime security

Introduction

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.

Scope

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.

Findings

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.

ID Description Category 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

Conclusion

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.

Article Link: Audit of Falco, the open-source cloud-native runtime security