Node.js REST server in esecuzione come root

4

Sto costruendo un server API REST usando Node.js ed Express, che ti permetteranno di trasformare qualsiasi server Linux in un NAS. Ho parecchio fileExec che fondamentalmente genera una shell ed esegue un comando BASH (come pvs , pvcreate , lvs , vgs , ecc.). La maggior parte di questi comandi richiede l'accesso root per l'esecuzione corretta. Per farlo devo eseguire Node.js come utente root con sudo .

So che potrei avere un utente non root che esegue il server e ha una funzione separata con sudo in esso che esegue quel comando specifico. Tuttavia dovrei inserire e gestire la sudo password nella mia applicazione server per avere le credenziali corrette. Non so se sarebbe molto meglio. Inoltre aggiungerebbe più complessità alla mia applicazione ...

Quindi la mia domanda è, c'è un modo migliore per proteggere la mia applicazione server?

    
posta Mudkip 06.07.2016 - 17:20
fonte

4 risposte

3

Suggerirei di dividere l'app in più componenti che comunicano tramite API REST standardizzate.

In questo caso avresti un'app di gestione dello storage che viene eseguita come utente con privilegi sufficienti per gestire i volumi LVM (o se impossibile, quindi come root) e espone i suoi servizi attraverso un'API REST l'app principale (che non ha alcun privilegio ) può consumare. Quella piccola app dovrebbe essere ascoltata su un socket UNIX invece che su uno TCP, sia per motivi di prestazioni che di sicurezza (non è possibile accedere a un socket UNIX da qualsiasi punto dove potrebbe esserlo il TCP se il firewall non viene configurato correttamente e l'app suona qualsiasi indirizzo).

Questo approccio ti permetterà anche di scambiare i componenti di basso livello con qualcos'altro senza modificare l'app principale.

    
risposta data 06.07.2016 - 19:40
fonte
1

Estendere la risposta di André, che è quella che penso che dovresti accettare.

Riduzione dei privilegi

Il primo passo è identificare i privilegi minimi necessari per il flusso di lavoro della tua app. È necessario manipolare i volumi virtuali, da quello che ho capito. Puoi configurare un nuovo UID per farlo, senza una shell di login e senza altre capacità root ? La maggior parte delle interfacce Linux ha file di configurazione per la concessione dei privilegi, quindi controlla con gli sviluppatori i comandi che devi usare.

Se è possibile creare un UID separato

Quindi creane uno. Fai funzionare la tua app in questo modo. Fai in modo che non ci siano bash e home per quell'UID, quindi se l'app viene sfruttata, non dovrebbe esserci un'area del tuo disco rigido con privilegi di scrittura permanenti, il più possibile. Inoltre, nessuna possibilità di accesso remoto su tale UID. Puoi avere uno script di avvio (utilizzando Upstart, Systemd, Init, qualunque cosa, non entrare in quelle polemiche) per eseguire la tua app con questo ID account.

Se devi usare l'UID di root

Quindi capisci che c'è di più in root di come sembra. In primo luogo, un processo eseguito come root può rinunciare ad alcuni privilegi che sono considerati pericolosi da tenere. Queste sono chiamate funzionalità Linux . Quindi, scrivi un wrapper per la tua app che elimina tutte le funzionalità irrilevanti. Se hai bisogno di lasciare delle capacità, fai le tue ricerche per assicurarti che non possano essere sfruttate! Ad esempio, Sfruttare le funzionalità di Linux spiega come ottenere nuovamente un set completo di funzionalità a partire da solo capacità specifiche.

compartimentazione

Vedi la risposta di André. Fondamentalmente, fare in modo che una piccola app svolga tutte le operazioni privilegiate in modo che (1) sia facile da rivedere, è sufficiente convalidare l'API ed eseguire una corretta convalida del dominio di input; (2) c'è meno codice spedito, quindi meno possibilità di bug sfruttabili che completamente rendono il controllo della tua app.

Tempra

Un'altra arma che è stata progettata per proteggerti in questo tipo di scenari è il modulo di sicurezza Linux per il controllo degli accessi obbligatorio. Per impostazione predefinita, Linux consente a root di sovrascrivere la maggior parte dei controlli di controllo degli accessi discrezionali effettuati sulle chiamate di sistema. Tuttavia, gli LSM possono ancora applicare la propria logica obbligatoria sulle chiamate. Ciò consente agli LSM di ridurre i privilegi di root .

