Est-il possible d'ajuster un paramètre de noyau pour permettre à un programme utilisateur de se lier au port 80 et 443?
La raison pour laquelle je pose cette question est qu’il est idiot de permettre à un processus privilégié d’ouvrir un socket et d’écouter. Tout ce qui ouvre un socket et écoute présente un risque élevé, et les applications à haut risque ne doivent pas être exécutées en tant que root.
Je préférerais de beaucoup essayer de déterminer quel processus non privilégié écoute sur le port 80 plutôt que d'essayer de supprimer les logiciels malveillants qui s'y enfoncent avec des privilèges root.
Réponses:
Je ne suis pas sûr de ce que les autres réponses et commentaires ici font référence. C'est possible assez facilement. Il existe deux options, toutes deux permettant l’accès à des ports peu nombreux sans avoir à élever le processus à la racine:
Option 1: utilisation
CAP_NET_BIND_SERVICE
pour accorder l'accès à un processus à un port de petit numéro:Avec cela, vous pouvez accorder un accès permanent à un binaire spécifique pour vous lier à des ports de faible numéro via le
setcap
commander:Pour plus de détails sur la partie e / i / p, voir
cap_from_text
.Après cela,
/path/to/binary
sera en mesure de se lier à des ports peu numérotés. Notez que vous devez utilisersetcap
sur le binaire lui-même plutôt qu'un lien symbolique.Option 2: utilisation
authbind
pour accorder un accès unique, avec un contrôle utilisateur / groupe / port plus précis:le
authbind
( page de manuel ) outil existe précisément pour cela.Installer
authbind
en utilisant votre gestionnaire de paquets préféré.Configurez-le pour accorder l'accès aux ports appropriés, par exemple. pour autoriser 80 et 443 de tous les utilisateurs et groupes:
Maintenant, exécutez votre commande via
authbind
(en spécifiant éventuellement--deep
ou d’autres arguments, voir la page de manuel):Par exemple.
Il y a des avantages et des inconvénients à ces deux aspects. L’option 1 accorde la confiance au binaire mais ne fournit aucun contrôle sur l'accès par port. L’option 2 donne confiance aux utilisateur / groupe et permet de contrôler l'accès par port, mais AFAIK ne prend en charge que IPv4.
la source
setcap
permission sur le Ruby exécutable spécifique à la version , par exemple./usr/bin/ruby1.9.1
chmod
777 labyport
fichiers est la meilleure idée. J'ai vu donner des autorisations allant de500
à744
. Je resterais sur le plus restrictif qui fonctionne pour vous.Dale Hagglund est sur place. Je vais donc simplement dire la même chose, mais d'une manière différente, avec des détails et des exemples. ☺
La bonne chose à faire dans les mondes Unix et Linux est la suivante:
Vous avez une mauvaise idée de l'endroit où le risque est élevé. Le risque élevé est en lire sur le réseau et agir sur ce qui est lu pas dans les simples gestes d'ouvrir un socket, de le lier à un port et d'appeler
listen()
. C'est la partie d'un service qui fait la communication réelle qui est le risque élevé. Les parties qui s'ouvrent,bind()
, etlisten()
et même (dans une certaine mesure) la partieaccepts()
, ne sont pas à haut risque et peuvent être exécutés sous l’égide du superutilisateur. Ils n'utilisent pas et n'agissent pas (à l'exception des adresses IP source dans leaccept()
cas) des données sous le contrôle d’étrangers non fiables sur le réseau.Il y a plusieurs façons de le faire.
inetd
Comme le dit Dale Hagglund, l'ancien "super serveur"
inetd
est ce que ca. Le compte sous lequel le processus de service est exécuté est l’une des colonnes deinetd.conf
. Il ne sépare pas la partie écoute et la partie suppression des privilèges en deux programmes distincts, petits et faciles à auditer, mais il sépare le code de service principal en un programme séparé.exec()
ed dans un processus de service qu’il génère avec un descripteur de fichier ouvert pour le socket.La difficulté de l'audit n'est pas un problème, il suffit de vérifier le programme en question.
inetd
Le principal problème de l'audit n'est pas tant l'audit, mais plutôt le fait qu'il ne fournit pas un contrôle de service d'exécution à granularité fine, comparé aux outils plus récents.UCSPI-TCP et daemontools
De Daniel J. Bernstein UCSPI-TCP et Daemon Tools les paquets ont été conçus pour le faire en conjonction. On peut également utiliser l'équivalent de Bruce Guenter daemontools-encore ensemble d'outils.
Le programme pour ouvrir le descripteur de fichier de socket et le lier au port local privilégié est
tcpserver
, de UCSPI-TCP. Il fait les deuxlisten()
et leaccept()
.tcpserver
puis génère un programme de service qui supprime lui-même les privilèges root (car le protocole utilisé implique de démarrer en tant que superutilisateur puis de se "connecter", comme dans le cas, par exemple, d'un démon FTP ou SSH) ousetuidgid
qui est un petit programme autonome facilement vérifiable qui abandonne uniquement les privilèges, puis enchaîne les charges vers le programme de service proprement dit (aucune partie de celui-ci ne s'exécute donc avec des privilèges de superutilisateur, comme c'est le cas avec, par exemple,qmail-smtpd
).Un service
run
script serait donc par exemple (celui-ci pour dummyidentd pour fournir un service nul IDENT):bouffe
Mon paquet est conçu pour le faire. Il a un petit
setuidgid
utilité, tout comme les autres. Une légère différence est qu’il est utilisable avecsystemd
style "LISTEN_FDS" ainsi qu’avec les services UCSPI-TCP, donc le traditionneltcpserver
programme est remplacé par deux programmes distincts:tcp-socket-listen
ettcp-socket-accept
.Encore une fois, les utilitaires à but unique apparaissent et se chargent en chaîne. Une particularité intéressante de la conception est que l'on peut supprimer les privilèges de superutilisateur après
listen()
mais avant mêmeaccept()
. Voici unrun
script pourqmail-smtpd
cela fait en effet exactement cela:Les programmes exécutés sous l’égide du superutilisateur sont les petits outils de chargement en chaîne indépendants du service.
fdmove
,clearenv
,envdir
,softlimit
,tcp-socket-listen
, etsetuidgid
. Au point quesh
est démarré, le socket est ouvert et lié ausmtp
port, et le processus ne dispose plus des privilèges de superutilisateur.s6, s6-networking et execline
De Laurent Bercot s6 et s6-mise en réseau les paquets ont été conçus pour le faire en conjonction. Les commandes sont structurellement très similaires à celles de
daemontools
et UCSPI-TCP.run
scripts seraient sensiblement les mêmes, sauf pour la substitution des6-tcpserver
pourtcpserver
ets6-setuidgid
poursetuidgid
. Cependant, on pourrait aussi choisir de faire usage de la méthode de M. Bercot. execline ensemble d'outils en même temps.Voici un exemple de service FTP légèrement modifié à partir de L'original de Wayne Marshall , qui utilise execline, s6, s6-networking et le programme de serveur FTP de publicfile :
ipsvd
Gerrit Pape ipsvd C’est un autre ensemble d’outils qui va dans le même sens que ucspi-tcp et s6-networking. Les outils sont
chpst
ettcpsvd
cette fois-ci, mais ils font la même chose, et le code à haut risque qui lit, traite et écrit les choses envoyées sur le réseau par des clients non fiables fait toujours l’objet d’un programme séparé.Voici L'exemple de M. Pape de courir
fnord
dans unrun
scénario:systemd
systemd
, le nouveau système de supervision de service et init que l'on retrouve dans certaines distributions Linux est destiné à faire quoiinetd
peut faire . Cependant, il n’utilise pas une suite de petits programmes autonomes. Il faut auditersystemd
dans son intégralité, malheureusement.Avec
systemd
on crée des fichiers de configuration pour définir un socket quisystemd
écoute, et un service quisystemd
départs. Le fichier "unité" de service contient des paramètres qui permettent de contrôler le processus de service, y compris son utilisateur.Avec cet utilisateur défini pour être un non-superutilisateur,
systemd
effectue tout le travail consistant à ouvrir le socket, à le lier à un port et à appelerlisten()
(et, si nécessaire,accept()
) dans le processus n ° 1 en tant que superutilisateur, et le processus de service qu'il génère est exécuté sans privilèges de superutilisateur.la source
CAP_NET_BIND_SERVICE
etauthbind
les deux existent à cet effet; pour permettre aux applications non root d’accéder aux ports dont le numéro est bas.Votre instinct est tout à fait correct: c’est une mauvaise idée d’avoir un grand programme complexe exécuté en tant que root, car leur complexité les rend difficiles à faire confiance.
Cependant, il est également déconseillé de permettre aux utilisateurs normaux de se connecter à des ports privilégiés, car ils représentent généralement des services système importants.
L’approche standard pour résoudre cette contradiction apparente est séparation de privilège . L'idée de base est de séparer votre programme en deux parties (ou plus), chacune d'entre elles constituant une partie bien définie de l'application globale et communiquant par le biais d'interfaces limitées.
Dans l'exemple que vous donnez, vous voulez séparer votre programme en deux parties. Celui qui s'exécute en tant que root s'ouvre et se connecte au socket privilégié, puis le transfère d'une manière ou d'une autre à l'autre partie, qui s'exécute en tant qu'utilisateur normal.
Ces deux moyens principaux pour réaliser cette séparation.
Un seul programme qui commence en tant que root. La première chose à faire est de créer le socket nécessaire, de la manière la plus simple et la plus limitée possible. Ensuite, il supprime les privilèges, c’est-à-dire qu’il se convertit en un processus normal en mode utilisateur et effectue tout autre travail. Il est difficile de supprimer des privilèges correctement. Veuillez donc prendre le temps d’étudier la meilleure façon de le faire.
Une paire de programmes qui communiquent via une paire de sockets créée par un processus parent. Un programme de pilote non privilégié reçoit les arguments initiaux et effectue peut-être une validation de base des arguments. Il crée une paire de sockets connectés via socketpair (), puis lance et exécute deux autres programmes qui feront le vrai travail et communiqueront via la paire de sockets. L'une d'elles est privilégiée et créera le socket du serveur, ainsi que toute autre opération privilégiée, et l'autre effectuera l'exécution d'application la plus complexe et donc la moins digne de confiance.
[1] http://en.m.wikipedia.org/wiki/Privilege_separation
la source
J'ai une approche assez différente. Je voulais utiliser le port 80 pour un serveur node.js. Je n'ai pas pu le faire car Node.js a été installé pour un utilisateur autre que sudo. J'ai essayé d'utiliser des liens symboliques, mais cela n'a pas fonctionné pour moi.
Ensuite, j'ai appris que je pouvais transférer les connexions d'un port à un autre. J'ai donc démarré le serveur sur le port 3000 et configuré un transfert de port du port 80 au port 3000.
Ce lien fournit les commandes qui peuvent être utilisées pour cela. Voici les commandes -
J'ai utilisé la deuxième commande et cela a fonctionné pour moi. Je pense donc que c'est un moyen terme pour ne pas autoriser les processus utilisateur à accéder directement aux ports inférieurs, mais leur permettre d'accéder via le transfert de port.
la source