È sicuro non parametrizzare una query SQL quando il parametro non è una stringa?


113

In termini di SQL injection , comprendo perfettamente la necessità di parametrizzare un stringparametro; questo è uno dei trucchi più antichi del libro. Ma quando può essere giustificato non parametrizzare un SqlCommand? Ci sono tipi di dati considerati "sicuri" da non parametrizzare?

Per esempio: io non mi considero da nessuna parte vicino a un esperto di SQL, ma non riesco a pensare a tutti i casi in cui sarebbe potenzialmente vulnerabile a SQL injection di accettare una boolo un inte solo concatenare a destra nella query.

La mia ipotesi è corretta o ciò potrebbe potenzialmente lasciare un'enorme vulnerabilità di sicurezza nel mio programma?

Per chiarimenti, questa domanda è contrassegnata che è un linguaggio fortemente tipizzato; quando dico "parametro", pensa qualcosa di simile public int Query(int id) .


14
Non otterrai il vantaggio dei piani di query memorizzati nella cache se non utilizzi i parametri, sarebbe necessario creare un piano di query separato per ogni nuova combinazione di input che fornisci.
Scott Chamberlain

5
@MatthewWhited Come sapresti che ci vuole meno tempo? Questa situazione si verifica ovunque in alcuni progetti di uno sviluppatore attuale e di uno sviluppatore precedente. Se effettivamente migliora la sicurezza, invia una risposta. Per chiarimento, sono d'accordo sul fatto che sia meglio parametrizzare, ovviamente. Ma non è proprio la mia domanda.
johnnyRose

7
Le query parametrizzate vengono utilizzate principalmente per le prestazioni e l'ottimizzazione. La prevenzione di SQL injection è un effetto collaterale.
Salman A

13
Penso che l'OP abbia posto una domanda valida. Sta cercando di valutare i costi / benefici della correzione di un potenziale rischio. quell'equazione cambia con il potenziale di quel rischio. se il rischio è zero, non lo farei neanche io. Ha chiesto una domanda tecnica sul potenziale, non un giudizio soggettivo sul fatto che tu pensi che valga il suo tempo. L'OP è l'unico che può fare quella chiamata.
Sir Swears-a-lot

10
Per spiegarmi: sono un dba. Apprezzo e rispetto le migliori pratiche e in un mondo perfetto tutto il codice sarebbe perfetto. Purtroppo nel mondo in cui lavoro, ho più problemi da risolvere che tempo per risolverli. Questo significa dare priorità. IMO Rewriting code che già funziona, è sicuro e funziona a livelli accettabili sembra un lusso. (Che non posso permettermi)
Sir Swears-a-lot

Risposte:


101

Penso che sia sicuro ... tecnicamente , ma è un'abitudine terribile in cui entrare. Vuoi davvero scrivere domande come questa?

var sqlCommand = new SqlCommand("SELECT * FROM People WHERE IsAlive = " + isAlive + 
" AND FirstName = @firstName");

sqlCommand.Parameters.AddWithValue("firstName", "Rob");

Ti lascia anche vulnerabile nella situazione in cui un tipo cambia da un intero a una stringa (pensa al numero del dipendente che, nonostante il suo nome, può contenere lettere).

Quindi, abbiamo cambiato il tipo di EmployeeNumber da inta string, ma abbiamo dimenticato di aggiornare le nostre query sql. Ops.


24
Possiamo smettere di usarlo AddWithValue già? blogs.msmvps.com/jcoehoorn/blog/2014/05/12/…
RemarkLima