Potrei parlare di AppArmor o TOMOY Linux, ma lasciamo i giocattoli della scuola elementare ai bambini piccoli. Devi cercare in SELinux, e comprenderlo effettivamente (dannazione Sì, è difficile). Devi creare un ruolo SELinux, che applicherai al tuo processo. I ruoli si sovrappongono alle identità in SELinux per applicare criteri su tutte le chiamate di sistema. I ruoli significano che puoi avere un root utente a cui è vietato eseguire virtualmente qualsiasi cosa sul sistema. Qui, devi identificare le chiamate di sistema di cui hai bisogno (puoi utilizzare audit2allow a tale scopo) e concedere al ruolo l'accesso a tali chiamate di sistema.

Una volta ottenuto un elenco di privilegi, assicurati di esaminarli e, se possibile, di permetterli solo con le risorse appropriate. Ad esempio, un ruolo può essere autorizzato a scrivere file su / var / www ma non su / var / log. Ciò significa che probabilmente dovrai etichettare alcuni file sul tuo sistema con un tipo specifico e scrivere i tuoi script per aiutarti a mantenere le etichette. Dovrai anche creare un nuovo dominio per la tua app, in modo che tu possa scrivere quella che viene definita una norma di tipo Domain and Type Enforcement. La norma stabilirà in che modo la tua app nel suo dominio può interagire solo con altri tipi e domini specifici.

Per riepilogare, la politica del tipo di dominio garantirà che il tuo processo sia limitato e il criterio del ruolo garantirà il controllo del tuo UID. Ci sono alcune sovrapposizioni ma entrambe sono necessarie perché potresti commettere un errore (o avere una necessità legittima) che porta all'app che passa ad un altro dominio meno ristretto. Il ruolo di SELinux che imponi nella tua app assicurerà che le transizioni possano avvenire solo verso i domini del tuo abbinamento.

È comunque tua responsabilità assicurarti che tutti i domini consentiti per i tuoi ruoli dispongano di privilegi sufficientemente bassi da non compromettere in modo permanente il tuo sistema. Ciò è facilmente ottenibile se (1) prevedi uno qualsiasi dei ' capacità sfruttabili di Linux; (2) non si dispone di risorse condivise tra l'app confinata e altre app; (e (3) neghi qualsiasi forma di memorizzazione permanente (vedi la proprietà senza memoria in Una nota sul problema del confino ), in modo che un'app compromessa non permanga).

Se non riesci a raggiungere questo obiettivo, le probabilità sono che non puoi proteggere il tuo sistema perché l'app richiede solo troppi privilegi. È ora di assumere esperti per verificare che non ti sia sfuggito qualcosa!

    
risposta data 06.08.2016 - 13:54
fonte
0

Supponendo che non ci siano difetti nel programma, si è sicuri di essere in esecuzione con le credenziali root . Sfortunatamente, questo non è sempre il caso, quindi dovresti mai eseguire un servizio accessibile pubblicamente con le credenziali di root.

Se il servizio non è pubblicamente accessibile (ad es. solo LAN, o stai usando un elenco di accesso agli indirizzi IP per limitare i visitatori) allora dovresti giudicare la probabilità che qualcuno sia in grado di accedere al tuo servizio attraverso questi mezzi per determinare se il minore la sicurezza di un servizio root è accettabile.

Altrimenti, devi eseguire il listener come non root . A seconda dell'hacker e dell'impostazione dell'account% non di%, questa è facilmente la differenza tra un hack no-damage e un takeover completo + completo.

Un'opzione è di avere un processo genitore in esecuzione come root , e poi fare in modo che un processo figlio esegua le funzioni dell'applicazione principale incluso il listener HTTP o il listener HTTPS% basato su% co_de. Chiama root per abbassare le proprie credenziali in openssl , setuid , noaccess o qualsiasi account creato / ritenuto appropriato per questo scopo. Usa nobody per comunicare con il processo genitore.

Ma in realtà, penso che la soluzione più semplice per te sia impostare l'opzione Nessuna password nel tuo file webservd . Questo dovrebbe essere fatto solo per l'account utente a cui viene eseguito il servizio, ovvero stdin/stdout , e dovrebbe avere una whitelist specifica di comandi. Se l'accesso di sudoers è concesso per il comando 'any', hai perso lo scopo di eseguire come non webservd .

    
risposta data 06.07.2016 - 18:19
fonte
0

Solitamente è considerata una cattiva idea eseguire applicazioni accessibili esternamente come root

Il modo corretto per farlo sarebbe:

  • crea un nuovo utente come node-data dagli solo le autorizzazioni necessarie (cioè le autorizzazioni alla radice del file system NAS NOT / così come le autorizzazioni specifiche all'eseguibile necessario )

e / o

  • crea 2 server nodo uno rivolto all'esterno con accesso utente di basso livello e uno con un solo API interno tramite qualcosa come ZMQ specifico per l'esecuzione dei comandi di accesso root.
risposta data 06.07.2016 - 18:54
fonte

Leggi altre domande sui tag