Voir aussi : autres exemples en c des usages de seccomp (mode 1)
SECCOMP (secure computing mode) est une bibliothèque par défaut de Linux permettant d'agir sur un programme vis-à-vis du noyau.
Plusieurs modalités existent : l'arrêt complet du programme et de ses enfants (le mode original), l'arrêt du thread concerné, une “trace”, un “log” ou l'autorisation (c'est-à-dire l'absence de restriction et de signalement).
Certaines filtres peuvent affiner (par exemple open peut être restreint à la lecture seule, etc.).
Deux modes généraux de restriction existent.
Attention : quelque soit le mode prévu (original ou filtrage), les règles qui agissent sur le noyau pour le programme visé et ses enfants / descendant / clones, ne peuvent être déchargées ou modifiées.
Si une nouvelle règle est activée, la préséance agit en fonction d'un poids défini par le type de restriction (“ALLOW” est plus faible → “KILL” est plus fort).
Dans une politique de sécurité active, il est toujours préférable d'agir via une liste blanche : tout ce qui n'est pas explicitement autorisé, doit être interdit. De plus, seccomp ne couvre pas tout le spectre des protections disponibles pour les programmes dans un bac à sable (chroot, etc.).
Seuls 4 appels système sont autorisés :
exit()
sigreturn()
read()
write()
Ces 4 appels ne permettent donc pas d'ouvrir de nouveaux descripteurs de fichiers : seuls ceux ouverts peuvent être utilisés, dans la limite de la lecture et l'écriture. L'évolution dans le fichier grâce à “seek” n'est donc pas possible (lecture et écriture en sens unique).
Cette fonctionnalité permettait à l'origine de donner à des unités de traitement, du code non-sûr provenant du réseau, pour du calcul distribué, sans que cela n'interfère avec ou empoissonne la machine de traitement.
Lorsque ses fonctionnalités sont actives, le programme ne peut plus passer des appels qui ne soient pas explicitement autorisés (“liste blanche”) ou qui ne sont pas explicitement interdits (“liste noire”).
Ce mode - seccomp-bpf - autorise une configuration conforme au mode original.
Les règles sont définis dans le code source : une fois la compilation effectuée, si elles sont en dures (sans intervention extérieure prévue), la modification n'est pas directement possible.
Encore faut-il trouver quels appels sont passés par un programme que l'on souhaite renforcer :
julien@JulienGPortable:~$ strace -cf ls ./ [ ... liste des fichiers trouvés par "ls" ... ] % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 30,70 0,000614 21 28 mmap 10,95 0,000219 3 62 write 9,15 0,000183 20 9 mprotect 8,50 0,000170 14 12 close 7,75 0,000155 15 10 openat 7,40 0,000148 18 8 pread64 5,60 0,000112 16 7 read 5,05 0,000101 9 11 fstat 2,85 0,000057 28 2 getdents64 2,35 0,000047 23 2 2 statfs 2,10 0,000042 42 1 munmap 1,65 0,000033 11 3 brk 1,30 0,000026 13 2 rt_sigaction 1,00 0,000020 10 2 2 access 0,65 0,000013 13 1 prlimit64 0,60 0,000012 12 1 rt_sigprocmask 0,60 0,000012 6 2 1 arch_prctl 0,60 0,000012 12 1 set_tid_address 0,60 0,000012 12 1 set_robust_list 0,35 0,000007 3 2 ioctl 0,15 0,000003 3 1 stat 0,10 0,000002 2 1 futex 0,00 0,000000 0 1 execve ------ ----------- ----------- --------- --------- ---------------- 100.00 0,002000 170 5 total
Cette commande vous permet d'avoir immédiatement les appels systèmes qui sont utilisés. Attention : une fois seccomp actif dans le programme, ce dernier peut ajouter ses propres appels à la liste (faire le différentiel).
Les enfants héritent du contexte de leur parent ; ici avec le fork du processus, l'enfant laisse la place (même PID) à l'exécutable Python3, qui de fait peut voir ses appels systèmes restreints.
Ici le script Python affiche juste un message (pas d'appel au réseau par exemple).
#include <stdio.h> #include <seccomp.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <errno.h> #include <stdlib.h> int main(int argc, char **argv, char **envp) { scmp_filter_ctx scmp = seccomp_init(SCMP_ACT_KILL); if (!scmp) { fprintf(stderr, "Failed to initialize libseccomp\n"); return -1; } int r = 0; // attention, pas sûr (deux additions peuvent s'annuler, voir pour autre chose) r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(pwrite64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(pwritev), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fstat64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fstatat64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lstat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lstat64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(stat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(stat64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(statx), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getdents), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getdents64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(pread64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(preadv), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(access), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(capget), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(chdir), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(dup), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(dup3), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(faccessat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fchdir), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(gettid), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(_llseek), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(readlink), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(readlinkat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getcwd), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(msgget), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(msgrcv), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(msgsnd), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(semget), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(semop), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(semtimedop), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(ipc), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(execve), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fork), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(unshare), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(vfork), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(wait4), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(waitid), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(waitpid), 0); // + Python r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getrandom), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lseek),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(openat),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(ioctl),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(dup),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(sigaltstack),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lstat),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getcwd),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getuid),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getgid),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(geteuid),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getegid),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(munmap),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(sysinfo),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(arch_prctl),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(futex),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(set_tid_address),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(prlimit64),0); if (r != 0 ){ printf("pas bon\n"); return -1; } else { printf("bon\n"); } // Load in the kernel if (seccomp_load(scmp) != 0) { fprintf(stderr, "Failed to load the filter in the kernel\n"); return -1; } // printf("hello\n"); // execlp("/bin/ls","./",NULL); // penser à modifier ici le nom du script Python char *args[]={"python3", "./script-2.py", NULL}; pid_t child_pid; int child_status; child_pid = fork(); if(child_pid == 0) { execv("/usr/bin/python3.8", args); } else { pid_t tpid = wait(&child_status); printf("stop parent\n"); } // return 0; }
Le code peut être testé avec la commande suivante :
var=" --- NOM DU SCRIPT ---" && gcc "$var.c" -o "$var" -lseccomp && echo " --- ENVOI VERS STDIN --- " | "./$var"
Si vous commentez une des listes pour l'autorisation d'un appel système, le script peut potentiellement être arrêté.
Il s'agit désormais d'agir directement dans le fonctionnement de l'exécutable Python en cours. Pour cela, j'ai choisi une bibliothèque dynamique (.so) avec une fonction unique.
#include <stdio.h> #include <seccomp.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <errno.h> #include <stdlib.h> int verrouiller(int argc, char **argv, char **envp) { scmp_filter_ctx scmp = seccomp_init(SCMP_ACT_KILL); if (!scmp) { return -1; } int r = 0; // /!\ je désactive la possibilité de fermeture de descripteurs de fichier // r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(close), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(write), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(writev), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(pwrite64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(pwritev), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fstat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fstat64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fstatat64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lstat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lstat64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(stat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(stat64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(statx), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(openat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(mmap), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(mmap2), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(munmap), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getdents), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getdents64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(pread64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(read), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(readv), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(preadv), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fcntl), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(access), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(brk), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(capget), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(chdir), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(dup), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(dup2), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(dup3), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(faccessat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fchdir), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getpid), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(gettid), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lseek), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(_llseek), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(futex), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(readlink), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(readlinkat), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getcwd), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(msgget), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(msgrcv), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(msgsnd), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(semget), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(semop), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(semtimedop), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(ipc), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(clone), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(execve), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(fork), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(unshare), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(vfork), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(wait4), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(waitid), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(waitpid), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getrandom), 0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lseek),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(openat),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(ioctl),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(dup),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(sigaltstack),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(lstat),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getcwd),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getuid),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getgid),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(geteuid),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(getegid),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(munmap),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(sysinfo),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(arch_prctl),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(futex),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(set_tid_address),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(set_robust_list),0); r += seccomp_rule_add(scmp, SCMP_ACT_ALLOW, SCMP_SYS(prlimit64),0); if (r != 0 ) { return -1; } if (seccomp_load(scmp) != 0) { return -1; } return 0; }
Après la compilation, on peut intégrer cette bibliothèque très facilement au sein d'un script Python dont on souhaite restreindre les appels systèmes définitivement (ainsi que tous ses éventuels enfants, clones, fork, etc.).
import ctypes malib = ctypes.CDLL("./vers_python.so") # la bibliothèque nouvellement créée # tout est chargé ou doit être chargé avant ces lignes # on verrouille à partir de là (attention au "print" si vous empêchez "write") print( "seccomp retour = ", malib.verrouiller() ) # 'with' ferme automatiquement le descripteur de fichier with open("./message.txt","r") as f: print( f.read() ) # après cela, Python va fermer "f" et donc l'appel système va tuer le processus # ne s'exécutera jamais a = 1+1 b = a+1
Pour tester le fonctionnement, compilation de la bibliothèque comprise :
gcc -O3 -fPIC -g3 -I/usr/include/seccomp -o vers_python.o -c vers_python.c && gcc -O3 -fPIC -shared -o vers_python.so vers_python.o -L/usr/lib/x86_64-linux-gnu -lseccomp && ltrace -o ./log.txt -c python3 ./vers_python.py
Pourquoi faire cela ?
Documentations générales sur seccomp :
Documentation sur les bibliothèques systèmes Linux :
Appel de code C dans Python (ctypes ; sametmax)
Bibliothèque système pour Rust (GIT)
Compilation - ordre des arguments (GCC)
Tracer les appels systèmes :