Outils pour utilisateurs

Outils du site


securite:seccomp

SECCOMP : exemple avec Python (tracer et sécuriser)

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.

Modes prévus

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.).

Mode 1 - "l'original"

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.

Mode 2 - "avec filtrage"

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.

Trouver quels appels sont effectués par un programme

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).

Mise en œuvre pour lancer un script Python via un fork

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é.

Mise en œuvre pour lancer un script Python via un fork

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 

Ressources

securite/seccomp.txt · Dernière modification: 2020/07/10 18:58 de julieng

Outils de la page