This content originally appeared on Level Up Coding - Medium and was authored by TJ. Podobnik, @dorkamotorka
Linux Seccomp Security Profiles from scratch using Golang
This is the fourth part of the series, where I’ll demonstrate how to manage seccomp profiles using Golang. We’ll discuss how they are used to control allowed syscalls. Although this series focuses on containers, I’m simplifying things by experimenting with processes, since a container essentially consists of processes, namespaces, and some additional features that we are addressing in this series. Nevertheless, the same principles discussed here apply to containers as well.
For reference, here’s the previous post in this series:
Container Internals Series Part 3: Mount Namespace
Seccomp
Seccomp, short for secure computing mode, is a security feature introduced in the Linux kernel 2.6.12.
It allows for the restriction of system calls (syscalls) that a process can make, thereby reducing potential security vulnerabilities. Seccomp plays a critical role in tools like Containerd, which is extensively used by Kubernetes, Docker and others.
# Example of configuring Pod with Seccomp profile
apiVersion: v1
kind: Pod
metadata:
name: default-pod
spec:
# NOTE: Here you can add seccomp profile
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: test-container
image: hashicorp/http-echo:1.0
...
For instance, in a production web server running your application (be it either in a container or as a normal process), you can pre-configure a seccomp profile which will ensure your app operates under a limited set of syscalls. The default seccomp profile might allow only essential syscalls needed for typical web server operations, such as reading files, writing logs, and handling network requests. Syscalls unrelated to these operations, like those related to process management or low-level system control, would be blocked to reduce the attack surface in case the attacked gains access to your server through that same process.
Consider another scenario where an organization deploys a microservice that performs data processing tasks. This microservice only needs to read input data, perform computations, and write the results to a database. The seccomp profile applied to this microservice can be customized to allow only the syscalls necessary for file I/O and database communication, while the rest can be blocked.
And we can go on and on, but I think you get an idea. Let’s see this in action on a simple example.
Code Example
First we need to check whether our local system supports seccomp:
cat /boot/config-$(uname -r) | grep CONFIG_SECCOMP
In case it outputs CONFIG_SECCOMP=y, we are good to go!
We also need to install the libseccomp-dev and lurk package which we’re gonna need later on:
sudo apt install libseccomp-dev
curl -L -o /tmp/lurk.tar.gz "https://github.com/JakWai01/lurk/releases/latest/download/lurk-x86_64-unknown-linux-gnu.tar.gz"
tar -xzf /tmp/lurk.tar.gz -C /tmp
sudo install /tmp/lurk /usr/local/bin
Now let’s first take a look at the code example without any syscall restrictions:
package main
import (
"fmt"
"syscall"
)
func main() {
err := syscall.Mkdir("/tmp/sec", 0755)
if err != nil {
panic(err)
} else {
fmt.Printf("Create a tmp file")
}
}
This program just creates a file /tmp/sec. So now we can either blacklist all the syscalls we don’t want it to do or even easier — whitelist the ones that it ONLY does.
In order to figure which syscalls this program makes, we run our go program using strace:
lurk ./seccomp-demp
lurk is an alternative to strace tool, which outputs all of the syscalls that our program makes, so we can later whitelist them in our program.
GitHub - JakWai01/lurk: A pretty (simple) alternative to strace
Here’s a screenshot of the redacted output:
Now we can modify our code as follows:
package main
import (
"fmt"
"syscall"
"github.com/seccomp/libseccomp-golang"
)
func main() {
// Set up a Seccomp filter and DENY ALL BY DEFAULT!
defaultAction := seccomp.ActErrno.SetReturnCode(int16(syscall.EPERM))
filter, err := seccomp.NewFilter(defaultAction)
if err != nil {
panic("Error creating Seccomp filter")
}
// Add allowed syscalls
var syscalls = []string{
"rt_sigaction", "mkdirat", "clone", "mmap", "readlinkat", "futex", "rt_sigprocmask",
"mprotect", "write", "sigaltstack", "gettid", "read", "open", "close", "fstat",
"munmap","brk", "access", "execve", "getrlimit", "arch_prctl", "sched_getaffinity",
"set_tid_address", "set_robust_list", "exit_group"}
for _, call := range syscalls {
syscallID, err := seccomp.GetSyscallFromName(call)
if err != nil {
panic(err)
}
// Here we allow the syscall in the list - one by one
if err := filter.AddRule(syscallID, seccomp.ActAllow); err != nil {
panic("Error adding rule for syscall")
}
}
// Load the Seccomp filter
if err := filter.Load(); err != nil {
panic("Error loading Seccomp filter")
}
// Trigger our initial program
err = syscall.Mkdir("/tmp/sec", 0755)
if err != nil {
panic(err)
} else {
fmt.Printf("Create a tmp file")
}
}
Complete source code is available on my GitHub:
LearningContainers/seccomp at main · dorkamotorka/LearningContainers
Conclusion
This post has explored the essentials of creating and managing Seccomp profiles using Golang, emphasizing their importance in controlling syscalls and enhancing security within containerized environments. By tailoring Seccomp filters to the specific needs of your applications, you can significantly reduce the attack surface, limiting potential vulnerabilities.
To stay current with the latest cloud technologies, make sure to subscribe to my bi-monthly newsletter, Cloud Chirp.
Container Internals Series Part 4: Seccomp was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by TJ. Podobnik, @dorkamotorka
TJ. Podobnik, @dorkamotorka | Sciencx (2024-08-27T11:22:20+00:00) Container Internals Series Part 4: Seccomp. Retrieved from https://www.scien.cx/2024/08/27/container-internals-series-part-4-seccomp/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.