Question

Une application veut analyser et « exécuter » un fichier, et veut affirmer que le fichier est exécutable pour des raisons de sécurité.

A des moments de pensée et vous réalisez ce code initial a une condition qui rend le régime de sécurité inefficace:

import os

class ExecutionError (Exception):
    pass

def execute_file(filepath):
    """Execute serialized command inside @filepath

    The file must be executable (comparable to a shell script)
    >>> execute_file(__file__)  # doctest: +ELLIPSIS
    Traceback (most recent call last):
        ...
    ExecutionError: ... (not executable)
    """
    if not os.path.exists(filepath):
        raise IOError('"%s" does not exist' % (filepath, ))
    if not os.access(filepath, os.X_OK):
        raise ExecutionError('No permission to run "%s" (not executable)' %
                filepath)

    data = open(filepath).read()

    print '"Dummy execute"'
    print data

La condition de course existe entre

os.access(filepath, os.X_OK)

et

data = open(filepath).read()

Comme il est possible du fichier en cours avec un fichier écrasé non exécutable de contenu différent entre ces deux appels système.

La première solution que j'ai est de changer l'ordre des appels critiques (et ignorer la vérification de l'existance maintenant redondant):

fobj = open(filepath, "rb")
if not os.access(filepath, os.X_OK):
    raise ExecutionError('No permission to run "%s" (not executable)' %
            filepath)

data = fobj.read()

Est-ce que résoudre la condition de la course? Comment puis-je résoudre correctement?

justification du système de sécurité, brièvement (je pensais)

Le fichier sera en mesure d'exécuter des commandes arbitraires à l'intérieur de son environnement, il est donc comparable à un script shell.

Il y avait un trou de sécurité sur les ordinateurs de bureau gratuits avec des fichiers .desktop qui définissent Applications: Le fichier peut spécifier un exécutable avec des arguments, et il peut choisir son propre icône et le nom. Ainsi, un fichier téléchargé au hasard pouvait cacher derrière un nom ou d'une icône et faire quoi que ce soit. C'était mauvais.

Cela a été résolu en exigeant que les fichiers .desktop ont le bit exécutable ensemble, sinon ils ne seront pas rendus avec le nom / icône et le bureau libre demande à l'utilisateur si elle veut lancer le programme avant de commencer.

Comparez cela à Mac OS X de très bonne conception: « Ce programme a été téléchargé à partir du Web, êtes-vous sûr de vouloir l'ouvrir? ».

Ainsi, dans l'allégorie avec cela, et le fait que vous avez à chmod +x shell scripts que vous téléchargez, je pensais à la conception dans la question ci-dessus.

Fermeture des mots

Peut-être en guise de conclusion, peut-être que nous devrions garder les choses simples: si le fichier doit être exécutable, rendre exécutable et laissez le noyau l'exécuter lorsqu'il est appelé par l'utilisateur. Délégation de la tâche à laquelle il appartient.

Était-ce utile?

La solution

Le exécutabilité est attaché au fichier que vous ouvrez, il n'y a rien qui empêche plusieurs fichiers de pointant vers le inode contenant les données que vous souhaitez lire. En d'autres termes, les mêmes données peuvent être lues à partir d'un fichier non exécutable ailleurs dans le même système de fichiers. De plus, même après l'ouverture du fichier, vous ne pouvez pas empêcher le caractère exécutable ce même fichier de changer, il pourrait même être dissociées.

Le « meilleur effort » disponible pour vous que je vois que ce serait faire des vérifications à l'aide os.fstat sur le fichier ouvert, et vérifier le mode de protection et le temps de modification avant et après, mais au mieux cela ne réduira la possibilité que les changements passent inaperçues pendant que vous lisez le fichier.

A la réflexion, si vous êtes le créateur original des données dans ce fichier, vous pouvez envisager d'écrire un inode qui n'a jamais lié au système de fichiers en premier lieu, cette technique commune dans le partage de la mémoire via des fichiers. Par ailleurs, si les données contenues doivent éventuellement rendues publiques à d'autres utilisateurs, vous pouvez utiliser le verrouillage de fichier, puis étendre progressivement les bits de protection aux utilisateurs qui en ont besoin.

En fin de compte, vous devez vous assurer que les utilisateurs malveillants n'ont tout simplement pas accès en écriture au fichier.

Autres conseils

Vous ne pouvez pas tout à fait résoudre cette condition de course - par exemple, dans la version où vous ouvrez d'abord, puis vérifier les autorisations, il est possible que les autorisations sont changés juste après avoir ouvert le fichier et juste avant d'avoir modifié les autorisations.

Si vous pouvez déplacer le fichier atomiquement dans un répertoire où les gars potentiels mauvais ne peuvent pas atteindre, alors vous pouvez être sûr que rien sur le fichier sera changé sous votre nez pendant que vous faites affaire avec elle. Si les gars potentiels mauvais peuvent atteindre partout , ou vous ne pouvez pas déplacer le fichier à l'endroit où ils ne peuvent pas atteindre, il n'y a pas de défense.

BTW, ce n'est pas clair pour moi comment ce système, même si elle pourrait être de travailler, serait en fait ajouter toute sécurité - sûrement si les méchants peuvent mettre du contenu empoisonné dans le fichier, il est pas au-delà de chmod +x comme bien?

Le mieux que vous pouvez faire est:

  • enregistrer l'autorisation.
  • changer à votre propre utilisateur unique (quelque chose avec le nom du programme) et interdire les autres de l'exécuter.
  • vous faire des contrôles (sur l'autorisation enregistrée en cas de besoin).
  • exécuter votre processus.
  • retrait l'autorisation de ceux qui sont sauvés.

Bien sûr, il y a des inconvénients, mais si votre cas d'utilisation est aussi simple que vous semblez dire, il pourrait faire l'affaire.

Vous devez modifier la propriété des fichiers tels qu'un attaquant ne peut pas y accéder « chown root: nom_fichier racine ». Faites un « chmod 700 nom_fichier » de sorte qu'aucun autre comptes peut lire / écrire / exécuter le fichier. Cela évite le problème d'un TOCTOU tous ensemble et voilà comment les gens empêchent les fichiers d'être modifié par un attaquant qui a un compte d'utilisateur sur votre système.

Une autre façon de le faire est de changer le nom du fichier à quelque chose d'inattendu, ou même copier le fichier entier - si ce n'est pas trop grand - un répertoire temporaire (crypté si nécessaire), vous faire des contrôles, puis renommer / copier le fichier retour.

Bien sûr, il est un processus très lourd.

Mais vous vous retrouvez avec cela parce que le système n'a pas été fixé pour la sécurité depuis le début. Un programme sûr signerait ou crypter les données qu'il veut garder en sécurité. Dans votre cas, il est impossible.

À moins que vous sur le cryptage lourd realy, il n'y a pas moyen d'assurer la sécurité 100 sur une machine que vous ne contrôlez pas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top