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é?
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.
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.
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.
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
$1
, $2
, ..., $*
, $@
/etc/sudoers
env_reset
est dans la politique par défaut de votre fichier sudoersNotez 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.
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".
strace
, le bit s
n'a aucun effetLinux 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.