Exécuter un programme C non approuvé dans un bac à sable sous Linux qui l'empêche d'ouvrir des fichiers, de forger, etc.?


110

Je me demandais s'il existe un moyen d'exécuter un programme C non approuvé sous un bac à sable sous Linux. Quelque chose qui empêcherait le programme d'ouvrir des fichiers ou des connexions réseau, ou de forger, d'exécuter, etc.?

Ce serait un petit programme, une tâche de devoirs, qui est téléchargé sur un serveur et sur lequel des tests unitaires sont exécutés. Le programme serait donc de courte durée.


Est-ce comme un programme C unique dont vous avez besoin pour exécuter 1 fois pendant 5 minutes, ou quelque chose que vous devez exécuter en permanence?
bwawok

Ce serait un petit programme qui est téléchargé et sur lequel des tests unitaires sont exécutés. Le programme serait donc de courte durée.
Frank

Quelle distribution le système utilise-t-il? Certaines distributions ont des outils prêts à l'emploi pour le sandboxing. Votre système dispose-t-il d'un modèle de sécurité tel que SELinux ou AppArmor activé?
thkala

J'utilise Fedora 13. Je regarde la politique de SELinux Sandbox. Je me demande quelles autres options existent.
Frank

Réponses:


47

J'ai utilisé Systrace pour sandbox des programmes non approuvés à la fois de manière interactive et en mode automatique. Il a un ptrace()backend basé sur qui permet son utilisation sur un système Linux sans privilèges spéciaux, ainsi qu'un backend beaucoup plus rapide et plus puissant qui nécessite de patcher le noyau.

Il est également possible de créer un bac à sable sur des systèmes de type Unix en utilisant chroot(1), bien que ce ne soit pas aussi facile ou sécurisé. Les conteneurs Linux et les prisons FreeBSD sont une meilleure alternative au chroot. Une autre alternative sous Linux est d'utiliser un framework de sécurité comme SELinux ou AppArmor , ce que je proposerais pour les systèmes de production.

Nous serions en mesure de vous aider davantage si vous nous disiez exactement ce que vous voulez faire.

ÉDITER:

Systrace fonctionnerait pour votre cas, mais je pense que quelque chose basé sur le modèle de sécurité Linux comme AppArmor ou SELinux est une alternative plus standard, et donc préférée, en fonction de votre distribution.

MODIFIER 2:

