Domanda:
Come limitare l'impatto e ridurre il rischio di SQL injection per il sito Web esistente?
Phung D. An
2018-06-21 00:41:53 UTC
view on stackexchange narkive permalink

Il nostro sito web è al 100% basato su API (con un client SPA). Recentemente, un hacker è riuscito a ottenere la password del nostro amministratore (con hash SHA-256) tramite SQL injection (e cracking di pwd) in questo modo:

  https://example.com/api/products? userId = 3645&type = sqlinject here  

È solo un esempio, ma per noi è mortale. Fortunatamente, è stato un bravo hacker e ci ha appena inviato un'e-mail riguardo l'hack. Fortunatamente per un sito web che subisce attacchi costanti durante i suoi 5 anni di esistenza.

Sì, sappiamo che dobbiamo controllare l'input dell'utente ovunque ed eseguire correttamente formattare / uscire / istruzioni preparate prima di inviare i dati a MySQL. Lo sappiamo e lo stiamo aggiustando. Ma non abbiamo abbastanza sviluppatori / tester per renderlo sicuro al 100%.

Ora supponendo di avere lo 0,1% di possibilità di essere iniettato SQL in qualche modo. Come possiamo rendere più difficile per gli hacker trovarlo e limitare il più possibile il danno?

Cosa facciamo per quanto riguarda soluzioni rapide / misurazioni aggiuntive:

  1. Al "gate" di output condiviso da tutte le API, non inviamo più il PDOException grezzo e il messaggio come prima. Ma dobbiamo ancora dire al client che si è verificata un'eccezione:

      {type: exception, code: err643, message: 'contact support for err643'}  

    Sono consapevole che se un hacker vede un'eccezione, continuerà a provare ...

  2. L'utente che PHP usa per connettersi a MySQL può solo CRUD alle tabelle. È abbastanza sicuro?

  3. Rinomina tutte le tabelle (usiamo l'open source in modo che l'hacker possa indovinare il nome delle tabelle).

Cos'altro dovremmo fare?

Aggiornamento: dato che ci sono molti commenti, vorrei dare alcune informazioni a margine

  1. Prima di tutto, questo è LEGACY app, sviluppata da persone simili a studenti, non di livello aziendale. Il team di sviluppo non si trova da nessuna parte, ora solo 1-2 tizi ibridi dev-test che gestiscono centinaia di classi di accesso ai dati.
  2. La password è hash con SHA-256, sì, fa schifo. E lo stiamo cambiando in modo php consigliato.
  3. SQL injection ha 17 anni. Perché è ancora disponibile?
  4. Le istruzioni preparate sono sicure al 100% contro l'iniezione SQL?
