115 votes

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

Je me demandais s'il existe un moyen d'exécuter un programme C non fiable dans une sandbox sous Linux. Quelque chose qui empêcherait le programme d'ouvrir des fichiers, ou des connexions réseau, ou de bifurquer, d'exécuter, etc ?

Il s'agirait d'un petit programme, d'un devoir à domicile, qui serait téléchargé sur un serveur et sur lequel des tests unitaires seraient exécutés. Le programme serait donc de courte durée.

0 votes

S'agit-il d'un programme C unique que vous devez exécuter une fois pendant 5 minutes, ou de quelque chose que vous devez exécuter constamment ?

0 votes

Il s'agirait d'un petit programme qui serait téléchargé et sur lequel des tests unitaires seraient exécutés. Le programme serait donc de courte durée.

0 votes

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

48voto

thkala Points 36148

J'ai utilisé Systrace pour mettre en bac à sable les programmes non fiables, à la fois de manière interactive et en mode automatique. Il dispose d'un ptrace() -based backend qui permet son utilisation sur un système Linux sans privilèges spéciaux, ainsi qu'un backend beaucoup plus rapide et puissant qui nécessite Parcheando le noyau.

Il est également possible de créer une sandbox sur les systèmes Unix-like en utilisant chroot(1) bien que cela ne soit pas aussi facile ou sûr. Conteneurs Linux y Les prisons FreeBSD sont une meilleure alternative à chroot. Une autre alternative sous Linux est d'utiliser un framework de sécurité comme SELinux o AppArmor C'est ce que je propose pour les systèmes de production.

Nous pourrions vous aider davantage si vous nous disiez exactement ce que vous voulez faire.

EDITAR:

Systrace fonctionnerait pour votre cas, mais je pense que quelque chose basé sur la 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.

EDIT 2 :

Alors que chroot(1) est disponible sur la plupart (tous ?) des systèmes de type Unix, il présente quelques problèmes :

  • On peut s'en défaire. Si vous compilez ou exécutez des programmes C non fiables sur votre système, vous êtes particulièrement vulnérable à ce problème. Et si vos étudiants sont comme les miens, quelqu'un va essayer de s'échapper de la prison.

  • Vous devez créer une hiérarchie complète de systèmes de fichiers indépendants avec tout ce qui est nécessaire à votre tâche. Il n'est pas nécessaire 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 y ait des utilitaires qui aident à cela, ce n'est toujours pas trivial.

  • Vous devez maintenir le chroot. Comme il est indépendant, les fichiers du chroot ne seront pas mis à jour en même temps que 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 maintenir les données système et utilisateur (mots de passe, fichiers d'entrée, etc.) synchronisées avec le système hôte.

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

Le problème de l'utilisation des ressources est commun à toutes les alternatives. Quotas de systèmes de fichiers empêchera les programmes de remplir le disque. Correctement ulimit ( setrlimit() en C) peuvent protéger contre la surutilisation de la mémoire et les bombes à bifurcation, ainsi que mettre un terme aux monopolisations du processeur. nice(1) peut diminuer la priorité de ces programmes afin que l'ordinateur puisse être utilisé sans problème pour toute tâche jugée plus importante.

0 votes

Systrace a fonctionné pour moi pour des programmes simples, mais est resté bloqué indéfiniment lorsque GNU as(1) est exécuté par GCC. J'ai donc abandonné. C'est un bogue non corrigé dans systrace : forum.soft32.com/linux/

0 votes

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

1 votes

Le lien systrace est cassé.

18voto

Justin Cormack Points 475

J'ai écrit un aperçu des techniques de sandboxing sous Linux récemment. Je pense que l'approche la plus simple serait d'utiliser des conteneurs Linux (lxc) si vous ne vous souciez pas de la bifurcation et ainsi de suite, qui n'ont pas vraiment d'importance dans cet environnement. Vous pouvez donner au processus un système de fichiers Root en lecture seule, une connexion réseau loopback 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 la mémoire.

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

6voto

Thomas M. DuBuisson Points 31851

Eh bien, si la recherche sur le NaCl se poursuit correctement, vous devriez pouvoir télécharger un compilateur client natif (c'est-à-dire un LLVM modifié), compiler toutes les affectations avec ce compilateur et les exécuter.

Pour l'instant, je vous suggère d'utiliser seccomp - consultez la page de manuel de prctl . A priori, cela empêche votre processus de faire autre chose que d'opérer sur les poignées déjà ouvertes.

5voto

pts Points 15396

Essayez Linux en mode utilisateur . Il présente un surcoût de performance d'environ 1 % pour les tâches exigeantes en termes de CPU, mais il peut être 6 fois plus lent pour les tâches exigeantes en termes d'E/S.

3voto

Laurent Parenteau Points 1686

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

QEMU serait une bonne solution 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 sauvegarde de la sortie pour une récupération ultérieure) pourrait être scripté pour des tests automatisés.

2 votes

Je ne sais pas pour le PO, mais lancer une VM par programme de test serait inacceptable dans de nombreux cas. Dans mon environnement (je suis un TA), il peut y avoir jusqu'à 200 étudiants qui soumettent 10-12 programmes chacun dans une période de 2 heures. Aucun programme ne fonctionne pendant plus de 10 secondes de temps CPU, mais lorsque les soumissions s'accumulent, nous obtenons des temps d'exécution de 15 minutes ou plus. L'introduction d'une VM pour chaque programme ferait passer 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 pas moyen de faire ça par programme...

0 votes

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

0 votes

Dans ce cas, gardez la même VM en permanence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X