web-dev-qa-db-fra.com

Est-il sûr de permettre à www-data d'exécuter des commandes privilégiées?

J'ai remarqué plusieurs questions sur Stack Overflow, comme this one, sur l'exécution de commandes avec des privilèges root en utilisant PHP. La réponse a proposé d'ajouter la ligne

www-data ALL=(ALL) NOPASSWD: ALL

à la /etc/sudoers.d fichier.

Est-ce une approche sûre pour résoudre le problème? Cela crée-t-il une vulnérabilité?

25
UserK

C'est ... atroce. Le point entier d'exécuter des choses Web en tant qu'utilisateur non root est la limitation des dommages: au cas où le processus du serveur Web serait détourné par une vulnérabilité, au moins l'attaquant ne le fera pas obtenir le contrôle total de la machine, car il sera contraint par les limitations du compte non root www-data. Mais si vous donnez www-data un moyen d'exécuter toutes les commandes qu'il souhaite, avec les droits de tout utilisateur (y compris root), et sans autre authentification, alors vous venez de perdre cette fonctionnalité de limitation des dommages.

Être juste, www-data + Sudo est un peu mieux que de simplement tout exécuter en tant que root, car le passage à la racine doit être explicite; par conséquent, des failles communes comme un script PHP écrivant des fichiers dans des emplacements incorrects seraient plus difficiles à exploiter. Mais tout de même, rendre www-data un membre des sudoers ressemble à une mauvaise idée.

83
Tom Leek

Lorsque vous envisagez la sécurité d'un élément, vous devez supposer que l'attaquant peut se connecter en tant qu'utilisateur www-data et avoir un shell. Cela ne signifie pas que votre attaquant peut vraiment obtenir un Shell, mais il peut y avoir de nombreuses façons dont l'attaquant peut exécuter des commandes Shell arbitraires; il peut s'agir de bogues de bibliothèque comme Shellshock ou d'oubli dans votre code.

Le moyen le plus sûr

La meilleure façon de le faire est, comme l'a dit @AlexeyVesnin, d'utiliser un processus spécialisé pour effectuer le travail. Demandez à ce processus d'écouter sur un socket (domaine Unix, donc il n'est pas accessible depuis le réseau), de lire son entrée à partir dudit socket, de nettoyer l'entrée (!), De faire le travail et de renvoyer un résultat au socket, d'où le script du serveur Web lit les résultats. Toute autorisation (l'utilisateur doit entrer un mot de passe sur le site Web pour être autorisé à le faire) doit être traitée dans ce processus, et l'utilisateur www-data ne doit pas être en mesure de lire aucune de ces données d'autorisation.

La façon la plus sûre de Sudo

Dans le cas où votre budget ou vos compétences ne rendent pas possible cette meilleure approche, l'utilisation de l'approche Sudo n'est pas complètement fausse, mais vous devez limiter les autorisations Sudo au minimum dont vous avez réellement besoin. Par exemple, supposons que vous souhaitiez afficher les données d'E/S disque actuelles sur votre site Web, pour lesquelles vous devez appeler iotop:

  • faire un script, dans cet exemple /var/www/bin/get-disk-io, qui extrait les données dont vous avez besoin:

    /usr/sbin/iotop -b -n 1 | /usr/bin/head -2

  • Ne laissez pas l'appelant du script passer des paramètres, c'est-à-dire que le script ne doit pas accéder à $1, $2, ..., $*, $@
  • Si vous devez absolument utiliser des paramètres, désinfectez-les d'abord dans votre script. Faites particulièrement attention aux espaces blancs ou à tout caractère inhabituel qui pourrait être masqué dans les paramètres.
  • Assurez-vous d'indiquer le chemin d'accès complet à chaque commande de ce script, afin que les attaquants ne puissent remplacer aucune de ces commandes par la leur
  • Autoriser l'accès à ce script, et uniquement ce script, dans /etc/sudoers
  • Assure-toi env_reset est dans la politique par défaut de votre fichier sudoers

Notez que cela est toujours plus sûr qu'un programme suid, car (a) vous pouvez restreindre qui peut l'exécuter, donc un attaquant qui gagne la possibilité d'exécuter un programme sous un autre utilisateur ne pourra pas l'utiliser, (b) vous ne pouvez pas lui passer de paramètres arbitraires, (c) l'environnement est assaini par Sudo, et (d) vous pouvez créer un journal Sudo lorsque la commande est exécutée, vous avez donc une piste d'audit qu'un programme suid ne vous donne pas.

La manière suid

Remarque: ne faites pas cela à moins que vous ne sachiez ce que vous faites. Si vous posez ou lisez cette question sur stackexchange, vous ne le faites probablement pas. Ne faites donc pas cela.

Si vous définissez le propriétaire d'un exécutable sur un certain utilisateur (chown user /my/executable/file), puis définissez le bit suid (chmod u+s /my/executable/file), ce programme s'exécutera sous les autorisations de cet utilisateur à chaque exécution. Ainsi, par exemple, chown root /bin/cat; chmod u+s /bin/cat exécutera chaque appel de cat avec les droits root, ce qui signifie que vous pouvez lire chaque fichier sur le système indépendamment de ses droits d'accès. N'essayez pas ceci sur un système qui est connecté à un réseau, pas même pendant 5 minutes pour "vérifier si cela fonctionne".

  • Sur de nombreux systèmes Unix, cela ne fonctionne que pour les programmes compilés, pas pour les scripts qui ont besoin d'un interprète
  • Dans certaines configurations, par exemple si vous exécutez le programme sous strace, le bit s n'a aucun effet
  • Dans les configurations NFS, root n'a souvent pas accès aux fichiers sur le serveur NFS, ce qui peut même réduire ce que vous pouvez faire.

La manière restreinte-suid-Linux

Linux a un système de capacités, qui fonctionne presque comme suid, mais avec une granularité beaucoup plus fine. Par exemple, si vous avez besoin d'un processus pour pouvoir utiliser des numéros de port inférieurs à 1024, dans les systèmes Unix classiques, vous devez exécuter la commande en tant que root, ce qui signifie souvent que vous devez faire ce qui précède chown/chmod u+s stuff, qui permet d'utiliser ces numéros de port, mais accorde également l'accès au système de fichiers. Linux vous permet de donner la capacité du port sans tout ce qui vient avec root:

setcap cap_net_bind_service+EP /path/to/my/program

Faire man 7 capabilities pour apprendre plus. Si vous envisagez sérieusement de donner du suid à un programme, réfléchissez bien si la définition d'une capacité n'est pas une meilleure idée.

Every fois, sans exception, lorsque vous voyez ALL=(ALL) NOPASSWD: ALL dans le /etc/sudoers fichier, quelqu'un mérite d'être viré. Fondamentalement, vous avez un deuxième utilisateur root.

Est-ce sûr? Sûrement pas. Cela crée-t-il une vulnérabilité? Putain, oui.

Vous pouvez utiliser Sudo pour accorder en toute sécurité à un utilisateur non root (y compris www-data) une exécution privilégiée, mais cela doit toujours être aussi précis que possible. Si vous devez exécuter /usr/bin/my_system_tool +x /var/cache/my_cache en tant que root pour quelque raison que ce soit, cette commande exacte, y compris les paramètres doit être dans le /etc/sudoers fichier.

5
Tom