Servidor REST de Node.js ejecutándose como root

4

Estoy creando un servidor de API REST utilizando Node.js y Express, que le permitirá convertir cualquier servidor Linux en un NAS. Tengo varios fileExec que básicamente genera un shell y ejecuta un comando BASH (como pvs , pvcreate , lvs , vgs , etc.). La mayoría de estos comandos requieren acceso de root para ejecutarse correctamente. Para hacer eso, debo ejecutar Node.js como usuario root con sudo .

Sé que es posible que un usuario no root ejecute el servidor y tenga una función separada con sudo que ejecute ese comando específico. Sin embargo, tendría que colocar y administrar la contraseña sudo en mi aplicación de servidor para tener las credenciales correctas. No sé si eso sería mucho mejor. También agregaría más complejidad a mi aplicación ...

Entonces, mi pregunta es, ¿hay una mejor manera de asegurar mi aplicación de servidor?

    
pregunta Mudkip 06.07.2016 - 17:20
fuente

4 respuestas

3

Recomendaría dividir su aplicación en múltiples componentes que se comunican a través de API REST estandarizadas.

En este caso, tendría una aplicación de administrador de almacenamiento que se ejecuta como un usuario con suficientes privilegios para administrar volúmenes LVM (o si es imposible, entonces como root) y expone sus servicios a través de una API REST, la aplicación principal (que no tiene privilegios). ) puede consumir. Esa pequeña aplicación debe escuchar en un socket UNIX en lugar de uno TCP, por razones de rendimiento y seguridad (no se podrá acceder a un socket UNIX desde cualquier lugar donde TCP podría estar si el firewall se configura mal y la aplicación escucha). cualquier dirección).

Este enfoque también le permitirá intercambiar los componentes de bajo nivel con otra cosa sin modificar la aplicación principal.

    
respondido por el André Borie 06.07.2016 - 19:40
fuente
1

Ampliando la respuesta de André, que es la que creo que deberías aceptar.

Reducción de privilegios

El primer paso es identificar los privilegios mínimos necesarios para el flujo de trabajo de su aplicación. Necesitas manipular volúmenes virtuales, desde lo que entiendo. ¿Puede configurar un nuevo UID para hacer eso, sin un shell de inicio de sesión y sin otras capacidades root ? La mayoría de las interfaces de Linux tienen archivos de configuración para la concesión de privilegios, así que verifique con los desarrolladores los comandos que necesita usar.

Si puedes crear un UID separado

Entonces haz uno. Haz que tu aplicación funcione así. Asegúrese de que no haya bash y home para ese UID, de modo que si la aplicación se explota no debería haber un área de su disco duro con privilegios de escritura permanentes, tanto como sea posible. Además, no hay oportunidad de inicio de sesión remoto en ese UID. Puede ejecutar una secuencia de comandos de inicio (utilizando Upstart, Systemd, Init, lo que sea, no entrar en esas polémicas) para ejecutar su aplicación con esta ID de cuenta.

Si tienes que usar el UID raíz

Entonces entiendo que hay más en root de lo que parece. En primer lugar, un proceso que se ejecuta como root puede renunciar a algunos privilegios que se consideran peligrosos de mantener. Estos se denominan capacidades de Linux . Entonces, escribe un contenedor para tu aplicación que elimine todas las capacidades irrelevantes. Si necesita dejar algunas capacidades, investigue para asegurarse de que no puedan ser explotadas. Por ejemplo, Aprovechándose de las capacidades de Linux se explica cómo recuperar un conjunto completo de capacidades comenzando solo con capacidades específicas.

Compartimentación

Ver la respuesta de André. Básicamente, haga que una pequeña aplicación realice todas las operaciones privilegiadas para que (1) sea fácil de revisar, solo necesita validar la API y realizar la validación adecuada del dominio de entrada; (2) hay menos código enviado, por lo tanto, hay menos posibilidades de errores explotables que ceden completamente el control de su aplicación.

Endurecimiento

Otra arma que fue diseñada para protegerte en este tipo de escenarios son los módulos de seguridad de control de acceso obligatorio de Linux. De forma predeterminada, Linux permite que root sobrescriba la mayoría de las comprobaciones de control de acceso discrecionales realizadas en las llamadas al sistema. Sin embargo, los LSM aún pueden aplicar su propia lógica obligatoria en las llamadas. Esto permite que los LSM reduzcan los privilegios de root .

