All Projects → xfernando → Go2seccomp

xfernando / Go2seccomp

Licence: mit
Generate seccomp profiles from go binaries

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to Go2seccomp

Selinux
common selinux implementation
Stars: ✭ 107 (-12.3%)
Mutual labels:  containers
Kontena
The developer friendly container and micro services platform. Works on any cloud, easy to setup, simple to use.
Stars: ✭ 1,480 (+1113.11%)
Mutual labels:  containers
Cloud Discovery
Cloud Discovery provides a point in time enumeration of all the cloud native platform services
Stars: ✭ 119 (-2.46%)
Mutual labels:  containers
Labs
This is a collection of tutorials for learning how to use Docker with various tools. Contributions welcome.
Stars: ✭ 10,443 (+8459.84%)
Mutual labels:  containers
Containers
Containers backed by std.experimental.allocator
Stars: ✭ 111 (-9.02%)
Mutual labels:  containers
Images
Browser images for Selenoid and Moon
Stars: ✭ 116 (-4.92%)
Mutual labels:  containers
Bitnami Docker Suitecrm
SuiteCRM container image
Stars: ✭ 105 (-13.93%)
Mutual labels:  containers
Bitnami Docker Rabbitmq
Bitnami Docker Image for RabbitMQ
Stars: ✭ 120 (-1.64%)
Mutual labels:  containers
Dockle
Container Image Linter for Security, Helping build the Best-Practice Docker Image, Easy to start
Stars: ✭ 1,713 (+1304.1%)
Mutual labels:  containers
Registrish
Dirty hack to run a read-only, public Docker registry on almost any static file hosting service (e.g. NGINX, Netlify, S3...)
Stars: ✭ 119 (-2.46%)
Mutual labels:  containers
Docker Slim
DockerSlim (docker-slim): Don't change anything in your Docker container image and minify it by up to 30x (and for compiled languages even more) making it secure too! (free and open source)
Stars: ✭ 11,712 (+9500%)
Mutual labels:  containers
Bitnami Docker Node
Bitnami Node.js Docker Image
Stars: ✭ 111 (-9.02%)
Mutual labels:  containers
Bitnami Docker Mysql
Bitnami MySQL Docker Image
Stars: ✭ 116 (-4.92%)
Mutual labels:  containers
Cas Webapp Docker
Apereo CAS Server web application running inside a docker container.
Stars: ✭ 107 (-12.3%)
Mutual labels:  containers
Vorteil
turn your applications and containers into micro virtual machines
Stars: ✭ 120 (-1.64%)
Mutual labels:  containers
Minideb
A small image based on Debian designed for use in containers
Stars: ✭ 1,561 (+1179.51%)
Mutual labels:  containers
Ruby Lxc
ruby bindings for liblxc
Stars: ✭ 115 (-5.74%)
Mutual labels:  containers
Dksnap
Docker Snapshots for Development and Test Data
Stars: ✭ 122 (+0%)
Mutual labels:  containers
Ignite
Ignite a Firecracker microVM
Stars: ✭ 1,954 (+1501.64%)
Mutual labels:  containers
Lastbackend
System for containerized apps management. From build to scaling.
Stars: ✭ 1,536 (+1159.02%)
Mutual labels:  containers

go2seccomp

go2seccomp analyzes compiled go binaries and generates a seccomp profile that blocks all syscalls, except the ones used by the binary. The profile can then be used when running the binary in a container using docker, rkt, or any runtime that supports seccomp to further reduce the container's attack surface.

This tool aims to help make the process of creating seccomp profiles for go programs easier, and can also help developers see when changes increase or decrease the scope of what their programs can do with relation to syscalls.

Installation

go get -u github.com/xfernando/go2seccomp

Usage

go2seccomp /path/to/binary /path/to/profile.json

Examples

Running go2seccomp on a simple hello world application like this one:

package main

import "fmt"

func main() {
        fmt.Println("Hello World!")
}

yields this profile:

 {
     "defaultAction": "SCMP_ACT_ERRNO",
     "architectures": [
         "SCMP_ARCH_X86_64"
     ],
     "syscalls": [
         {
             "names": [
                 "arch_prctl",
                 "brk",
                 "clone",
                 "close",
                 "epoll_create",
                 "epoll_create1",
                 "epoll_ctl",
                 "epoll_wait",
                 "execve",
                 "exit",
                 "exit_group",
                 "fcntl",
                 "futex",
                 "getpid",
                 "gettid",
                 "kill",
                 "madvise",
                 "mincore",
                 "mmap",
                 "munmap",
                 "open",
                 "pselect6",
                 "read",
                 "readlinkat",
                 "rt_sigaction",
                 "rt_sigprocmask",
                 "rt_sigreturn",
                 "sched_getaffinity",
                 "sched_yield",
                 "setitimer",
                 "sigaltstack",
                 "stat",
                 "tkill",
                 "write"
             ],
             "action": "SCMP_ACT_ALLOW"
         }
     ]
 }

With the generated profile we can then start a docker container like this (assuming you built an image for the code above with the tag helloworld):

docker run --security-opt="no-new-privileges" --security-opt="seccomp=profile.json" helloworld

