Migliori Pratiche Di Produzione
Il termine “produzione” si riferisce allo stadio del ciclo di vita del software quando un’applicazione o API è generalmente disponibile per i suoi utenti finali o consumatori. Al contrario, nella fase di “sviluppo” stai ancora scrivendo attivamente e testando il codice, e l’applicazione non è aperta ad accesso esterno. Gli ambienti di sistema corrispondenti sono conosciuti rispettivamente come ambienti production e development.
Gli ambienti di sviluppo e di produzione sono di solito impostati in modo diverso e hanno esigenze molto diverse. Che cosa bene in sviluppo potrebbe non essere accettabile nella produzione. Ad esempio, in un ambiente di sviluppo potresti voler registrare dettagliatamente gli errori per il debug, mentre lo stesso comportamento può diventare una preoccupazione di sicurezza in un ambiente di produzione. E nello sviluppo, non c’è bisogno di preoccuparsi di scalabilità, affidabilità e prestazioni, mentre queste preoccupazioni diventano fondamentali nella produzione.
Note
If you believe you have discovered a security vulnerability in Express, please see Security Policies and Procedures.
Le migliori pratiche di sicurezza per le applicazioni Express in produzione includono:
- Migliori Pratiche Di Produzione: Sicurezza
- Overview
- Non utilizzare versioni deprecate o vulnerabili di Express
- Usa TLS
- Non fidarti dell’input dell’utente
- Usa Elmet
- Riduci l’impronta digitale
- Usa i cookie in modo sicuro
- Prevenire attacchi di forza brutale contro l’autorizzazione
- Assicurati che le tue dipendenze siano sicure
- Ulteriori considerazioni
Non utilizzare versioni deprecate o vulnerabili di Express
Express 2.x e 3.x non sono più mantenuti. Problemi di sicurezza e prestazioni in queste versioni non saranno risolti. Non usarli! Se non hai spostato nella versione 4, segui la guida alla migrazione o prendi in considerazione Opzioni di supporto commerciale.
Assicurati inoltre di non utilizzare nessuna delle versioni Express vulnerabili elencate nella pagina Aggiornamenti di sicurezza. Se lo si è, aggiornare a una delle versioni stabili, preferibilmente l’ultimo.
Usa TLS
Se la tua app si occupa o trasmette dati sensibili, usa Transport Layer Security (TLS) per proteggere la connessione e i dati. Questa tecnologia crittografa i dati prima che vengano inviati dal client al server, impedendo così alcuni hack comuni (e facili). Anche se le richieste Ajax e POST potrebbero non essere visibilmente evidenti e sembrano “nascoste” nei browser, il loro traffico di rete è vulnerabile a packet sniffing e man-in-the-middle attacks.
Potresti avere familiarità con la crittografia Secure Socket Layer (SSL). TLS è semplicemente la prossima progressione di SSL. In altre parole, se si utilizza SSL prima, considerare l’aggiornamento a TLS. In generale, si consiglia Nginx per gestire TLS. Per un buon riferimento per configurare TLS su Nginx (e altri server), vedere Configurazioni server consigliate (Mozilla Wiki).
Inoltre, uno strumento utile per ottenere un certificato TLS gratuito è Let’s Encrypt, un gratuito, automatizzato, e autorità di certificazione aperta (CA) fornite dal Gruppo di ricerca sulla sicurezza Internet (ISRG).
Non fidarti dell’input utente
Per le applicazioni web, uno dei requisiti di sicurezza più critici è la convalida e la gestione dell’input dell’utente. Questo avviene in molte forme e non li copriremo tutti qui. In definitiva, la responsabilità di convalidare e gestire correttamente i tipi di input utente che la tua applicazione accetta è tua.
Impedisci reindirizzamenti aperti
Un esempio di input utente potenzialmente pericoloso è un open redirect, dove un’applicazione accetta un URL come input utente (spesso nella domanda URL, ad esempio ? rl=https://esempio. om) e utilizza res.redirect per impostare l’intestazione location e
restituisce uno stato 3xx.
Un’applicazione deve convalidare che supporta il reindirizzamento all’URL in arrivo per evitare di inviare gli utenti a link dannosi come siti web di phishing, tra gli altri rischi.
Ecco un esempio di controllo degli URL prima di usare res.redirect o res.location:
app.use((req, res) => { try { if (new Url(req.query.url).host !== 'example.com') { return res.status(400).end(`Unsupported redirect to host: ${req.query.url}`); } } catch (e) { return res.status(400).end(`Invalid url: ${req.query.url}`); } res.redirect(req.query.url);});Usa Elmo
Helmet può aiutare a proteggere la tua app da alcune note vulnerabilità web impostando le intestazioni HTTP in modo appropriato.
Helmet è una funzione middleware che imposta le intestazioni di risposta HTTP legate alla sicurezza. Casco imposta le seguenti intestazioni per impostazione predefinita:
Content-Security-Policy: Una potente lista di permessi di ciò che può accadere sulla tua pagina che attenua molti attacchiCross-Origin-Opener-Policy: aiuta a isolare la tua paginaCross-Origin-Resource-Policy: blocca gli altri dal caricamento delle risorse cross-originOrigin-Agent-Cluster: Modifica l’isolamento del processo per essere basato sull’origineReferrer-Policy: controlla l’intestazioneRefererStrict-Transport-Security: Racconta i browser per preferire HTTPSX-Content-Type-Options: Evita MIME sniffingX-DNS-Prefetch-Control: controlla il prefetching DNSX-D\<unk> ad-Options: Forza il salvataggio dei download (solo Internet Explorer)X-Frame-Options: intestazione legacy che attenua gli attacchi ClickjackingX-Permitted-Cross-Domain-Policies: Controlla il comportamento cross-domain per i prodotti Adobe, come AcrobatX-Powered-By: Informazioni sul server web. Rimosso perché potrebbe essere usato in semplici attacchiX-XSS-Protection: intestazione legacy che cerca di mitigare attacchi XSS, ma peggiora le cose, quindi l’Elmo lo disabilita
Ogni intestazione può essere configurata o disabilitata. Per saperne di più su di esso si prega di andare su il suo sito di documentazione.
Installare Elmo come qualsiasi altro modulo:
$ npm install helmetQuindi per usarlo nel tuo codice:
// ...
const helmet = require('helmet');app.use(helmet());
// ...Riduci l’impronta digitale
Può aiutare a fornire un ulteriore livello di sicurezza per ridurre la capacità degli aggressori di determinare il software che un server utilizza, conosciuto come “impronta digitale”. Anche se non un problema di sicurezza in sé, ridurre la capacità di impronte digitali un’applicazione migliora la sua posizione generale di sicurezza. Il software del server può essere improntato alle impronte digitali per quanto riguarda il modo in cui risponde a richieste specifiche, ad esempio in le intestazioni di risposta HTTP.
Per impostazione predefinita, Express invia l’intestazione della risposta X-Powered-By che puoi disabilitare
usando il metodo app.disable():
app.disable('x-powered-by');Note
Disabilitare l’intestazione X-Powered-By non impedisce a un sofisticato aggressore di determinare
che un’app sta eseguendo Express. Può scoraggiare un exploit casuale, ma ci sono altri modi per
determinare che un’app è in esecuzione Express.
Express invia anche i propri messaggi di risposta “404 Not Found” formattati e i messaggi di risposta di errore di formattazione . Questi possono essere modificati da aggiungendo il tuo gestore non trovato e scrivendo il tuo gestore di errore:
// last app.use calls right before app.listen():
// custom 404app.use((req, res, next) => { res.status(404).send("Sorry can't find that!");});
// custom error handlerapp.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('Something broke!');});Utilizzare i cookie in modo sicuro
Per garantire che i cookie non aprano la tua app agli exploit, non utilizzare il nome predefinito del cookie di sessione e impostare le opzioni di sicurezza dei cookie in modo appropriato.
Ci sono due principali moduli di sessione di cookie middleware:
- express-session che sostituisce il middleware
express.sessionintegrato in Express 3.x. - cookie-session che sostituisce il middleware
express.cookieSessionintegrato in Express 3.x.
La differenza principale tra questi due moduli è come salvano i dati di sessione dei cookie. La express-session middleware memorizza i dati di sessione sul server; salva solo l’ID di sessione nel cookie stesso, non i dati di sessione. Per impostazione predefinita, utilizza l’archivio in-memory e non è progettato per un ambiente di produzione. Nella produzione, dovrai impostare un archivio di sessione scalabile; vedi l’elenco di negozi di sessione compatibili.
Al contrario, cookie-session middleware implementa la memorizzazione supportata dai cookie: serializza l’intera sessione al cookie, piuttosto che una semplice chiave di sessione. Usalo solo quando i dati di sessione sono relativamente piccoli e facilmente codificati come valori primitivi (piuttosto che oggetti). Anche se i browser dovrebbero supportare almeno 4096 byte per cookie, per assicurarsi di non superare il limite, non superare una dimensione di 4093 byte per dominio. Inoltre, essere consapevoli che i dati dei cookie saranno visibili al cliente, quindi se c’è qualche motivo per mantenerlo sicuro o oscuro, allora express-session potrebbe essere una scelta migliore.
Non utilizzare il nome predefinito del cookie di sessione
Utilizzando il nome predefinito del cookie di sessione puoi aprire la tua app agli attacchi. Il problema di sicurezza posto è simile a X-Powered-By: un potenziale attaccante può usarlo per impronte digitali il server e attacchi di destinazione di conseguenza.
Per evitare questo problema, usa i nomi generici dei cookie, ad esempio usando il middleware express-session:
const session = require('express-session');app.set('trust proxy', 1); // trust first proxyapp.use( session({ secret: 's3Cur3', name: 'sessionId', }));Imposta opzioni di sicurezza cookie
Impostare le seguenti opzioni di cookie per migliorare la sicurezza:
secure- Assicura il browser solo invia il cookie su HTTPS.httpOnly- Assicura che il cookie venga inviato solo su HTTP(S), non su JavaScript, contribuendo a proteggere dagli attacchi di scripting cross-site.domain- indica il dominio del cookie; usalo per confrontare con il dominio del server in cui viene richiesto l’URL. Se corrispondono, controlla l’attributo percorso successivo.path- indica il percorso del cookie; usalo per confrontare con il percorso della richiesta. Se questo e dominio corrispondono, quindi inviare il cookie nella richiesta.expires- usa per impostare la data di scadenza per i cookie persistenti.
Ecco un esempio che usa cookie-session middleware:
const session = require('cookie-session');const express = require('express');const app = express();
const expiryDate = new Date(Date.now() + 60 * 60 * 1000); // 1 hourapp.use( session({ name: 'session', keys: ['key1', 'key2'], cookie: { secure: true, httpOnly: true, domain: 'example.com', path: 'foo/bar', expires: expiryDate, }, }));Prevenire attacchi di forza brutale contro l’autorizzazione
Assicurati che gli endpoint di accesso siano protetti per rendere i dati privati più sicuri.
Una tecnica semplice e potente è quella di bloccare i tentativi di autorizzazione utilizzando due metriche:
- Il numero di tentativi consecutivi falliti dallo stesso nome utente e indirizzo IP.
- Il numero di tentativi falliti da un indirizzo IP per un lungo periodo di tempo. Ad esempio, blocca un indirizzo IP se fa 100 tentativi falliti in un giorno.
Il pacchetto rate-limiter-flexible fornisce strumenti per rendere questa tecnica facile e veloce. Puoi trovare un esempio di protezione della forza brutale nella documentazione
Assicurati che le tue dipendenze siano sicure
Usare npm per gestire le dipendenze della tua applicazione è potente e conveniente. Ma i pacchetti che si utilizzano possono contenere vulnerabilità di sicurezza critiche che potrebbero influenzare anche la vostra applicazione. La sicurezza della tua app è forte solo come il “link più debole” nelle tue dipendenze.
Dal momento che npm@6, npm esamina automaticamente ogni richiesta di installazione. Inoltre, puoi usare npm audit per analizzare il tuo albero delle dipendenze.
$ npm auditSe vuoi rimanere più sicuro, considera Snyk.
Snyk offre sia un strumento da riga di comando che una integrazione Github che controlla la tua applicazione contro database di vulnerabilità open source di Snyk per qualsiasi vulnerabilità nota nelle tue dipendenze. Installare il CLI come segue:
$ npm install -g snyk$ cd your-appUsa questo comando per testare la tua applicazione per le vulnerabilità:
$ snyk testEvitare altre vulnerabilità note
Tieni d’occhio Progetto di Sicurezza Nodi o Snyk gli avvisi che possono influenzare Express o altri moduli che la tua app utilizza. In generale, queste banche dati sono risorse eccellenti per la conoscenza e gli strumenti sulla sicurezza del nodo.
Infine, Express apps—come qualsiasi altra web app—può essere vulnerabile a una varietà di attacchi basati sul web. Conoscere se stessi con conosciute vulnerabilità web e prendere precauzioni per evitarli.
Considerazioni aggiuntive
Ecco alcuni ulteriori consigli dall’eccellente Node.js Security Checklist. Fare riferimento a quel post del blog per tutti i dettagli su queste raccomandazioni:
- Filtrare e sanificare sempre l’input dell’utente per proteggere contro gli script cross-site (XSS) e gli attacchi di iniezione dei comandi.
- Difendi gli attacchi di SQL injection utilizzando query parametrizzate o dichiarazioni preparate.
- Usa lo strumento open-source sqlmap per rilevare le vulnerabilità di SQL injection nella tua app.
- Usa gli strumenti nmap e sslyze per testare la configurazione dei tuoi cifrari SSL, chiavi, rinegoziazione e validità del certificato.
- Usa safe-regex per garantire che le tue espressioni regolari non siano suscettibili di espressione regolare negazione del servizio attacchi.