I commenti non sono per discussioni estese;questa conversazione è stata [spostata in chat] (https://chat.stackexchange.com/rooms/79300/discussion-on-question-by-phung-d-an-how-to-limit-the-impact-of-e-ridurre-il).
Undici risposte:
#1
+80
Anders
2018-06-21 01:08:04 UTC
view on stackexchange narkive permalink

Non dedicare molto tempo a soluzioni alternative o mezze correzioni. Ogni minuto che spendi cercando di implementare qualsiasi cosa suggerita qui è un minuto che avresti potuto spendere per implementare dichiarazioni preparate. Questa è l'unica vera soluzione.

Se hai una vulnerabilità SQLi, l'attaccante probabilmente vincerà alla fine, qualunque cosa tu faccia per cercare di rallentarlo. Quindi tieni presente che mentre puoi apportare miglioramenti, alla fine stai giocando una partita persa a meno che non risolva la causa principale del problema.

Per quanto riguarda quello che hai provato finora: nascondere i messaggi di errore è un buon inizio. Ti consiglio di applicare autorizzazioni ancora più rigorose (vedi sotto). È discutibile se cambiare i nomi delle tabelle aiuta, ma probabilmente non farà male.

Ok, che dire di quei permessi? Limita quanto più possibile ciò che l'utente del database può fare, fino al livello di tabella o persino di colonna. Puoi persino creare più utenti del database per bloccare le cose ancora di più. Ad esempio, utilizza solo un utente del database con il permesso di scrivere quando stai effettivamente scrivendo. Connettiti solo con un utente che ha il diritto di leggere la colonna della password quando hai effettivamente bisogno di leggere la colonna della password. In questo modo, se hai una vulnerabilità di injection in qualche altra query, non può essere sfruttata per far trapelare le password.

Un'altra opzione è usare un firewall per applicazioni web (WAF), come mod_security per Apache. Puoi configurarlo per bloccare le richieste che sembrano sospette. Tuttavia, nessun WAF è perfetto. E ci vogliono tempo ed energia per configurarlo. Probabilmente faresti meglio a usare quel tempo per implementare le dichiarazioni preparate.

Ancora una volta, non lasciare che nulla di tutto ciò ti attiri in un falso senso di sicurezza. Non è possibile sostituire la causa principale del problema.

Non posso approvare il consiglio generale di connettersi solo con un particolare utente quando è necessaria una particolare operazione.Ciò diventa poco pratico troppo rapidamente.Se vuoi davvero, una separazione modesta andrebbe bene, come la scrittura separata nelle tabelle utente da tutto il resto.Ma devi avere tutte le query per una singola richiesta in una singola transazione.Cercare di garantire che sia così per ogni possibile percorso di codice sarebbe un peso enorme se si hanno molti utenti DB diversi.
In generale sono d'accordo con questo e ci sono molte cose buone qui.Non sono davvero d'accordo sul fatto che dedicare tempo a una soluzione sottrae tempo a un'altra.Un buon WAF può essere configurato da un addetto ai sistemi che non ha una conoscenza specifica del codice di base dell'applicazione.Lo stesso vale per le modifiche al database, che possono essere eseguite da un DBA.Il punto è che le abilità delle persone variano considerevolmente e ogni persona è adatta a compiti diversi.Se riesci a sfruttare bene le capacità delle persone, puoi lavorare meglio come una squadra.
_ "È discutibile se cambiare i nomi delle tabelle aiuta, ma probabilmente non farà male." _ - Può danneggiare i tuoi stessi sviluppatori su tutta la linea, sorprendendoli ogni volta che devono accedere a una tabella che non ha il nome che si aspettano.
Ho usato PDO con dichiarazioni preparate da un po 'di tempo ormai, ma dopo un po' diventa stressante.Recentemente ho iniziato a utilizzare [Medoo] (http://medoo.in).È un wrapper semplice ma potente per PHP, utilizzabile per MySQL, MSSQL, SQLite e altro.Dovresti dare un'occhiata, ti semplifica davvero la vita poiché non hai più bisogno di pensare a dichiarazioni preparate.
@RobinK Sono molto scettico sul fatto che l'uso di istruzioni preparate sia significativamente più "stressante" che concatenare manualmente stringhe insieme ovunque ... e, francamente, chi se ne frega quando è semplicemente il minimo indispensabile di responsabilità da avere quando si programma usando SQL?Non sono sicuro che arrendersi e aggiungere una libreria di terze parti farà molto di più che complicare le cose.
Considererei anche di investire i soldi che dovresti usare per _ "... limitare l'impatto e ridurre il rischio ..." _ per pagare un pentest professionale (ovviamente mentre i tuoi sviluppatori sono ragionevolmente sicuri di aver fatto il loro lavoro)
#2
+65
trietend
2018-06-21 01:05:50 UTC
view on stackexchange narkive permalink

L'unico modo corretto è utilizzare istruzioni preparate.

  1. Se nascondi i messaggi di errore, è un po 'più difficile, ma non fermerà gli aggressori.
  2. Puoi limitare i diritti, ma tutti i diritti concessi all'utente potrebbero essere acquisiti dall'aggressore. In alcuni casi è anche possibile eseguire comandi di shell da una SQL-injection.
  3. Rinominare le tabelle non ti aiuterà. Lo strumento sqlmap forza bruta i nomi delle tabelle per te carattere per carattere. Questo non richiede molto tempo.

Potresti anche limitare il numero di chiamate, per rendere le cose più difficili per gli aggressori o fare avvisi su chiamate sospette e fermare questo manuale, ma l'unico modo corretto per affrontare questo problema è usare istruzioni preparate. Basta eseguire il grep del codice sorgente e dare un'occhiata alle istruzioni SQL con contenuti dinamici e sostituirli.

Fai attenzione alle restrizioni, poiché può avere un rapido impatto sugli utenti legittimi sapendo che il problema qui riguarda una richiesta `GET`, quindi potrebbe essere inserito in un tag` `così tutti gli utenti che vedono la pagina con questo tag attiveranno una richiesta,e potrebbe finire per essere bloccato dal sito web.
Potrebbe anche essere una buona idea rendere la revisione del codice parte del tuo processo, ad es.rivedere tutto ciò che viene accorpato al ramo principale o di produzione.Avere linee guida di codifica che definiscono come le cose dovrebbero essere codificate e cosa è proibito (ad esempio, non dovrebbe essere consentito di concatenare i parametri in una query SQL).Ciò manterrà l'introduzione di nuove vulnerabilità dopo aver corretto quelle attuali.
Trovo "l'unico modo corretto" un po 'grandioso, o nel migliore dei casi ambiguo.Forse l'utilizzo di un database SQL non era corretto sin dall'inizio?
Ok, potrebbero esserci altre opzioni, ma se l'OP sta già esaurendo il tempo di programmazione, questi altri modi saranno solo più lenti.Le dichiarazioni preparate sono probabilmente il modo più pratico per chiudere il buco.
@phresnel Che tipo di database dovrebbe essere usato invece?
@curiousguy, ... non si ottiene l'iniezione SQL in un database [Datalog] (https://en.wikipedia.org/wiki/Datalog).Inoltre, ciò tende a essere dovuto al fatto che le implementazioni recentemente popolari ([DataScript] (https://github.com/tonsky/datascript), [Datomic] (https://www.datomic.com/)) accettano le strutture dati LISPycome specifiche di query - non stringhe - quindi non c'è la tentazione di provare a costruire quelle query tramite la concatenazione di stringhe.
@curiousguy: Dipende dall'intera piattaforma e dai suoi requisiti.Per i requisiti di autenticazione di base e solo poche diecimila utenti, un semplice array di mappe / dizionari / associativi caricato nella memoria di un daemon / servizio e archiviato in un file CSV, XML o JSON potrebbe essere la cosa giusta.Un'implementazione di questo sarebbe semplice, o usare CouchDB, per esempio.Possibilità infinite: è fondamentalmente solo una struttura di dati e una scelta di algoritmi, anche se mi rendo conto che anche i "Bachelors" / "Master" in Germania sembrano aver dimenticato le strutture di dati e gli algoritmi.Per i principianti: https://bit.ly/2lEy9GL
"L'unico modo corretto" Sono fortemente in disaccordo con "l'unico modo corretto".Ci sono molti modi per correggere i modi.(Finiscono per fare qualcosa di equivalente.)
#3
+26
Gloweye
2018-06-21 15:23:55 UTC
view on stackexchange narkive permalink

Lo sappiamo, ma non abbiamo abbastanza sviluppatori / tester per renderlo sicuro al 100%.

Questo è il vero problema . Finché non assumi più persone o riassegni le priorità, non sei al sicuro. Fermare il 99,9% degli aggressori significa che i tuoi dati sono stati compromessi. Le soluzioni cerotto sono una cosa cattiva e non funzionano. Non perdere tempo a refactoring del tuo modello di accesso SQL mentre potresti risolvere problemi reali.

Per quanto riguarda la soluzione del codice, utilizzare istruzioni preparate, come molte persone qui suggeriscono, è il modo più semplice per usare SQL in sicurezza.

È molto più facile che provare a usare php per ripulire gli argomenti da solo e costa molto meno tempo. Basta grep tutta la tua base di codice per tutto ciò che riguarda SQL e risolverlo.

Non credo che assumere più persone aiuterebbe come [soluzione a breve termine] (https://softwareengineering.stackexchange.com/questions/14968/why-does-adding-more-resource-to-a-late-project-make-it-later).E i problemi di sicurezza richiedono soluzioni immediate.Gli altri tuoi suggerimenti sono esatti.
@xDaizu e Jacco: grazie per l'interesse.abbiamo migliaia di classi legacy di accesso ai dati ma solo 1-2 sviluppatori per sistemare le cose, faremo "dichiarazioni preparate" ma non siamo sicuri al 100%
@xDaizu Mentre normalmente sono un convinto sostenitore dell'idea che non è possibile coinvolgere più persone in un progetto in ritardo per accelerarlo, trovare persone in grado di tradurre SQL in dichiarazioni preparate è relativamente facile in quanto è un'abilità piuttosto basilare e universale per ilmaggior 'parte.
assumere molte persone in ritardo potrebbe in generale essere un male, ma come ha detto @wedstrom, la traduzione in dichiarazioni preparate dovrebbe essere qualcosa che le persone che rispondono a un'opportunità di lavoro PHP possono fare senza troppe presentazioni.Le presentazioni appropriate potrebbero essere successive.Ad esempio, effettua il refactoring del codice fino a ottenere quelle migliaia di classi di accesso ai dati legacy con una superclasse comune che contiene tutte le basi SQL.
#4
+9
Nacht
2018-06-21 10:37:33 UTC
view on stackexchange narkive permalink

Elimina definitivamente tutto l'SQL dal codice

La migliore soluzione a questo problema è eliminare tutto il codice SQL come stringhe letterali dal codice e non introdurlo mai più. Utilizza invece il software ORM come Hibernate o Entity Framework. Questo software è comunque molto più piacevole da usare rispetto all'SQL grezzo e parametrizza automaticamente l'SQL quando finisce nel database. Se è possibile per te, segui questa politica.

Se non hai il tempo di apprendere e implementare questi pacchetti, o non puoi usarli per qualche altro motivo, la risposta di trietend è la prossima cosa migliore, usando dichiarazioni preparate. Ciò ti consentirà di essere al sicuro dall'iniezione SQL. Cioè, finché non eserciti alcuna pressione sui tuoi sviluppatori per fornire soluzioni rapide, momento in cui potrebbero dimenticare ancora una volta di parametrizzare una singola variabile, lasciandoti al punto di partenza.

Questo può essere un buon consiglio di sicurezza, ma è un ** terribile ** consiglio di sviluppo.Gli ORM NON sono un proiettile d'argento e l'utilizzo di ORM può facilmente portare a problemi di prestazioni.Ho visto un ORM tirare su una tabella completa in memoria ed eseguire i filtri in memoria perché non è riuscito a ridurli a SQL.Ho anche visto utenti di un ORM fare inavvertitamente una query all'interno di un ciclo (perché sembrava solo codice!).Quindi, no, gli ORM non sono un proiettile d'argento ... e per tutte le applicazioni semi-serie, consiglierei di utilizzare un buon framework SQL.
@MatthieuM.non saper usare una tecnologia non è una scusa per non usarla mai.Gli ORM, come ogni altro strumento, sono soggetti a caveat e una curva di apprendimento, e posso assicurarti che sono perfettamente adatti per essere utilizzati in "applicazioni semi-serie" se usati correttamente.
@BgrWorker: Questo è più un problema di astrazione che perde, che un problema di conoscenza.In realtà è molto facile usare un ORM e per la maggior parte delle situazioni funzionerà perfettamente.Poi, improvvisamente, un refactoring "innocente" introdurrà un problema di prestazioni per vari motivi ... ma i test funzionali passeranno perché è ancora corretto (solo facendo un sacco di lavoro non necessario).Questo è il motivo per cui preferisco un buon framework SQL: enfatizza la differenza tra un getter economico e una query SQL costosa, oltre a delineare chiaramente quali parti del codice si basano su una connessione SQL.
Penso che "Il migliore" sia troppo assoluto.Forse SQL non è affatto giustificato?
@MatthieuM.Anche un refactoring innocente di SQL può causare problemi di prestazioni se impedisce l'uso degli indici.
@AndrolGenhald: Sì, così come le discrepanze nella struttura della tabella tra ambienti di sviluppo / test / produzione e una miriade di variabili.Tuttavia, il vantaggio principale di un framework SQL invece di un ORM qui, è che è immediatamente visibile nella revisione del codice che stai toccando SQL: quali tabelle, quali query, ecc ... a differenza degli ORM in cui dal momento che assomiglia molto al codiceè facile trascurare.
Se l'OP ha problemi a utilizzare correttamente la propria tecnologia attuale, il passaggio a una nuova tecnologia richiederà ancora più tempo.Innanzitutto, proteggi il sito il più velocemente possibile.In secondo luogo, quando c'è più tempo, indaga su quale sia la migliore tecnologia per il futuro.Tutte le soluzioni tecnologiche hanno vantaggi e svantaggi.Chiunque dica il contrario sta cercando di venderti qualcosa.
@MatthieuM.In che modo gli ORM non sono un proiettile d'argento per l'iniezione SQL, di che cosa tratta questa domanda?
Inoltre, preferiresti avere una pagina web che impiega 30 secondi per caricarsi oi tuoi dati trapelati su Internet?Uno di questi problemi è risolvibile;l'altro no.
Gli ORM @Nacht: non sono un proiettile d'argento dal punto di vista dello * sviluppo *.Possono risolvere il problema particolare di SQL injection, ma non risolvono tutti i problemi.Per quanto riguarda la tua domanda da uomo di paglia: entrambi i problemi sono risolvibili e nessuno dei due è inevitabile.Un buon framework SQL * inoltre * evita le iniezioni SQL (perché le query SQL non sono stringhe) rendendo evidente dove si verificano le interazioni del database e quali query vengono eseguite.
@Nacht La maggior parte degli ORM ha il proprio linguaggio di query, ad es.HQL.Ecco un esempio di CVE per un attacco HQL injection.["Hibernate Query Language (HQL) injection attacca e ottieni informazioni sensibili tramite il parametro entityName."] (Https://nvd.nist.gov/vuln/detail/CVE-2016-1595).Se tutto ciò che fai è cambiare SQLi in HQLi, non sono sicuro che risolva davvero qualcosa.
@AndrolGenhald Il refactoring di istruzioni preparate non richiede il refactoring dell'SQL.Spesso può migliorare le prestazioni perché le istruzioni non vengono ricompilate sul database a ogni esecuzione.Ciò che diventa complicato è quando esiste una logica complessa nel tentativo di generare dinamicamente istruzioni diverse (ad es. L'aggiunta di clausole where diverse) in base a condizioni diverse.Ibatis ha una soluzione decente per questo utilizzando modelli e genera un'istruzione preparata per ogni query distinta che viene eseguita.
@Nacht Ecco un esempio migliore di come un ORM 'non è un proiettile d'argento per l'iniezione SQL' che discute come può accadere: https://cwe.mitre.org/data/definitions/564.html
@JimmyJames Non stavo cercando di implicare che sarebbe stato richiesto il refactoring di SQL, stavo fornendo un contrappunto al punto di MatthieuM secondo cui un refactoring innocente potrebbe causare problemi di prestazioni quando si utilizza un ORM.
@AndrolGenhald La mia esperienza con gli ORM pesanti è che provare a usarli con un database che non è stato progettato per funzionare con loro è problematico.È davvero difficile implementarne uno senza un certo livello o refactoring del codice, delle strutture del database e / o delle query.Il refactoring per utilizzare le istruzioni preparate * può * sicuramente essere fatto senza alterare la struttura di nessuno di questi, ma il livello di sforzo varierà.
@JimmyJames Ancora una volta, non quello che stavo dicendo.Stavo semplicemente dicendo che discutere contro l'utilizzo di un ORM perché "causerà problemi di prestazioni" non è necessariamente un buon argomento perché i problemi di prestazioni possono verificarsi anche utilizzando direttamente SQL.
@AndrolGenhald È l'argomento più forte per non muoversi?Forse no, ma l'OP ha già SQL.È improbabile che il passaggio a un ORM sia un calo della sostituzione in cui il passaggio alle dichiarazioni preparate più o meno lo.Nella mia stima (in gran parte uniforme), è molto più probabile che l'OP introduca modifiche ai piani di esecuzione quando si passa a un ORM rispetto a quando si esegue il refactoring per utilizzare le istruzioni prepare.
@JimmyJames ci ha permesso di [continuare questo in chat] (https://chat.stackexchange.com/rooms/79246/)
#5
+9
Jared Smith
2018-06-21 19:18:37 UTC
view on stackexchange narkive permalink

Lo sappiamo, ma non abbiamo abbastanza sviluppatori / tester per renderlo sicuro al 100%.

Non è del tutto chiaro cosa intendi con questa affermazione, come preparata le dichiarazioni sono banali in ogni linguaggio web popolare (PHP, Python, Java, node.js, ecc.) e sono più o meno una misura efficace al 100% contro l'iniezione SQL.

Vuoi dire che subappalti sviluppo e non puoi permetterti di controllare il codice che scrivono per te su contratto? Non puoi permetterti di non farlo: qui sei ancora la parte responsabile.

Vuoi dire che i tuoi sviluppatori sono troppo occupati nell'implementare le funzionalità per impiegare qualche ora per aggiornare la base di codice? Tutto tranne le dichiarazioni preparate richiederà più tempo e costerà di più (ad esempio ORM, obsfucation, autorizzazioni granulari, ecc.).

Vuoi dire che i tuoi sviluppatori non sono abbastanza competenti per eseguire questo semplice compito? Questo è un problema mooolto più grande (o per essere più precisi, SQL injection non dovrebbe essere la tua più grande preoccupazione a quel punto).

Vuoi dire che la tua base di codice è un tale pasticcio di logica spaghetti formattato a fucile code> include che anche sviluppatori competenti impiegheranno un'eternità per eseguire quello che altrimenti sarebbe un semplice compito di poche ore? Allo stesso modo, problema più grande.

Qualunque sia, la soluzione è usare dichiarazioni preparate, circa ieri.

Voglio dire, abbiamo migliaia di classi legacy di accesso ai dati ma solo 1-2 sviluppatori per sistemare le cose, faremo "dichiarazioni preparate" ma non siamo sicuri al 100%.Come dai, anche Facebook ha un buco di sicurezza
@PhungD. E mi dispiace, è difficile.1000 posti da cambiare per 1-2 sviluppatori non sono così banali come lo sarebbero con un'architettura più sana.Ma è ancora fattibile, solo in giorni (come 1-2) invece che in ore.Per quanto riguarda la sicurezza al 100%, dovresti essere abbastanza sicuro solo di eseguire `grep` sulla tua base di codice, ma se vieni citato in giudizio" eravamo occupati e sembrava difficile "non sarà una difesa molto credibile ... non più di"un ragazzo di un'università ha chiesto tutti i nostri dati utente e noi glieli abbiamo dati e ci siamo fidati di non venderli "sarà per fb.
@PhungD.An Il grosso problema con il passaggio dalla concatenazione di stringhe in SQL a istruzioni preparate è generalmente che ci vuole un po 'per capire cosa fa il pasticcio esistente.Il tempo impiegato per risolvere questo problema: migliorerà la sicurezza, migliorerà le prestazioni e renderà il codice più facile da capire.Cercare di disinfettare gli input è un'attività infinita che non risolverà mai il problema principale e non migliorerà la base del codice.
@PhungD.An Le falle di sicurezza possono e _will_ diventeranno molto costose per te se mai vengono sfruttate.Molto più costoso di qualsiasi tempo o denaro che pensi di risparmiare non facendo la cosa giusta.
#6
+5
Nicolas
2018-06-21 23:02:45 UTC
view on stackexchange narkive permalink

Una volta implementato il consiglio iniziale di "istruzione preparata", consiglierei alcune letture sull'iniezione di SQL. Chiedere "come posso impedire l'iniezione di SQL" è una domanda piuttosto ampia! La sicurezza è un argomento che tu (piuttosto, il tuo intero team di sviluppo) devi conoscere molto per ridurre il rischio di compromissione. Un buco mina tutti gli altri tuoi sforzi.

Visita l'Open Web Application Security Project (OWASP) qui: https://www.owasp.org/index.php/SQL_Injection

In particolare il materiale aggiuntivo:

  • Foglio informativo sulla prevenzione di SQL Injection
  • Foglio informativo sulla parametrizzazione delle query
  • Articolo guida su come evitare le vulnerabilità di SQL injection

E anche

  • Come esaminare il codice per le vulnerabilità di SQL injection .
Adoro OWASP per la comprensione del motivo per cui stai facendo la cosa giusta, ma ci sono molte altre risorse specifiche per lo stack tecnologico dell'OP con cui è più facile iniziare.Come per molti problemi di sicurezza, la cosa migliore è non reinventare la ruota.Le pratiche di sicurezza di base della tecnologia scelta è il miglior inizio.
In realtà, come prevenire l'iniezione SQL è una domanda molto ristretta con una risposta molto semplice: non costruire stringhe di query da dati controllati dall'utente.Evitarlo in primo luogo è abbastanza facile, ma ovviamente trovare posti che lo fanno in una grande base di codice esistente può essere complicato.
@Cubic Abbastanza giusto, la stessa questione OP era ristretta.Forse stavo leggendo oltre la domanda stessa: se qualcuno fa quel tipo di domanda, allora sembra che ciò di cui ha effettivamente bisogno sia acquisire una comprensione generale delle migliori pratiche.(e, come dice Guy Schalat sopra, le migliori pratiche per la _tua tecnologia_)
#7
+4
CoderTao
2018-06-22 02:17:28 UTC
view on stackexchange narkive permalink

Una misura provvisoria potrebbe essere quella di esaminare un firewall per applicazioni web (WAF): ci sono alcune aziende là fuori che lo forniscono come servizio e alcuni fornitori di cloud che hanno anche offerte. CloudFlare sembra offrirne uno, ho avuto un client che utilizza Incapsula e so che l'offerta AWS WAF ha alcuni set di regole gestiti per SQL injection.

Il modo in cui funziona è che tutto il traffico viene inviato a / attraverso il WAF (includendolo sui server o impostando il DNS in modo che punti al WAF come faresti per un CDN), e cerca cose che sembrano tentativi di SQL injection nei parametri. Non rileva tutti gli attacchi e potrebbe bloccare il traffico legittimo, ma è una soluzione disponibile per i cerotti.

+1 per aver effettivamente risposto a Q e non aver ripetuto ciò che è già stato detto sulla sanificazione dell'input dell'utente.Ovviamente le istruzioni preparate dovrebbero essere implementate, ma a seconda del software potrebbe essere molto più veloce far funzionare WAF, potrebbe non essere la soluzione perfetta ma probabilmente aiuterà con la situazione immediata.
#8
+2
Concrete Gannet
2018-06-22 08:28:22 UTC
view on stackexchange narkive permalink

Con "non ho abbastanza sviluppatori" presumo tu intenda che alcune persone influenti nella tua organizzazione pensano che ci siano priorità più alte, quindi qualsiasi risorsa tu abbia è dedicata a queste cose. Quindi risolvere il tuo problema di sicurezza significa perdere altri punti in un'analisi costi-benefici.

Il tuo compito qui è cambiare idea, tanto quanto implementare la correzione. Quantificare la posta in gioco: quale sarebbe il danno, sia in termini economici che di reputazione, di un'altra violazione? Potrebbero esserci leggi nella tua giurisdizione che richiedono di segnalare le violazioni dei dati dei tuoi utenti. Sarebbe imbarazzante? Potrebbero esserci rapporti dei media sulle cattive pratiche della tua organizzazione?

Pensa all'investimento per fissare la sicurezza come un'assicurazione. In retrospettiva, dopo aver saputo che il tuo edificio non è stato bruciato per un periodo di dieci anni, potresti sostenere che i tuoi premi sono stati uno spreco. Ma tu e la tua organizzazione pagate l'assicurazione, perché dovete affrontare un futuro incerto. È la gestione del rischio.

Il rischio ha due fattori: probabilità e impatto. La probabilità di un'altra violazione è alta: sai che può essere eseguita almeno una volta. Se anche le potenziali conseguenze sono negative, dovresti aumentare la priorità di correggere le tue vulnerabilità di sicurezza.

#9
+1
LUser
2018-06-23 16:53:53 UTC
view on stackexchange narkive permalink

Come tutti hanno già detto, correggi il codice sul sito.

Puoi fare qualsiasi patch desideri su un muro, ma fino a quando il muro non sarà costruito correttamente, qualsiasi patch sarà un problema di sanguinamento ..

Qualsiasi altro suggerimento per pulire il codice è ciò che Linus Torvalds chiamerebbe masterbation.

  • Correggi il tuo codice (dai punti di iniezione più ovvi all'ultimo IE Get params) e utilizzare istruzioni preparate. come posso impedire l'iniezione sql in php

    • Puoi provare un WAF (IE ModSecurity ) temporaneamente finché non sarai in grado di sistemare le cose.

    • Prova Forse una sorta di divieto di PI su "persone che testano il sito" o blocca le query non sicure.

    • Se hai la possibilità di creare una schermata di accesso temporanea (sicura) di fronte fino a quando questo non viene risolto.

    • Prova un servizio di terze parti finché non viene risolto qualcosa come cloudflare o qualsiasi altra cosa sia fuori lì.

I PDO sono disponibili dal rilascio di PHP 5.1 nel 24 novembre 2005 ... Gli sviluppatori devono capire che sono conseguenze per le loro cattive abitudini di codifica e personalmente penso che dovrebbe esserci responsabilità per la qualità del lavoro fornito.

In ogni caso i PDO sono una cosa facile da implementare. Se i tuoi sviluppatori non sono in grado di fornire una qualità migliore, allora suggerirei di eliminarli ...

#10
  0
bobflux
2018-06-24 00:05:31 UTC
view on stackexchange narkive permalink

La regola più importante è:

Utilizza librerie, strumenti e API che rendono l'opzione sicura l'opzione più semplice.

Nacht dice "basta usare un ORM "che è un sottoinsieme di questa regola.

Le istruzioni preparate violano questa regola, poiché sono ingombranti da usare, provocano un eccesso di codice, inoltre possono essere spesso più lente delle istruzioni non preparate a seconda Banca dati. Sono una soluzione valida, non criticherò chi li usa, ma non sono necessariamente la soluzione migliore e più conveniente.

E .. vogliamo che l'opzione sicura sia facile e conveniente, quindi il programmatore lo usa per interesse personale e pigrizia. Vogliamo che il programmatore debba effettivamente fare di tutto e investire un po 'di impegno per utilizzare l'opzione non sicura! ...

Una soluzione molto migliore è un'API come Python dbapi. Ho scritto un equivalente in php anni fa, che era come:

  db_query ("SELECT * FROM mytable WHERE id =% s", $ id)  

Questo è più conveniente delle dichiarazioni preparate. Solo una riga per digitare. Inoltre restituisce il risultato in una forma utilizzabile da foreach (), quindi è molto più facile da usare rispetto a fetch () e altre cose. Ancora più importante, il codice nascosto dietro questa API gestirà correttamente l'escape. Ciò rende irrilevanti le SQL injection. Questo gestisce circa il 99% delle query se non si utilizza un ORM. Le query dinamiche (di solito la ricerca) richiedono una gestione speciale, ma è comunque facile.

Se tieni a mente questa regola, a un certo punto ti chiederai perché devi usare htmlspecialchars (), e perché la lingua non ha una caratteristica che renderebbe l'impostazione sicura (cioè, nessun vuln XSS) la più facile da usare? Perchè oh perchè? Ed è allora che rilascia PHP.

#11
  0
Tom
2018-07-06 15:17:25 UTC
view on stackexchange narkive permalink

Oltre a tutte le ottime risposte finora, se vuoi affrontare il problema specifico dell'estrazione delle credenziali utente, puoi effettuare il refactoring del tuo database per avere le password in una tabella separata con diritti di accesso rigorosi , simile al modo in cui i sistemi Unix le inseriscono in /etc/shadow.

Per verificare le credenziali, è necessaria una procedura memorizzata che prenda la password (o hash) inserita come parametro e restituisca un valore booleano. In altre parole, scarichi il lavoro di verifica delle credenziali sul database e l'hash effettivo non lascia mai il database.

Ciò richiede un refactoring minimo e risolve il tuo problema immediato alla radice, invece di una specifica SQL injection mentre lasciandoti vulnerabile al prossimo.

Anche se all'inizio sembra una buona idea, la maggior parte dei database non supporta buone funzioni di hashing delle password e le query sui database vengono spesso registrate.Suppongo che tu recuperi _solo_ il sale e i parametri, l'hash, quindi esegui un'altra query per confrontare l'hash, ma sembra troppo complicato per valerne la pena per la maggior parte dei siti.
c'è pgcrypto per PostgreSQL, per esempio.Non so di altri database.Non riesco a immaginare cose come Oracle non hanno equivalenti.


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 4.0 con cui è distribuito.
Loading...