There's a script on examples/helloworld called build-and-run.sh that takes this hello world example, builds the binary, generates the seccomp profile, builds the docker image and runs the image with the generated profile:

Running go2seccomp on the kubectl 1.9.0 binary yields the following profile:

{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": [
        "SCMP_ARCH_X86_64"
    ],
    "syscalls": [
        {
            "names": [
                "accept",
                "accept4",
                "arch_prctl",
                "bind",
                "brk",
                "chdir",
                "chroot",
                "clone",
                "close",
                "connect",
                "dup",
                "dup2",
                "epoll_create",
                "epoll_create1",
                "epoll_ctl",
                "epoll_wait",
                "execve",
                "exit",
                "exit_group",
                "fchdir",
                "fchmod",
                "fchmodat",
                "fchown",
                "fcntl",
                "fstat",
                "fsync",
                "ftruncate",
                "futex",
                "getcwd",
                "getdents64",
                "getgid",
                "getpeername",
                "getpid",
                "getppid",
                "getrandom",
                "getsockname",
                "getsockopt",
                "gettid",
                "getuid",
                "ioctl",
                "kill",
                "listen",
                "lseek",
                "lstat",
                "madvise",
                "mincore",
                "mkdirat",
                "mmap",
                "mount",
                "munmap",
                "open",
                "openat",
                "pipe",
                "pipe2",
                "prctl",
                "pread64",
                "pselect6",
                "ptrace",
                "pwrite64",
                "read",
                "readlinkat",
                "recvfrom",
                "recvmsg",
                "renameat",
                "rt_sigaction",
                "rt_sigprocmask",
                "rt_sigreturn",
                "sched_getaffinity",
                "sched_yield",
                "sendfile",
                "sendmsg",
                "sendto",
                "setgid",
                "setgroups",
                "setitimer",
                "setpgid",
                "setsid",
                "setsockopt",
                "setuid",
                "shutdown",
                "sigaltstack",
                "socket",
                "stat",
                "symlinkat",
                "tkill",
                "unlinkat",
                "unshare",
                "wait4",
                "waitid",
                "write",
                "writev"
            ],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

How it works

go2seccomp usesgo tool objdump to decompile the binary. With the decompiled binary we search for occurences of any of the following:

  • CALL syscall.Syscall(SB)
  • CALL syscall.Syscall6(SB)
  • CALL syscall.RawSyscall(SB)
  • CALL syscall.RawSyscall6(SB)

These are calls to functions of the same name on the syscall package, which are used to provide access to the underlying syscalls using constants with the syscall ID.

After finding an occurrence of one of those calls, go2seccomp searches the previous instructions looking for the MOVQ instruction that puts the syscall ID at the address pointed by the stack pointer (SP) register.

As an example, let's look at the code for the GetCwd func of the syscall package. Line 152 is where the call to the Syscall func is made, shown below.

r0, _, e1 := Syscall(SYS_GETCWD, uintptr(_p0), uintptr(len(buf)), 0)

It passes the SYS_GETCWD constant, which has the value 79. Below we have the dissasembled code for this line.

  zsyscall_linux_amd64.go:152   0x47b234    48c704244f000000    MOVQ $0x4f, 0(SP)
  zsyscall_linux_amd64.go:152   0x47b23c    48894c2408          MOVQ CX, 0x8(SP)
  zsyscall_linux_amd64.go:152   0x47b241    4889442410          MOVQ AX, 0x10(SP)
  zsyscall_linux_amd64.go:152   0x47b246    48c744241800000000  MOVQ $0x0, 0x18(SP)
  zsyscall_linux_amd64.go:152   0x47b24f    e81c340000          CALL syscall.Syscall(SB)

The value the MOVQ instruction is putting on the address pointed by the SP register is 0x4F, which is 79, the ID of the getcwd syscall.

We collect all syscall IDs using this method and generate a seccomp profile json as output.

Go Runtime syscalls

Go's runtime package doesn't use the functions on the syscall package. Instead, it has a lot of assembly code that uses syscalls directly. The file sys_linux_amd64.s contains most of those. The first version of go2seccomp didn't take those into account, so a lot of syscalls needed were missing, but are now properly accounted for.

Since it now analyzes actual SYSCALL calls, this removed the limitations that only those syscalls made through the syscall package would be discovered. Now even syscalls made in C code through cgo should be discovered when analyzing static builds.

Default syscalls

When I tried running containers with profiles go2seccomp generated they didn't start with different error messages at times (even the basic helloworld). After some digging, I found this issue on the moby project, where I found that some syscalls need to be enabled on the seccomp profile because docker needs them to start the container, even if they're not needed for the binary the container runs.

The syscalls that need to be enabled by default are:

  • execve
  • futex
  • stat

Limitations

There are some limitations in go2seccomp:

  • If the syscall ID passed to the syscall functions are defined at runtime, they won't be detected
    • Though a warning will be displayed when we find a syscall whose ID can't be parsed
  • If you use go plugins, syscalls from the plugins probably won't be detected

More details about limitations can be seen at @jessfraz keynote at FOSDEM around 30 minutes in.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].