Bien qu'il chroot(1)soit disponible sur la plupart (tous?) Des systèmes de type Unix, il présente de nombreux problèmes:

  • Il peut être brisé. Si vous allez réellement compiler ou exécuter des programmes C non approuvés sur votre système, vous êtes particulièrement vulnérable à ce problème. Et si vos élèves ressemblent à moi, quelqu'un essaiera de sortir de prison.

  • Vous devez créer une hiérarchie de système de fichiers indépendante complète avec tout ce qui est nécessaire pour votre tâche. Vous n'avez pas besoin d'avoir un compilateur dans le chroot, mais tout ce qui est nécessaire pour exécuter les programmes compilés doit être inclus. Bien qu'il existe des utilitaires qui aident à cela, ce n'est toujours pas anodin.

  • Vous devez maintenir le chroot. Puisqu'il est indépendant, les fichiers chroot ne seront pas mis à jour avec votre distribution. Vous devrez soit recréer le chroot régulièrement, soit y inclure les outils de mise à jour nécessaires, ce qui exigerait essentiellement qu'il s'agisse d'une distribution Linux à part entière. Vous devrez également synchroniser les données système et utilisateur (mots de passe, fichiers d'entrée, etc.) avec le système hôte.

  • chroot()ne protège que le système de fichiers. Cela n'empêche pas un programme malveillant d'ouvrir des sockets réseau ou un programme mal écrit d'aspirer toutes les ressources disponibles.

Le problème d'utilisation des ressources est commun à toutes les alternatives. Les quotas de système de fichiers empêcheront les programmes de remplir le disque. Des paramètres appropriés ulimit( setrlimit()en C) peuvent protéger contre la surutilisation de la mémoire et toutes les bombes de fourche, ainsi que mettre un terme aux porcs CPU. nice(1)peut réduire la priorité de ces programmes afin que l'ordinateur puisse être utilisé pour toutes les tâches jugées plus importantes sans problème.


systrace a fonctionné pour moi pour des programmes simples, mais est resté bloqué indéfiniment lorsque GNU as (1) comme exécuté par GCC. Alors j'ai abandonné. C'est un bug non résolu dans systrace: forum.soft32.com/linux
pts

Existe-t-il un moyen de garantir que la mémoire partagée, les files d'attente de messages et les sémaphores ne sont pas partagés entre les processus sandbox?
daveagp le

1
Le lien systrace est rompu.
Collin

2
Et Firejail? Vous ne devez plus maintenir le fs en l'utilisant.
m3nda

18

J'ai récemment écrit un aperçu des techniques de sandboxing sous Linux . Je pense que votre approche la plus simple serait d'utiliser des conteneurs Linux (lxc) si cela ne vous dérange pas de forking et ainsi de suite, ce qui n'a pas vraiment d'importance dans cet environnement. Vous pouvez donner au processus un système de fichiers racine en lecture seule, une connexion réseau en boucle isolée, et vous pouvez toujours le tuer facilement et définir des limites de mémoire, etc.

Seccomp va être un peu difficile, car le code ne peut même pas allouer de mémoire.

Selinux est l'autre option, mais je pense que cela pourrait être plus de travail qu'un conteneur.


6

Vous pouvez utiliser Qemu pour tester rapidement les affectations. Cette procédure ci-dessous prend moins de 5 secondes sur mon ordinateur portable de 5 ans.

Supposons que l'étudiant doit développer un programme qui prend des entiers non signés, chacun sur sa propre ligne, jusqu'à ce qu'une ligne avec "-1" arrive. Le programme doit alors faire la moyenne de tous les entiers et afficher "Moyenne:% f". Voici comment tester un programme complètement isolé:

  1. Tout d'abord, obtenez root.binde Jslinux, nous l'utiliserons comme utilisateur (il a le compilateur C tcc):

    wget https://github.com/levskaya/jslinux-deobfuscated/raw/master/root.bin

  2. Nous voulons mettre la soumission de l'étudiant root.bin, alors configurez le périphérique de boucle:

    sudo losetup /dev/loop0 root.bin

    (vous pouvez également utiliser fuseext2 pour cela, mais ce n'est pas très stable. S'il se stabilise, vous n'aurez besoin de root pour rien de tout cela)

  3. Créez un répertoire vide:

    mkdir mountpoint

  4. Monter root.bin:

    sudo mount /dev/loop0 mountpoint

  5. Entrez le système de fichiers monté:

    cd mountpoint.

  6. Corriger les droits:

    sudo chown -R `whoami` .

  7. mkdir -p etc/init.d
  8. vi etc/init.d:

    #!/bin/sh
    cd /root
    echo READY 2>&1 > /dev/ttyS0
    tcc assignment.c 2>&1 > /dev/ttyS0
    ./a.out 2>&1 > /dev/ttyS0
    
  9. chmod +x etc/init.d/rcS

  10. Copiez la soumission sur la VM:

    cp ~/student_assignment.c root/assignment.c

  11. Quittez le FS racine de la VM:

    cd ..

  12. sudo umount mountpoint
  13. Maintenant, l'image est prête, il ne nous reste plus qu'à l'exécuter. Il compilera et exécutera la soumission après le démarrage.
  14. mkfifo /tmp/guest_output
  15. Ouvrez un terminal séparé et commencez à écouter la sortie de l'invité:

    dd if=/tmp/guest_output bs=1

  16. Dans un autre terminal:

    qemu-system-i386 -kernel vmlinuz-3.5.0-27-generic -initrd root.bin -monitor stdio -nographic -serial pipe:/tmp/guestoutput (Je viens d'utiliser le noyau Ubuntu ici, mais de nombreux noyaux fonctionneront)

  17. Lorsque la sortie de l'invité affiche «READY», vous pouvez envoyer des clés à la VM à partir de l'invite qemu. Par exemple, pour tester cette affectation, vous pouvez faire

    (qemu) sendkey 1
    (qemu) sendkey 4
    (qemu) sendkey ret
    (qemu) sendkey 1
    (qemu) sendkey 0
    (qemu) sendkey ret
    (qemu) sendkey minus
    (qemu) sendkey 1
    (qemu) sendkey ret
    
  18. Maintenant Average = 12.000000devrait apparaître sur le tube de sortie de l'invité. Si ce n'est pas le cas, l'étudiant a échoué.

  19. Quittez qemu: quit

Un programme réussissant le test est ici: https://stackoverflow.com/a/14424295/309483 . Utilisez simplement à la tcclib.hplace de stdio.h.


5

Essayez Linux en mode utilisateur . Il a une surcharge de performances d'environ 1% pour les travaux gourmands en ressources processeur, mais il peut être 6 fois plus lent pour les travaux gourmands en E / S.


4

Firejail est l'un des outils les plus complets pour ce faire - il prend en charge seccomp, les conteneurs de système de fichiers, les capacités et plus encore:

https://firejail.wordpress.com/features-3/


Cette réponse est excellente, elle mérite vraiment plus de votes positifs étant donné que firejail est activement entretenu avec une excellente documentation, englobe la plupart sinon toutes les autres réponses et est conçu pour être relativement facile à utiliser.
Jeff Hykin

3

L'exécuter dans une machine virtuelle devrait vous offrir toute la sécurité et les restrictions souhaitées.

QEMU serait un bon choix pour cela et tout le travail (téléchargement de l'application, mise à jour de l'image disque, démarrage de QEMU, exécution de l'application à l'intérieur et enregistrement de la sortie pour une récupération ultérieure) pourrait être scripté pour des tests automatisés.


2
Je ne connais pas l'OP, mais lancer une VM par programme de test serait inacceptable dans de nombreux cas. Dans mon environnement (je suis un AT), il peut y avoir jusqu'à 200 étudiants qui soumettent 10 à 12 programmes chacun sur une période de 2 heures. Aucun programme ne s'exécute pendant plus de 10 secondes de temps processeur, mais lorsque les soumissions s'accumulent, nous obtenons des délais d'exécution de 15 minutes ou plus. L'introduction d'une VM pour chaque programme pousserait le temps CPU à 60 secondes ou plus par programme et je ne veux pas du tout penser aux délais d'exécution. Peut-être une VM par session, mais nous ne pourrions pas faire cela par programme ...
thkala

@thkala C'est un bon point. J'aime l'idée de QEMU mais démarrer une VM pour chaque soumission n'est pas bon.
Frank

Eh bien, dans ce cas, gardez la même VM en marche tout le temps.
Laurent Parenteau

Pourriez-vous faire quelque chose en utilisant un instantané d'une VM qui est entièrement démarrée et prête à compiler et exécuter du code? Pour info, les vm ne sont pas nécessairement à l'abri du perçage. Vous pouvez également créer une version matérielle de celui-ci - un petit système qui démarre une image de reprise sur un support en lecture seule ou sur le réseau et fournit une sortie via le réseau ou la série, puis redémarre pour le suivant. Il y a eu quelques avancées de démarrage rapide qui permettent à Linux de démarrer en quelques secondes.
Chris Stratton

@thkala: Cela signifie que vous aurez besoin de moins de 3 secondes par soumission si vous les exécutez en série. L'approche que j'ai postée prend probablement environ 3 secondes sur une machine moderne (en série). Si vous parallélisez (ce que vous pourriez aussi bien), ce serait assez rapide.
Janus Troelsen

3

Quand il s'agit de sanboxing basé sur l'extraction ptrace (strace):

« Sydbox bac à sable » et « pinktrace bibliothèque de programmation » (il est C99 , mais il y a des liaisons à python et ruby pour autant que je sache).

Liens collectés liés au sujet:

http://www.diigo.com/user/wierzowiecki/sydbox

(désolé que pas de liens directs, mais pas encore assez de points de réputation)



1

Cette bibliothèque devrait bien servir votre objectif

http://sandbox.sourceforge.net

Bonne chance!


8
Cela ne semble pas être activement maintenu. Il semble également nécessiter un correctif pour le noyau Linux, ce qui le rendrait pratiquement inutile étant donné que sa dernière version date de 2003.
thkala


-1

ok merci à toutes les réponses, ils M'ont beaucoup aidé. Mais je ne suggérerais aucun d'entre eux comme solution pour la personne qui a posé la question initiale. Tous les outils mentionnés nécessitent beaucoup de travail pour tester le code des étudiants en tant que professeur, tuteur, prof. Le meilleur moyen dans ce cas serait à mon avis virtualbox. Ok, il émule un système x68 complet et n'a rien à voir avec le sens du sandboxing de cette manière, mais si j'imagine mon professeur de programmation, ce serait le meilleur pour lui. Donc, "apt-get install virtualbox" sur les systèmes basés sur Debian, tous les autres se dirigent vers http://virtualbox.org/ , créez une VM, ajoutez un iso, cliquez sur installer, attendez un peu et soyez chanceux. Ce sera beaucoup plus facile à utiliser que de configurer le mode utilisateur-linux ou de faire des choses lourdes ...

Et si vous craignez que vos élèves vous piratent, je suppose que vous avez un problème d'autorité et qu'une solution à cela les menacerait de poursuivre les vivants en justice si vous pouvez prouver qu'une seule bouchée de malware dans le travail qu'ils donnent tu...

De plus, s'il y a une classe et que 1% de celle-ci est aussi bonne qu'il pourrait faire de telles choses, ne les ennuyez pas avec des tâches aussi simples et donnez-leur de grandes tâches où elles doivent coder davantage. L'apprentissage intégratif est ce qu'il y a de mieux pour tout le monde, alors ne vous fiez pas aux anciennes structures bloquées ...

Et bien sûr, n'utilisez jamais le même ordinateur pour des choses importantes (comme la rédaction d'attestations et d'examens) que vous utilisez pour des choses comme la navigation sur le Web et le test de logiciels.

Utilisez un ordinateur hors ligne pour les choses importantes et un ordinateur en ligne pour toutes les autres choses.

Cependant, à tous ceux qui ne sont pas un enseignant paranoïaque (ne voulez offenser personne, je suis juste d'avis que vous devriez apprendre les bases de la sécurité et de notre société avant de commencer à être un enseignant de programmeurs ...)

... où étais-je ... pour tout le monde:

bon piratage !!

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.