Podría hablar sobre AppArmor o TOMOY Linux, pero dejemos los juguetes de la escuela primaria a los niños pequeños. Debe buscar en SELinux, y realmente lo entiende (maldición. Sí, es difícil). Debe crear un rol SELinux, que aplicará a su proceso. Los roles se añaden a las identidades en SELinux para aplicar políticas en todas las llamadas del sistema. Los roles significan que puede tener un usuario root que tiene prohibido hacer prácticamente cualquier cosa en el sistema. Aquí, debe identificar las llamadas al sistema que necesita (puede usar audit2allow para este fin) y otorgar el acceso de rol a esas llamadas al sistema.

Una vez que tenga una lista de privilegios, asegúrese de revisarlos y, si es posible, de permitirlos solo en los recursos adecuados. Por ejemplo, un rol puede tener permiso para escribir archivos en / var / www pero no en / var / log. Lo que significa que probablemente necesitará etiquetar algunos archivos en su sistema con un tipo específico y escribir sus propios scripts para ayudarlo a mantener las etiquetas. También deberá crear un nuevo dominio para su aplicación, de modo que pueda escribir lo que se denomina una política de Cumplimiento de Tipo y Dominio. La política determinará cómo su aplicación en su dominio solo puede interactuar con otros tipos y dominios específicos.

Para resumir, la política de tipo de dominio asegurará que su proceso sea restringido, y la política de rol asegurará que su UID esté restringido. Existe cierta superposición, pero ambas son necesarias porque puede cometer un error (o tener una necesidad legítima) que lleve a la aplicación a otro dominio menos restringido. El rol de SELinux que imponga en su aplicación asegurará que las transiciones solo puedan ocurrir hacia los dominios de su elección.

Todavía es su responsabilidad asegurarse de que todos los dominios permitidos para sus roles tengan privilegios suficientemente bajos para no comprometer permanentemente su sistema. Esto se logra fácilmente si (1) evita cualquiera de los ' capacidades explotables de Linux; (2) no tiene recursos compartidos entre la aplicación limitada y otras aplicaciones; (y (3) niega cualquier forma de almacenamiento permanente (consulte la propiedad memoryless en una nota sobre el problema de confinamiento ), para que una aplicación comprometida no persista).

Si no puede lograrlo, lo más probable es que no pueda asegurar su sistema porque la aplicación solo requiere demasiados privilegios. ¡Ahí es cuando es hora de contratar expertos para que puedan verificar que no se haya perdido algo!

    
respondido por el Steve DL 06.08.2016 - 13:54
fuente
0

Suponiendo que no haya fallas en el programa, se está ejecutando de manera segura con las credenciales root . Lamentablemente, esto no siempre es así, por lo que nunca debe ejecutar un servicio de acceso público con credenciales de raíz.

Si el servicio no es de acceso público (es decir, solo LAN, o si está utilizando una lista de acceso de direcciones IP para limitar los visitantes), debe juzgar la posibilidad de que alguien pueda acceder a su servicio a través de estos medios para determinar si el servicio es más bajo. la seguridad de un servicio root es aceptable.

De lo contrario, debe ejecutar la escucha como no root . Dependiendo del hacker y de la configuración de la cuenta que no sea root , esta es fácilmente la diferencia entre un hack sin daños y una toma de control completa + encubierta.

Una opción es tener un proceso padre ejecutándose como root , y luego hacer que un proceso hijo realice las funciones principales de la aplicación, incluyendo el Oyente HTTP o el oyente HTTPS basado en openssl . Llame a setuid para reducir sus propias credenciales a noaccess , nobody , webservd , o cualquier cuenta que cree / considere apropiada para este propósito. Utilice stdin/stdout para comunicarse con el proceso padre.

Pero realmente, creo que la solución más sencilla para usted es configurar la opción Sin contraseña en su archivo sudoers . Esto solo debe hacerse para la cuenta de usuario en la que se ejecuta su servicio (es decir, webservd ), y debe tener una lista blanca específica de comandos. Si sudo access se concede para el comando 'any', entonces ha rechazado el propósito de ejecutar como no-co_de%.

    
respondido por el George Bailey 06.07.2016 - 18:19
fuente
0

Por lo general, se considera una mala idea ejecutar aplicaciones accesibles externamente como root

La forma correcta de hacer esto sería cualquiera de las dos:

  • cree un nuevo usuario como node-data dale solo los permisos que necesita (también conocidos como permisos en la raíz del sistema de archivos NAS NOT / así como permisos específicos para el ejecutable necesario) )

y / o

  • cree 2 servidores de nodo, uno externo con acceso de usuario de bajo nivel y otro con una API interna solo a través de algo como ZMQ específicamente para ejecutar comandos de acceso raíz.
respondido por el CaffeineAddiction 06.07.2016 - 18:54
fuente

Lea otras preguntas en las etiquetas