¿Es posible ajustar un parámetro del kernel para permitir que un programa userland se una al puerto 80 y 443?
La razón por la que pregunto es que creo que es una tontería permitir que un proceso privilegiado abra un socket y escuche. Cualquier cosa que abra un socket y escuche es de alto riesgo, y las aplicaciones de alto riesgo no deberían ejecutarse como root.
Prefiero tratar de averiguar qué proceso no privilegiado está escuchando en el puerto 80 en lugar de tratar de eliminar el malware que se ha enterrado con privilegios de root.
Respuestas:
No estoy seguro de a qué se refieren las otras respuestas y comentarios aquí. Esto es posible con bastante facilidad. Hay dos opciones, ambas que permiten el acceso a puertos de bajo número sin tener que elevar el proceso a la raíz:
Opción 1: se utiliza
CAP_NET_BIND_SERVICE
para otorgar acceso de puerto de bajo número a un proceso:Con esto puede otorgar acceso permanente a un binario específico para enlazar a puertos de bajo número a través del
setcap
comando:Para obtener más detalles sobre la parte e / i / p, consulte
cap_from_text
.Después de hacer esto,
/path/to/binary
podrá vincularse a puertos de números bajos. Tenga en cuenta que debe usarsetcap
el binario en lugar de un enlace simbólico.Opción 2: use
authbind
para otorgar acceso de una sola vez, con un control más fino de usuario / grupo / puertoLa herramienta
authbind
( página de manual ) existe precisamente para esto.Instale
authbind
usando su administrador de paquetes favorito.Configúrelo para otorgar acceso a los puertos relevantes, por ejemplo, para permitir 80 y 443 de todos los usuarios y grupos:
Ahora ejecute su comando vía
authbind
(opcionalmente especificando--deep
u otros argumentos, vea la página del manual):P.ej
Hay ventajas y desventajas de los dos anteriores. La opción 1 otorga confianza al binario pero no proporciona control sobre el acceso por puerto. La opción 2 otorga confianza al usuario / grupo y proporciona control sobre el acceso por puerto pero, AFAIK, solo admite IPv4.
fuente
rwx
permiso?-p
intead of+eip
?setcap
permiso sobre el ejecutable ruby específico de la versión , por ejemplo/usr/bin/ruby1.9.1
chmod
usar 777byport
archivos sea la mejor idea. He visto dar permisos que van desde500
hasta744
. Me quedaría con el más restrictivo que funcione para ti.Dale Hagglund es perfecto. Así que voy a decir lo mismo pero de una manera diferente, con algunos detalles y ejemplos. ☺
Lo correcto en los mundos de Unix y Linux es:
Tienes una idea equivocada de dónde está el alto riesgo. El alto riesgo está en leer desde la red y actuar sobre lo que se lee, no en los simples actos de abrir un socket, vincularlo a un puerto y llamar
listen()
. La parte de un servicio que hace la comunicación real es el alto riesgo. Las partes que se abren,bind()
ylisten()
, e incluso (en una medida) la parte queaccepts()
, no son los de alto riesgo y se pueden ejecutar bajo los auspicios de la superusuario. No utilizan ni actúan sobre (a excepción de las direcciones IP de origen en elaccept()
caso) datos que están bajo el control de extraños no confiables a través de la red.Hay muchas maneras de hacer esto.
inetd
Como dice Dale Hagglund, el viejo "servidor de red"
inetd
hace esto. La cuenta bajo la cual se ejecuta el proceso de servicio es una de las columnas eninetd.conf
. No separa la parte de escucha y la parte de privilegios de caída en dos programas separados, pequeños y fácilmente auditables, pero separa el código de servicio principal en un programa separado,exec()
editado en un proceso de servicio que genera con un descriptor de archivo abierto para el zócaloLa dificultad de auditar no es un gran problema, ya que uno solo tiene que auditar un programa.
inetd
El principal problema no es auditar tanto, sino que no proporciona un control de servicio de tiempo de ejecución simple, en comparación con las herramientas más recientes.UCSPI-TCP y daemontools
Los paquetes UCSPI-TCP y daemontools de Daniel J. Bernstein fueron diseñados para hacer esto en conjunto. Alternativamente, se puede usar el conjunto de herramientas daemontools-encore en gran medida equivalente de Bruce Guenter .
El programa para abrir el descriptor del archivo de socket y enlazar al puerto local privilegiado es
tcpserver
, desde UCSPI-TCP. Hace tanto ellisten()
como elaccept()
.tcpserver
luego genera un programa de servicio que elimina los privilegios de raíz (porque el protocolo que se está sirviendo implica comenzar como superusuario y luego "iniciar sesión", como es el caso, por ejemplo, de un demonio FTP o SSH) osetuidgid
que es un programa autónomo pequeño y fácilmente auditable que solo elimina privilegios y luego encadena las cargas al programa de servicio propiamente dicho (ninguna parte se ejecuta con privilegios de superusuario, como es el caso, por ejemploqmail-smtpd
).Un
run
script de servicio sería, por ejemplo, (este para dummyidentd para proporcionar un servicio IDENT nulo):comida
Mi paquete nosh está diseñado para hacer esto. Tiene una pequeña
setuidgid
utilidad, al igual que las demás. Una ligera diferencia es que se puede usar con lossystemd
servicios "LISTEN_FDS" de estilo, así como con los servicios UCSPI-TCP, por lo que eltcpserver
programa tradicional se reemplaza por dos programas separados:tcp-socket-listen
ytcp-socket-accept
.Nuevamente, las utilidades de un solo propósito se generan y se encadenan entre sí. Una peculiaridad interesante del diseño es que uno puede abandonar los privilegios de superusuario después
listen()
pero incluso antesaccept()
. Aquí hay unrun
script paraqmail-smtpd
eso que hace exactamente eso:Los programas que se ejecutan bajo los auspicios del superusuario son las pequeñas herramientas de la cadena de carga de servicio agnóstica
fdmove
,clearenv
,envdir
,softlimit
,tcp-socket-listen
, ysetuidgid
. En el momento en quesh
se inicia, el socket está abierto y vinculado alsmtp
puerto, y el proceso ya no tiene privilegios de superusuario.s6, s6-networking y execline
Los paquetes de redes s6 y s6 de Laurent Bercot fueron diseñados para hacer esto en conjunto. Los comandos son estructuralmente muy similares a los de
daemontools
UCSPI-TCP.run
los guiones serían muy parecidos, excepto por la sustitución des6-tcpserver
fortcpserver
ys6-setuidgid
forsetuidgid
. Sin embargo, uno también podría optar por utilizar el conjunto de herramientas execlinas de M. Bercot al mismo tiempo.Aquí hay un ejemplo de un servicio FTP, ligeramente modificado del original de Wayne Marshall , que utiliza execline, s6, s6-networking y el programa de servidor FTP de publicfile :
ipsvd
El ipsvd de Gerrit Pape es otro conjunto de herramientas que se ejecuta en la misma línea que ucspi-tcp y s6-networking. Las herramientas son
chpst
ytcpsvd
esta vez, pero hacen lo mismo, y el código de alto riesgo que hace la lectura, el procesamiento y la escritura de cosas enviadas a través de la red por clientes no confiables todavía está en un programa separado.Aquí está el ejemplo de M. Pape de ejecutar
fnord
en unrun
script:systemd
systemd
, el nuevo sistema de supervisión de servicios e init que se puede encontrar en algunas distribuciones de Linux está destinado a hacer lo queinetd
puede hacer . Sin embargo, no utiliza un conjunto de pequeños programas independientes. Uno tiene que auditarsystemd
en su totalidad, desafortunadamente.Con
systemd
uno crea archivos de configuración para definir un socket quesystemd
escucha y un servicio que sesystemd
inicia. El archivo de "unidad" de servicio tiene configuraciones que le permiten a uno tener un gran control sobre el proceso de servicio, incluido el usuario con el que se ejecuta.Con ese usuario configurado para no ser un superusuario,
systemd
realiza todo el trabajo de abrir el socket, vincularlo a un puerto y llamarlisten()
(y, si es necesarioaccept()
) , en el proceso n. ° 1 como superusuario, y el proceso de servicio que genera carreras sin privilegios de superusuario.fuente
Tengo un enfoque bastante diferente. Quería usar el puerto 80 para un servidor node.js. No pude hacerlo porque Node.js se instaló para un usuario que no es sudo. Traté de usar enlaces simbólicos, pero no funcionó para mí.
Entonces llegué a saber que puedo reenviar conexiones de un puerto a otro puerto. Así que inicié el servidor en el puerto 3000 y configuré un puerto hacia adelante desde el puerto 80 al puerto 3000.
Este enlace proporciona los comandos reales que se pueden usar para hacer esto. Aquí están los comandos:
He usado el segundo comando y funcionó para mí. Así que creo que este es un término medio para no permitir que el proceso de usuario acceda directamente a los puertos inferiores, sino que les dé acceso mediante el reenvío de puertos.
fuente
Sus instintos son completamente correctos: es una mala idea tener un gran programa complejo ejecutado como root, porque su complejidad hace que sea difícil confiar en ellos.
Pero, también es una mala idea permitir que los usuarios regulares se unan a puertos privilegiados, porque tales puertos generalmente representan servicios importantes del sistema.
El enfoque estándar para resolver esta aparente contradicción es la separación de privilegios . La idea básica es separar su programa en dos (o más) partes, cada una de las cuales hace una parte bien definida de la aplicación general, y que se comunican mediante interfaces limitadas simples.
En el ejemplo que da, desea separar su programa en dos partes. Uno que se ejecuta como root y se abre y se une al socket privilegiado, y luego lo pasa de alguna manera a la otra parte, que se ejecuta como un usuario normal.
Estas dos formas principales de lograr esta separación.
Un único programa que comienza como root. Lo primero que hace es crear el socket necesario, de la manera más simple y limitada posible. Luego, elimina los privilegios, es decir, se convierte en un proceso de modo de usuario normal y realiza el resto del trabajo. Dejar los privilegios correctamente es complicado, así que tómese el tiempo para estudiar la forma correcta de hacerlo.
Un par de programas que se comunican a través de un par de socket creado por un proceso padre. Un programa de controlador no privilegiado recibe argumentos iniciales y quizás realiza una validación básica de argumentos. Crea un par de sockets conectados a través de socketpair (), y luego bifurca y ejecuta otros dos programas que harán el trabajo real y se comunicarán a través del par de sockets. Uno de estos tiene privilegios y creará el socket del servidor, y cualquier otra operación privilegiada, y el otro hará la ejecución de aplicaciones más compleja y, por lo tanto, menos confiable.
[1] http://en.m.wikipedia.org/wiki/Privilege_separation
fuente
La solución más simple: eliminar todos los puertos privilegiados en Linux
Funciona en ubuntu / debian:
(funciona bien para VirtualBox con cuenta no root)
¡Ahora, tenga cuidado con la seguridad porque todos los usuarios pueden vincular todos los puertos!
fuente