5
@RemarkLima Qual è la soluzione quando si genera dinamicamente codice che associa i valori ai parametri? Il post sul blog non riesce ad affrontare questo scenario. Sì, è una singola riga per impostare il tipo SQL quando è noto , ma quando non lo è, allora hai un problema (o devi ricorrere all'annotazione dei modelli con quelle informazioni).
casperOne

1
Quindi sei bloccato a AddWithValuemeno che tu non abbia una mappatura dei tipi di database come parte della costruzione dinamica dell'istruzione. Presumo che tu abbia un elenco di colonne di destinazione e, come parte del dizionario, potresti avere i tipi se lo desideri. Altrimenti, prendi solo il colpo di prestazioni. In definitiva, credo che sia solo una buona informazione da sapere.
RemarkLima

8
@RemarkLima Il punto è "Possiamo smettere di usare AddWithValuegià?" dovrebbe davvero essere "se conosci il tipo, dovresti astenervi AddWithValue
dall'usare

2
Ehi, non sparare al messenger, non l'ho scritto io ;-) ma il punto rimane, e se incorporato nei tuoi progetti dall'inizio, non c'è motivo per cui non dovresti conoscere il tipo. Le migliori pratiche e tutto quel jazz :-)
RemarkLima

65

Quando si utilizza una piattaforma fortemente tipizzato su un computer è possibile controllare (come un server web), è possibile impedire l'inserimento di codice per le query con solo bool, DateTimeo intvalori (e di altri numerica). Ciò che preoccupa sono i problemi di prestazioni causati dall'obbligo del server sql di ricompilare ogni query e impedirgli di ottenere buone statistiche su quali query vengono eseguite con quale frequenza (il che danneggia la gestione della cache).

Ma quella parte "su un computer che controlli" è importante, perché altrimenti un utente può modificare il comportamento utilizzato dal sistema per generare stringhe da quei valori per includere testo arbitrario.

Mi piace anche pensare a lungo termine. Cosa succede quando la base di codice fortemente tipizzata di oggi viene trasferita tramite traduzione automatica nel nuovo linguaggio dinamico e perdi improvvisamente il controllo del tipo, ma non hai ancora tutti gli unit test giusti per il codice dinamico ?

In realtà, non c'è un buon motivo per non utilizzare i parametri di query per questi valori. È il modo giusto per farlo. Vai avanti e inserisci i valori hard-code nella stringa sql quando sono davvero costanti, ma altrimenti, perché non usare solo un parametro? Non è difficile.

In definitiva, non lo chiamerei un bug , di per sé, ma lo chiamerei un odore : qualcosa che è appena inferiore a un bug di per sé, ma è una forte indicazione che i bug sono nelle vicinanze, o lo saranno alla fine. Un buon codice evita di lasciare odori e qualsiasi buon strumento di analisi statica lo contrassegna.

Aggiungerò che questo non è, sfortunatamente, il tipo di argomento che puoi vincere direttamente. Sembra una situazione in cui essere "giusti" non è più sufficiente e pestare i piedi dei colleghi per risolvere questo problema da soli non è probabile che promuova buone dinamiche di squadra; alla fine potrebbe ferire più di quanto aiuta. Un approccio migliore in questo caso potrebbe essere quello di promuovere l'uso di uno strumento di analisi statica. Ciò darebbe legittimità e credibilità agli sforzi mirati e tornare indietro e correggere il codice esistente.


1
Sicuramente non è una sfida farlo parametrizzato. La mia domanda è nata perché un collega ha scritto una serie di query concatenando valori interi e mi chiedevo se fosse una perdita di tempo esaminarle e risolverle tutte.
johnnyRose

2
Penso che la domanda "È un bug" sia a cosa si riduce la mia domanda.
johnnyRose

7
È un "odore": qualcosa che non è all'altezza di un insetto di per sé, ma indica che gli insetti sono probabilmente nelle vicinanze. Un buon codice cerca di eliminare gli odori. Qualsiasi buon strumento di analisi statica lo contrassegnerebbe sicuramente.
Joel Coehoorn

1
Mi piace il termine "odore". Avrei invece usato qualcosa come "larva", dove non è ancora un bug, ma gli aggiornamenti futuri potrebbero catturarlo in un verme che mangerà il tuo backend finché non lo schiaccerai o lo fumigerai. Certamente non vuoi che il potenziale del codice necrotico emerga in un ambiente di produzione, e avere qualcosa che non è stato sviluppato con una certa dose di finezza potrebbe certamente far sì che sia presente, come in questo caso.
CSS

1
Questo è semplicemente sbagliato. Vedi la mia risposta ad esempio su come puoi ancora creare SQL injection con DateTimeoint
Kaspars Ozols

53

In alcuni casi, è possibile eseguire attacchi SQL injection con variabili non parametrizzate (concatenate) diverse dai valori stringa - vedere questo articolo di Jon: http://codeblog.jonskeet.uk/2014/08/08/the-bobbytables -cultura / .

Il fatto è che quando ToStringviene chiamato, un provider di impostazioni cultura personalizzato può trasformare un parametro non di stringa nella sua rappresentazione di stringa che inietta un po 'di SQL nella query.


14
Penso che questo sia l'unico post che risponde alla domanda, che essenzialmente è "Come può essere possibile l'iniezione anche con ints?"
Arturo Torres Sánchez

3
Tuttavia, se sei in grado di iniettare codice personalizzato come booby trapped è CultureInfodifficile sapere perché avresti comunque bisogno di SQL injection.
Martin Smith

più 1, l'unica risposta che risponde effettivamente alla domanda
ken2k

@MartinSmith: vedi la mia risposta che mostra un possibile modo per cambiare CultureInfo dall'esterno.
user1027167

Se una persona può scrivere tale codice nell'applicazione, perché ha bisogno di SQL Injection?
Reza Aghaei

51

Questo non è sicuro nemmeno per i tipi non stringa. Usa sempre i parametri. Periodo.

Considera il seguente esempio di codice:

var utcNow = DateTime.UtcNow;
var sqlCommand = new SqlCommand("SELECT * FROM People WHERE created_on <= '" + utcNow + "'");

A prima vista il codice sembra sicuro, ma tutto cambia se apporti alcune modifiche nelle Impostazioni internazionali di Windows e aggiungi l'iniezione in formato data breve:

Datetime Injection

Ora il testo del comando risultante ha questo aspetto:

SELECT * FROM People WHERE created_on <= '26.09.2015' OR '1'<>' 21:21:43'

Lo stesso può essere fatto per il inttipo poiché l'utente può definire un segno negativo personalizzato che può essere facilmente modificato in SQL injection.

Si potrebbe sostenere che la cultura invariante dovrebbe essere usata al posto della cultura corrente, ma ho visto concatenazioni di stringhe come questa così tante volte ed è abbastanza facile non vederla quando si concatenano stringhe con oggetti usando +.


10
Chi può modificare le impostazioni del server? Se una persona può farlo nel tuo server, non ha bisogno di SQL Injection per distruggere i dati.
Reza Aghaei

5
Questa è la risposta migliore, mostra un modo in cui convalida la preoccupazione degli OP si tratta di un bug / difetto di sicurezza. Le prestazioni e la verifica del futuro a parte la concatenazione dei datetimes in SQL, ad esempio, non sono solo un odore o un debito tecnologico . @RezaAghaei la domanda non ha mai menzionato Server-Side, potrebbe essere un'app Windows con SQLExpress - in entrambi i casi questo non è un criterio per la domanda. Chiunque potrebbe dire, ma chi ha accesso alle impostazioni del server per confutare questa eccellente risposta, proprio come chiunque potrebbe dire che dire dell'hosting di server condiviso o di un bug Y2K. Sono d'accordo con te che il server sia bloccato - non è solo un prerequisito.
Jeremy Thompson,

2
Potresti fornire un esempio di ciò che stavi dicendo sul inttipo?
johnnyRose

1
So che sono passate alcune settimane da quando hai risposto a questa domanda, ma sarebbe possibile per te modificare il tuo post e aggiungere un esempio di come puoi definire un segno negativo personalizzato?
johnnyRose

23

"SELECT * FROM Table1 WHERE Id =" + intVariable.ToString ()


Sicurezza
Va bene.
Gli aggressori non possono iniettare nulla nella variabile int digitata.

Prestazioni
non OK.

È preferibile utilizzare i parametri, quindi la query verrà compilata una volta e memorizzata nella cache per l'utilizzo successivo. La prossima volta, anche con valori di parametro diversi, la query viene memorizzata nella cache e non è necessario compilare nel server di database.

Stile di codifica
Cattiva pratica.

  • I parametri sono più leggibili
  • Forse ti fa abituare a query senza parametri, quindi forse hai commesso un errore una volta e usi un valore stringa in questo modo e quindi probabilmente dovresti dire addio ai tuoi dati. Cattiva abitudine!


"SELECT * FROM Product WHERE Id =" + TextBox1.Text


Anche se non è la tua domanda, ma forse utile per i futuri lettori:


Disastro di sicurezza !
Anche quando il Idcampo è intero, la tua query potrebbe essere soggetta a SQL Injection. Supponiamo di avere una query nella tua applicazione "SELECT * FROM Table1 WHERE Id=" + TextBox1.Text, un utente malintenzionato può inserire nella casella di testo 1; DELETE Table1e la query sarà:

"SELECT * FROM Table1 WHERE Id=1; DELETE Table1"

Se non desideri utilizzare la query parametrizzata qui, dovresti utilizzare i valori digitati:

string.Format("SELECT * FROM Table1 WHERE Id={0}", int.Parse(TextBox1.Text))


La tua domanda


La mia domanda è nata perché un collega ha scritto una serie di query che concatenano valori interi e mi chiedevo se fosse una perdita di tempo esaminarle e risolverle tutte.

Penso che cambiare questi codici non sia una perdita di tempo. In effetti il ​​cambiamento è consigliato!

se il tuo collega utilizza variabili int, non ha rischi per la sicurezza, ma penso che cambiare quei codici non sia una perdita di tempo e in effetti cambiare quei codici è raccomandato. Rende il codice più leggibile, più manutenibile e rende l'esecuzione più veloce.


Anche la prima opzione non va bene per la sicurezza. Il comportamento di .ToString()è determinato da un elemento di configurazione del sistema operativo che è facile da modificare per includere testo arbitrario.
Joel Coehoorn

18

In realtà ci sono due domande in una. E la domanda dal titolo ha ben poco a che fare con le preoccupazioni espresse dall'OP nei commenti successivi.

Anche se mi rendo conto che per l'OP è il loro caso particolare che conta, per i lettori provenienti da Google, è importante rispondere alla domanda più generale, che può essere formulata come "è la concatenazione sicura quanto le dichiarazioni preparate se mi sono assicurato che ogni letterale che sto concatenando è sicuro? ". Quindi, vorrei concentrarmi su quest'ultimo. E la risposta è

Assolutamente no.

La spiegazione non è così diretta come vorrebbe la maggior parte dei lettori, ma farò del mio meglio.

Stavo riflettendo sulla questione per un po ', risultando nell'articolo (sebbene basato sull'ambiente PHP) in cui ho cercato di riassumere tutto. Mi è venuto in mente che la questione della protezione dall'iniezione SQL spesso sfugge ad alcuni argomenti correlati ma più ristretti, come l'escape di stringhe, il casting dei tipi e simili. Sebbene alcune delle misure possano essere considerate sicure se prese da sole, non esiste un sistema né una semplice regola da seguire. Il che lo rende un terreno molto scivoloso, mettendo troppo sull'attenzione e l'esperienza dello sviluppatore.

La questione dell'SQL injection non può essere semplificata a una questione di particolare problema di sintassi. È più ampio della media degli sviluppatori abituati a pensare. È anche una questione metodologica . Non è solo "Quale particolare formattazione dobbiamo applicare", ma anche " Come deve essere fatto".

(Da questo punto di vista, un articolo di Jon Skeet citato nell'altra risposta sta andando piuttosto male che bene, poiché è di nuovo pignolo su alcuni casi limite, concentrandosi su un particolare problema di sintassi e non riuscendo ad affrontare il problema per intero.)

Quando stai cercando di affrontare la questione della protezione non nel suo insieme ma come un insieme di diversi problemi di sintassi, stai affrontando una moltitudine di problemi.

  • l'elenco delle possibili scelte di formattazione è davvero enorme. Significa che si possono facilmente trascurare alcuni. Oppure confonderli (usando ad esempio l' escape di stringhe per l' identificatore ).
  • Concatenazione significa che tutte le misure di protezione devono essere eseguite dal programmatore, non dal programma. Questo problema da solo porta a diverse conseguenze:
    • tale formattazione è manuale. Manuale significa estremamente soggetto a errori. Si potrebbe semplicemente dimenticare di applicare.
    • inoltre, c'è la tentazione di spostare le procedure di formattazione in qualche funzione centralizzata, confondendo ancora di più le cose e rovinando i dati che non andranno al database.
  • quando sono coinvolti più sviluppatori, i problemi si moltiplicano per un fattore dieci.
  • quando si usa la concatenazione, non si può dire a colpo d'occhio una query potenzialmente pericolosa: sono tutte potenzialmente pericolose!

A differenza di quel pasticcio, le dichiarazioni preparate sono davvero il Santo Graal:

  • può essere espresso sotto forma di una semplice regola facile da seguire.
  • è essenzialmente una misura non rilevabile, significa che lo sviluppatore non può interferire e, volontariamente o meno, rovinare il processo.
  • la protezione dall'iniezione è in realtà solo un effetto collaterale delle dichiarazioni preparate, il cui vero scopo è produrre affermazioni sintatticamente corrette. E un'affermazione sintatticamente corretta è a prova di iniezione al 100%. Tuttavia, abbiamo bisogno che la nostra sintassi sia corretta nonostante qualsiasi possibilità di iniezione.
  • se utilizzato tutto intorno, protegge l'applicazione indipendentemente dall'esperienza dello sviluppatore. Diciamo, c'è una cosa chiamata iniezione di secondo ordine . E un'illusione molto forte che dice "per proteggere, sfuggire a tutti gli input forniti dall'utente ". Combinati insieme, portano all'iniezione, se uno sviluppatore si prende la libertà di decidere, cosa deve essere protetto e cosa no.

(Pensando ulteriormente, ho scoperto che l'attuale set di segnaposto non è sufficiente per le esigenze della vita reale e deve essere esteso, sia per le strutture di dati complesse, come gli array, sia per le parole chiave o gli identificatori SQL, che a volte devono essere aggiunti al interrogare dinamicamente anche, ma uno sviluppatore è lasciato disarmato per un caso del genere e costretto a ripiegare sulla concatenazione di stringhe, ma questa è un'altra questione).

È interessante notare che la controversia di questa domanda è provocata dalla natura molto controversa di Stack Overflow. L'idea del sito è quella di avvalersi di particolari domande degli utenti che chiedono direttamente per raggiungere l'obiettivo di avere un database di risposte generiche adatte agli utenti che provengono dalla ricerca . L'idea di per sé non è male , ma fallisce in una situazione come questa: quando un utente pone una domanda molto ristretta , in particolare per ottenere un argomento in una disputa con un collega (o per decidere se vale la pena refactoring del codice). Mentre la maggior parte dei partecipanti esperti sta cercando di scrivere una risposta, tenendo presente la missione di Stack Overflow nel suo complesso, rendendo la loro risposta valida per il maggior numero possibile di lettori, non solo per l'OP.


10
Non rispondere alla domanda
edc65

La maggior parte dei database rileva le query parametrizzate già utilizzate dall'uguaglianza delle stringhe SQL, quindi il vecchio metodo di preparazione e utilizzo sembra obsoleto per me. Queste maniglie possono essere utilizzate solo entro un certo ambito e richiedono una codifica per tenere traccia della maniglia. Le query parametrizzate dovrebbero, a mio avviso, essere utilizzate direttamente, in modo che i piani di query possano essere riutilizzati senza gestire il tracciamento e anche tra diverse applicazioni.
Erik Hart

15

Non pensiamo solo a considerazioni sulla sicurezza o sulla protezione dai tipi.

Il motivo per cui si utilizzano query parametrizzate è migliorare le prestazioni a livello di database. Dal punto di vista del database, una query parametrizzata è una query nel buffer SQL (per usare la terminologia di Oracle anche se immagino che tutti i database abbiano internamente un concetto simile). Quindi, il database può contenere una certa quantità di query in memoria, preparate e pronte per essere eseguite. Queste query non devono essere analizzate e saranno più veloci. Le query eseguite di frequente si trovano generalmente nel buffer e non necessitano di analisi ogni volta che vengono utilizzate.

SALVO CHE

Qualcuno non usa query parametrizzate. In questo caso, il buffer viene continuamente scaricato da un flusso di query quasi identiche ognuna delle quali deve essere analizzata ed eseguita dal motore di database e le prestazioni ne risentono a tutto tondo poiché anche le query eseguite frequentemente finiscono per essere rianalizzate molte volte a giorno. Ho ottimizzato i database per vivere e questa è stata una delle maggiori fonti di frutta a bassa portata.

ADESSO

Per rispondere alla tua domanda, SE la tua query ha un numero limitato di valori numerici distinti, probabilmente non causerai problemi e potresti effettivamente migliorare le prestazioni all'infinito. SE tuttavia ci sono potenzialmente centinaia di valori e la query viene chiamata molto, influenzerai le prestazioni del tuo sistema, quindi non farlo.

Sì, puoi aumentare il buffer SQL, ma alla fine è sempre a scapito di altri usi più critici della memoria come la memorizzazione nella cache di indici o dati. Morale, usa query parametrizzate in modo abbastanza religioso in modo da poter ottimizzare il tuo database e utilizzare più memoria del server per le cose che contano ...


8

Per aggiungere alcune informazioni alla risposta di Maciek:

È facile modificare le informazioni sulla cultura di un'app di terze parti .NET chiamando la funzione principale dell'assembly per riflessione:

using System;
using System.Globalization;
using System.Reflection;
using System.Threading;

namespace ConsoleApplication2
{
  class Program
  {
    static void Main(string[] args)
    {
      Assembly asm = Assembly.LoadFile(@"C:\BobbysApp.exe");
      MethodInfo mi = asm.GetType("Test").GetMethod("Main");
      mi.Invoke(null, null);
      Console.ReadLine();
    }

    static Program()
    {
      InstallBobbyTablesCulture();
    }

    static void InstallBobbyTablesCulture()
    {
      CultureInfo bobby = (CultureInfo)CultureInfo.InvariantCulture.Clone();
      bobby.DateTimeFormat.ShortDatePattern = @"yyyy-MM-dd'' OR ' '=''";
      bobby.DateTimeFormat.LongTimePattern = "";
      bobby.NumberFormat.NegativeSign = "1 OR 1=1 OR 1=";
      Thread.CurrentThread.CurrentCulture = bobby;
    }
  }
}

Funziona solo se la funzione principale di BobbysApp è pubblica. Se Main non è pubblico, potrebbero esserci altre funzioni pubbliche che potresti chiamare.


1
Non devi nemmeno farlo tramite codice. Puoi aggiungere l'iniezione direttamente nelle Impostazioni internazionali di Windows. Vedi la mia risposta.
Kaspars Ozols,

2
Chi può modificare le impostazioni del server o chi può strofinare tale codice nel server? Se una persona può farlo nel tuo server, non ha bisogno di SQL Injection per distruggere i dati.
Reza Aghaei

7

Secondo me se puoi garantire che il parametro con cui lavori non conterrà mai una stringa è sicuro ma non lo farei comunque. Inoltre, vedrai un leggero calo delle prestazioni dovuto al fatto che stai eseguendo la concatenazione. La domanda che ti farei è perché non vuoi usare i parametri?


1
Non è che non voglio usare parametri, sto usando parametri. Un collega ha scritto un codice come questo che ho modificato per essere parametrizzato oggi, il che mi ha fatto pensare alla domanda.
johnnyRose

Ok. Grande. È una best practice utilizzare i parametri. In questo modo non devi preoccuparti di cose come sql injection. Inoltre, se stai creando una query dinamica, puoi anche utilizzare parametri indipendentemente dalla complessità delle tue query. Usa semplicemente lo stile @ 1 ... @ n quando li costruisci. E aggiungili alla raccolta di parametri con il valore desiderato.
Max

@johnyRose C'è un altro punto per usare i parametri: i programmi si evolvono e cambiano. È possibile utilizzare la concatenazione solo per le stringhe, ma ciò non garantisce che qualcuno implementi il ​​refactoring che modifica un tipo di parametro e che le modifiche possano introdurre la vulnerabilità di SQL Injection.
lerthe61

3

Va bene ma non è mai sicuro .. e la sicurezza dipende sempre dagli input, ad esempio se l'oggetto di input è TextBox, gli aggressori possono fare qualcosa di complicato poiché la casella di testo può accettare stringhe, quindi devi inserire una sorta di convalida / conversione per poter impedire agli utenti l'input sbagliato. Ma il fatto è che non è sicuro. Semplicemente così.


Questa è una stringa però. Sto parlando di altri tipi di dati, come interi, booleani o datetimes.
johnnyRose

@johnnyRose Sì, ho visto un esempio molto carino sopra che hai contrassegnato come risposta da Kaspards .. e un'ottima risposta in quanto utilizza il tipo di dati datetime come esempio che è raro. :) Spero che tu sia già convinto che non sia sicuro e meglio usare i parametri in qualsiasi tipo di tipo di dati
japzdivino

Non ho mai avuto dubbi sul fatto che fosse più sicuro usare i parametri. La mia domanda si riferiva a implementazioni fortemente tipizzate.
johnnyRose

Sì .. sono d'accordo. e questa è anche un'ottima domanda che può aiutare i futuri lettori :)
japzdivino

-2

No, in questo modo puoi ottenere un attacco SQL injection. Ho scritto un vecchio articolo in turco che mostra come qui . Esempio di articolo in PHP e MySQL ma il concetto funziona allo stesso modo in C # e SQL Server.

Fondamentalmente attacchi nel modo seguente. Consideriamo che hai una pagina che mostra le informazioni in base al valore ID intero. Non hai parametrizzato questo valore, come sotto.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=24

Ok, presumo che tu stia usando MySQL e io attacco in questo modo.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII((SELECT%20DATABASE()))

Notare che qui il valore inserito non è una stringa. Stiamo cambiando il valore di char in int usando la funzione ASCII. È possibile eseguire la stessa operazione in SQL Server utilizzando "CAST (YourVarcharCol AS INT)".

Dopodiché utilizzo le funzioni di lunghezza e sottostringa per trovare il nome del tuo database.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=LEN((SELECT%20DATABASE()))

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR(SELECT%20DATABASE(),1,1))

Quindi, utilizzando il nome del database, inizi a ottenere i nomi delle tabelle nel database.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR((SELECT table_name FROM INFORMATION_SCHEMA.TABLES LIMIT 1),1,1))

