Безопасность компьютерных систем 2019/SECCOMP
Материал из Wiki - Факультет компьютерных наук
Содержание
Linux seccomp
Ссылки для изучения:
- Рекомендуемая основная презентация (пригодится для выполнения бонусного задания к заданию 3): http://man7.org/conf/lceu2016/limiting_kernel_attack_surface_with_seccomp-ContainerCon.eu_2016-Kerrisk.pdf
- https://eigenstate.org/notes/seccomp
- Kafel - язык для конструирования политик seccomp (not an official Google product) https://github.com/google/kafel
Тестовый пример 1
#include <stdio.h>
#include <unistd.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>
int main () {
pid_t pid;
printf("Step 1: no restrictions yet\n");
prctl (PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
printf ("Step 2: entering the strict mode. Only read(), write(), exit() and sigreturn() syscalls are allowed\n");
pid = getpid ();
printf ("!!YOU SHOULD NOT SEE THIS!! My PID = %d", pid);
return 0;
}
Тестовый пример 2
#include <stdio.h>
#include <seccomp.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <errno.h>
int main() {
pid_t pid;
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_TRAP);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(sigreturn), 0);
seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
printf ("No restrictions yet\n");
seccomp_load(ctx);
pid = getpid();
printf("!! YOU SHOULD NOT SEE THIS!! My PID is%d\n", pid);
return 0;
}
Тестовый пример 3
/*************************************************************************\
* Copyright (C) Michael Kerrisk, 2016. *
* *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation, either version 3 or (at your option) any *
* later version. This program is distributed without any warranty. See *
* the file COPYING.gpl-v3 for details. *
\*************************************************************************/
/* Supplementary program for Chapter Z */
/* seccomp_deny.c
A simple seccomp filter example. Install a filter that kills the process
if open() is called.
*/
#define _GNU_SOURCE
#include <stddef.h>
#include <fcntl.h>
#include <linux/audit.h>
#include <sys/syscall.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>
#include <sys/types.h> /* Type definitions used by many programs */
#include <stdio.h> /* Standard I/O functions */
#include <stdlib.h> /* Prototypes of commonly used library functions, plus EXIT_SUCCESS and EXIT_FAILURE constants */
#include <unistd.h> /* Prototypes for many system calls */
#include <errno.h> /* Declares errno and defines error constants */
#include <string.h> /* Commonly used string-handling functions */
static int
seccomp(unsigned int operation, unsigned int flags, void *args)
{
return syscall(__NR_seccomp, operation, flags, args);
}
static void
install_filter(void)
{
struct sock_filter filter[] = {
/* Load architecture */
BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
(offsetof(struct seccomp_data, arch))),
/* Kill process if the architecture is not what we expect */
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 1, 0),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),
/* Load system call number */
BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
(offsetof(struct seccomp_data, nr))),
/* Allow system calls other than open() */
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_open, 1, 0),
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
/* Kill process on open() */
BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL)
};
struct sock_fprog prog = {
.len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
.filter = filter,
};
if (seccomp(SECCOMP_SET_MODE_FILTER, 0, &prog) == -1)
perror("seccomp");
/* On Linux 3.16 and earlier, we must instead use:
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog))
errExit("prctl-PR_SET_SECCOMP");
*/
}
int
main(int argc, char **argv)
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
perror("prctl");
install_filter();
if (open("/tmp/a", O_RDONLY) == -1)
perror("open");
printf("We shouldn't see this message\n");
exit(EXIT_SUCCESS);
}
Тестовый пример 4
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/audit.h>
#define ArchField offsetof(struct seccomp_data, arch)
#define Allow(syscall) \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_##syscall, 0, 1), \
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
struct sock_filter filter[] = {
/* validate arch */
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, ArchField),
BPF_JUMP( BPF_JMP+BPF_JEQ+BPF_K, AUDIT_ARCH_X86_64, 1, 0),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP),
/* load syscall */
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct seccomp_data, nr)),
/* list of allowed syscalls */
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_brk, 0, 1),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_mmap, 0, 1),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_munmap, 0, 1),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_write, 0, 1),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_exit, 0, 1),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
/* and if we don't match above, die */
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL),
};
struct sock_fprog filterprog = {
.len = sizeof(filter)/sizeof(filter[0]),
.filter = filter
};
int main(int argc, char **argv) {
char buf[1024];
/* set up the restricted environment */
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
perror("Could not start seccomp:");
exit(1);
}
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &filterprog) == -1) {
perror("Could not start seccomp:");
exit(1);
}
/* printf only writes to stdout, but for some reason it stats it. */
printf("hello there!\n");
if (argc > 1 && strcmp(argv[1], "haxor") == 0) {
int fd = socket(AF_INET6, SOCK_STREAM, 0);
/* ...and start sending spam */
}
}