Je voudrais qu'un programme Python commence à écouter sur le port 80, mais après cela, exécute sans autorisations root. Existe-t-il un moyen de supprimer root ou d'obtenir le port 80 sans lui?Suppression des autorisations root en Python
Répondre
Vous ne serez pas en mesure d'ouvrir un serveur sur le port 80 sans privilèges root, ceci est une restriction au niveau du système d'exploitation. La seule solution est donc de supprimer les privilèges root après avoir ouvert le port.
Voici une solution possible pour supprimer les privilèges root en Python: Dropping privileges in Python. C'est une bonne solution en général, mais vous devrez également ajouter os.setgroups([])
à la fonction pour vous assurer que l'appartenance au groupe de l'utilisateur root n'est pas conservée. J'ai copié et nettoyé le code un petit peu, et supprimé la journalisation et les gestionnaires d'exceptions, il est donc laissé à vous de gérer correctement OSError
(il sera levé lorsque le processus n'est pas autorisé à changer son UID effectif ou GID):
import os, pwd, grp
def drop_privileges(uid_name='nobody', gid_name='nogroup'):
if os.getuid() != 0:
# We're not root so, like, whatever dude
return
# Get the uid/gid from the name
running_uid = pwd.getpwnam(uid_name).pw_uid
running_gid = grp.getgrnam(gid_name).gr_gid
# Remove group privileges
os.setgroups([])
# Try setting the new uid/gid
os.setgid(running_gid)
os.setuid(running_uid)
# Ensure a very conservative umask
old_umask = os.umask(077)
Gardez à l'esprit que le répertoire HOME sera toujours '/ root' et non '/ home/uid_name', et que uid_name ne pourra rien faire avec' ~/', qui sera ensuite développé en'/root/'. Cela peut affecter des modules comme matplotlib qui stockent des données de configuration dans le répertoire HOME. 'authbind' semble être la bonne façon de gérer ce problème. –
Et la variable HOME ne sera pas la seule à penser que l'utilisateur actuel est root. –
* "Vous ne serez pas en mesure d'ouvrir un serveur sur le port 80 sans privilèges root ..." * - Ce n'est pas nécessairement vrai (peut-être plus?). Voir aussi [Autoriser le processus non root à se lier aux ports 80 et 443?] (Https://superuser.com/q/710253/173513) sur SuperUser et [Existe-t-il un moyen pour les processus non root de se lier à "privilégié"? "Ports sur Linux?] (Https://stackoverflow.com/q/413807/608639) – jww
Je recommande d'utiliser authbind
pour démarrer votre programme Python, donc rien ne doit fonctionner en tant que root.
Un exemple d'utilisation de' authbind' - http://goo.gl/fxFde6 - Remplacez NodeJS par ce que vous voulez (ex : python) – starlocke
systemd peut le faire pour vous, si vous commencez votre programme par systemd, systemd peut remettre de la prise d'écoute déjà ouverte à lui, et il peut également activer votre programme sur la première connexion . et vous n'avez même pas besoin de le démoniser. Si vous souhaitez utiliser l'approche autonome, vous avez besoin de la fonction CAP_NET_BIND_SERVICE (consultez la page man de capabilities). Cela peut être fait programme par programme avec l'outil de ligne de commande correct, ou en faisant votre application (1) être suid root (2) démarrer (3) écouter le port (4) abandonner les privilèges/capacités immédiatement .
Rappelez-vous que les programmes suid root viennent avec beaucoup de considérations de sécurité (environnement propre et sûr, umask, privilèges, rlimits, toutes ces choses sont des choses que votre programme va devoir mettre en place correctement). Si vous pouvez utiliser quelque chose comme systemd, tant mieux.
La plupart de cette fonctionnalité fonctionne à moins que vous ne deviez demander le socket après avoir fait d'autres tâches que vous ne voulez pas être super-utilisateur.
J'ai fait un projet appelé tradesocket il y a quelque temps. Il vous permet de passer des sockets d'avant en arrière sur un système Posix entre les processus. Ce que je fais est de faire tourner un processus au début qui reste super-utilisateur, et le reste du processus descend dans les autorisations, puis demande le socket de l'autre.
Ce n'est pas une bonne idée de demander à l'utilisateur d'entrer son nom d'utilisateur et son groupe chaque fois que j'ai besoin de supprimer des privilèges. Voici une version légèrement modifiée du code de Tamás qui supprimera les privilèges et passera à l'utilisateur qui a initié la commande sudo. Je suppose que vous utilisez sudo (sinon, utilisez le code de Tamás).
#!/usr/bin/env python3
import os, pwd, grp
#Throws OSError exception (it will be thrown when the process is not allowed
#to switch its effective UID or GID):
def drop_privileges():
if os.getuid() != 0:
# We're not root so, like, whatever dude
return
# Get the uid/gid from the name
user_name = os.getenv("SUDO_USER")
pwnam = pwd.getpwnam(user_name)
# Remove group privileges
os.setgroups([])
# Try setting the new uid/gid
os.setgid(pwnam.pw_gid)
os.setuid(pwnam.pw_uid)
#Ensure a reasonable umask
old_umask = os.umask(0o22)
#Test by running...
#./drop_privileges
#sudo ./drop_privileges
if __name__ == '__main__':
print(os.getresuid())
drop_privileges()
print(os.getresuid())
Voici une nouvelle adaptation de Tamás's answer, avec les modifications suivantes:
- Utilisez le
python-prctl
module d'abandonner les capacités Linux à une liste des capacités pour préserver. - L'utilisateur peut éventuellement être passé en paramètre (il recherche par défaut l'utilisateur qui a exécuté
sudo
). - Il définit tous les groupes d'utilisateurs et .
- Il change éventuellement de répertoire.
(je suis relativement nouveau d'utiliser cette fonctionnalité, cependant, donc je peut-être manqué quelque chose. Il ne fonctionne pas sur les anciens noyaux (< 3.8) ou des noyaux avec des capacités de systèmes de fichiers désactivés.)
def drop_privileges(user=None, rundir=None, caps=None):
import os
import pwd
if caps:
import prctl
if os.getuid() != 0:
# We're not root
raise PermissionError('Run with sudo or as root user')
if user is None:
user = os.getenv('SUDO_USER')
if user is None:
raise ValueError('Username not specified')
if rundir is None:
rundir = os.getcwd()
# Get the uid/gid from the name
pwnam = pwd.getpwnam(user)
if caps:
prctl.securebits.keep_caps=True
prctl.securebits.no_setuid_fixup=True
# Set user's group privileges
os.setgroups(os.getgrouplist(pwnam.pw_name, pwnam.pw_gid))
# Try setting the new uid/gid
os.setgid(pwnam.pw_gid)
os.setuid(pwnam.pw_uid)
os.environ['HOME'] = pwnam.pw_dir
os.chdir(os.path.expanduser(rundir))
if caps:
prctl.capbset.limit(*caps)
try:
prctl.cap_permitted.limit(*caps)
except PermissionError:
pass
prctl.cap_effective.limit(*caps)
#Ensure a reasonable umask
old_umask = os.umask(0o22)
Il peut être utilisé comme suit:
drop_privileges(user='www', rundir='~', caps=[prctl.CAP_NET_BIND_SERVICE])
- 1. Suppression des privilèges root
- 2. Authentification de l'application GTK pour exécuter des autorisations root
- 3. git ne parvient pas à ajouter des fichiers qui ont des autorisations root uniquement
- 4. Exécuter un projet Python dans Eclipse en tant que root
- 5. Suppression des caractères indésirables d'une chaîne en Python
- 6. Suppression des caractères non-ascii d'un type donné en Python
- 7. Suppression des barres obliques inverses d'une chaîne en Python
- 8. Python - Suppression des doublons d'une chaîne
- 9. python: suppression des valeurs d'une liste
- 10. Suppression de fichiers avec des scripts python
- 11. La suppression d'un répertoire en Python
- 12. Suppression d'erreur Python eval
- 13. Vérification des autorisations de fichiers sous Linux avec Python
- 14. Suppression de Python HTML
- 15. Comment gagner des privilèges root en python via un sudo graphique?
- 16. Mes autorisations sont-elles définies correctement? (python)
- 17. suppression des dossiers
- 18. Directory.CreateDirectory avec des autorisations
- 19. Facebook demande des autorisations javascript?
- 20. Modélisation visuelle des autorisations
- 21. Python: suppression d'une trame TKinter
- 22. Comment appliquer des autorisations
- 23. Suppression de mots non anglais d'une phrase en python
- 24. vérifier les permissions des répertoires en python
- 25. Python: la suppression des doublons dans une liste de listes
- 26. Les autorisations de fichier n'héritent pas des autorisations de répertoire
- 27. Coût des fonctions de liste en Python
- 28. Suppression des éléments de tableau en Python tout en gardant la trace de leur position
- 29. Suppression des balises html d'un texte en utilisant l'expression régulière en python
- 30. Autorisations Unix de Windows
http://stackoverflow.com/questions/413807/is-there-a-way-for-non-root-processes-to-bind-to-privileged -ports-1024-on-li –
Sur Linux moderne, vous n'avez besoin que de capacités CAP_NET_ BIND_SERVICE pour lier au port 80, vous n'avez pas besoin d'être root, même au démarrage de l'application. Les capacités sont un standard POSIX, 1003.1e, qui est un partitionnement du privilège racine tout puissant en un ensemble de privilèges distincts. Voir: python-cap-ng et/sbin/setcap,/sbin/getcap (ceux-ci sont équivalentes à chmod setuid et ls -l) –
Pour python2 et peut-être d'autres interprètes, acquérir des capacités est la partie que vous voulez faire attention avec - libcap-ng peut laisser tomber les majuscules mais il ne les accorde pas. Cette réponse à la question posée par Ian est un moyen relativement sûr de distribuer un chapeau à la fois pour des projets spécifiques: http://stackoverflow.com/a/21895123/1724577 – duanev