Ovviamente devi automatizzare questo processo, poiché ottieni solo UN carattere per query. Ma puoi automatizzarlo facilmente. Il mio articolo mostra un esempio in watir . Utilizzo di una sola pagina e valore ID non parametrizzato. Posso imparare ogni nome di tabella nel tuo database. Dopodiché posso cercare tabelle importanti. Ci vorrà del tempo ma è fattibile.


2
La mia domanda si riferisce a un linguaggio fortemente tipizzato. Sebbene la tua spiegazione sia ottima per le lingue con digitazione flessibile, il valore inserito è ancora una stringa.
johnnyRose

Nessun valore inserito è intero. Ottieni char e cambialo in intero usando la funzione ASCII MySQL. Fai la stessa cosa in SQL Server usando CAST (YourCharValue AS INT)
Atilla Ozgur

Intendevo qualcosa del genere:public void QuerySomething(int id) { // this will only accept an integer }
johnnyRose

-3

Bene ... una cosa è certa: la sicurezza NON va bene, quando concatenate una stringa (presa dall'utente) con la vostra stringa di comando SQL. Non importa ogni volta che la clausola where fa riferimento a un numero intero oa qualsiasi tipo; potrebbero verificarsi iniezioni.

Ciò che conta in SQL Injection è il tipo di dati della variabile utilizzata per ottenere il valore dall'utente.

Supponiamo di avere un numero intero nella clausola where e:

  1. la variabile utente è una stringa. Allora ok, non è molto facile iniettare (usando UNION) ma è molto facile aggirare usando 'OR 1 = 1' - come attacchi ...

  2. Se la variabile utente è un numero intero. Quindi di nuovo possiamo 'testare' la forza del sistema superando insoliti test di numeri grandi per crash del sistema o anche per un buffer overflow nascosto (sulla stringa finale) ...;)

Forse i parametri per le query o (ancora meglio - imo) per le Stored Procedures non sono sicuri al 100% contro le minacce, ma sono la misura meno richiesta (o quella elementare se preferisci) per minimizzarle.


Penso che potresti aver frainteso la domanda. Sto parlando di tipi non di stringa.
johnnyRose

Ciao JonnyRose ... grazie per la tua nota. Capisco la tua domanda, ma ho solo messo la mia risposta in una forma più generale. Per il caso non di stringa, controllare il mio (2) punto. ;)
Andreas Venieris
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.