ADO.NET - SQL Injections (Best Practices 1)

Tags:    .net
Skrevet af Bruger #293 @ 21.03.2006
Jeg vil i den her "Best Practices" serie af artikler fokusere på et par grundlæggende best practices omhandlende brug af ADO.NET.
Artiklerne er affødt af at mange tilsyneladende ikke er bekendt med de forskellige faldgruber der kan opstå når man laver databasetilgang via ADO.NET og jeg vil her forsøge at rette op på nogle af disse. Vi starter i denne artikel blødt ud med at se på hvordan man overkommer et af de mest gængse sikkerhedsproblemer når man arbejder med databasetilgang.

SQL Injections



Enemy #1 og ikke uden grund. Ikke nok med at man alt for ofte ser semi-professionelle sites der overhovedet ikke beskæftiger sig med dette problem og som konsekvens er hullet som en si, når folk endelig håndterer det så er det somregel med en løsning der går ud på at replace tegnet single-qoutes i den ene eller anden udgave.

Det er som udgangspunkt også effektivt nok, det største problem i den forbindelse er at man kan glemme at replace en string inden den indsættes i SQL'en. Kan det lade sig gøre at glemme noget sådant, så er det blot et spørgsmål om tid før det rent faktisk sker!

Parameters



Løsningen er egentlig ganske enkel. Istedetfor at indsætte værdierne direkte i SQL'en, anvender man istedet parameters til formålet.

Det har minimum 2 fordele:

- Parameters beskytter automatisk mod SQL Injections
- Parameters gør SQL'en mere overskuelig

Så istedetfor den "gængse" løsning:

Fold kodeboks ind/udKode 


Anvendes istedet parameters, som mange af jer formentlig kender fra Stored Procedures.
Disse kan dog også anvendes til ganske almindelige SQL kald og det er det vi her vil gøre brug af:

Fold kodeboks ind/udKode 


Man sætter så dataene efterfølgende via Parameter collectionen der udbydes af IDbCommand objektet, i dette eksempel benytter jeg den specialiserede udgave til SQL Server:

Fold kodeboks ind/udKode 


Ulempen som det også fremgår af ovenstående er så at det hele kommer til at fylde lidt mere kode, dette synes jeg dog personligt ikke er et problem når man tager den øgede gennemskuelighed af SQL koden i betragtning og den sidegevinst at man helt slipper for at bekymre sig om SQL Injections.

Best Practice råd: Brug altid parameters til indsættelse af data i SQL sætninger, medmindre der er en meget god grund til at gøre en undtagelse.

Fodnote: Bemærk at parameters desværre ikke kan benyttes i WHERE IN (...) sætninger og at en replace af single-quote tegnet i dette tilfælde ikke løser problemet. Sørg derfor altid for at være særlig opmærksom på brug af denne konstrukt og lav passende input validering.

Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (8)

User
Bruger #2193 @ 21.03.06 22:42
Hvis "parameters" er .NET sidestykket til "prepared statements" i Java, er beskyttelsen mod SQL Injections kun en bi-virkning.
Hovedformålet med at trække parametrene ud, er at man sikrer at typerne er korrekte (ingen "sen" database type-cast på streng værdier) og hvis databasen understøtter det, oversættes sql sætningen kun første gang der stødes på den, herefter kan den oversatte (og optimerede) interne database version af sql sætningen med parametre, hentes frem (af SGA'en kalder Oracle vist deres) og parametrene til hvert kald kan blot puttes på plads med et minimum af CPU forbrug på database serveren.

Det er særligt brugbart hvis man skal loope x antal gange med en identisk sql opbygning, men med forskellige værdier.
Her bygger man kun sql sætningen en enkelt gang, og skifter parametre for hvert loop, og hvis databasen understøtter det, tjekkes syntaxen kun første gang og herefter køres der bare løs.

At man binder data typerne i programmet ved compile istedet for ved runtime, i forhold til sin sql sætning, byder naturligvis på den fordel som du nævner at man bliver tvunget til at lave lidt mere orden på sin kode og det bliver nok nemmere at læse.

Ellers en fin introduktion til ideen :)
User
Bruger #2193 @ 21.03.06 23:07
Lige et dumt spørgsmål:

Hvordan har du testet WHERE IN med parametre?

... "WHERE ID IN (@id1, @id2, @id3)"
og et parameter sættes for hver værdi?
eller

... "WHERE ID IN (@ids)"
og værdierne samles i din kode og sættes på en gang?
Mener ikke Java's prepared statements har problemer med WHERE IN ... så hvorfor skulle ADO.NET have det?M$ plejer ikke at forværre tingene når de kopierer, ups nej, lader sig inspirere, he he :D
User
Bruger #714 @ 21.03.06 23:08
Meget fin artikel omend den måske er lidt kort (du kunne måske godt have taget endnu et emne ind under denne artikel?).

Men artiklen er da skrevet i et rigtig let forståeligt sprog og det er jo bare herligt :D.
User
Bruger #2730 @ 22.03.06 07:50
Dejlig artikel om parameters, omend lidt kort. Fordelen ved parameters er, som der også bliver beskrevet ovenfor, at der tages højde for objekt konvertering, og faktisk også lokalisering (så vidt jeg husker, eks. datoformat)
User
Bruger #293 @ 23.03.06 00:49
#1, #3, #4:

Takker :)

Jeg tror dog I misforstår artiklen en smule da meningen ikke var at debattere parameters (eller hvad man nu vælger at kalde dem). Det er med vilje at fokus er holdt helt og aldeles på at komme SQL injections til livs uden for meget udenomssnak da det som titlen antyder er ment som tagende udgangspunkt i praktiske problemstillinger og iøvrigt gerne skulle være let læselig for begyndere.

Men det er selvfølgelig helt perfekt at I uddyber Parameters yderligere her i kommentar-delen :-)

Der bliver iøvrigt lidt mere kød på næste artikel :)

#2: Uden lige at have testet det vil jeg tro at "WHERE ID IN (@id1, @id2, @id3)" virker. I de tilfælde hvor jeg normaltvis har brug for det vil det dog være en noget mere omsonst løsning, så i det her tilfælde tager jeg udgangspunkt i "WHERE ID IN (@ids)". Jeg kan dog godt se at slutkommentaren kan misforståes og ikke burde tage udgangspunkt i min egen situation :)

(artiklen var oprindeligt postet som et indlæg på min blog, det kan være farligt når man senere konverterer den til en artikel :-))
User
Bruger #10057 @ 07.07.06 13:23
Kan man også bruge det der i ASP ? Altså ikke .Net ?
User
Bruger #815 @ 07.07.06 16:46
Herligt, endnumere omskrivning af min kode. Det er sgu snart nememre at starte helt forfra! :P
User
Bruger #5458 @ 24.10.06 00:42
Det er godt at du tager dette emne op. Det sted hvor jeg er i lære, viste min mester mig vigtigheden af at sikre sig af denne svaghed i SQL. Jeg prøvede umiddelbart efter at komme ind på forskellige sider, ved hjælp af denne simple teknik, og det lykkedes på forbavsende mange gange. Jeg prøvede dog kun på "små" hjemmesider, da det ikke var noget jeg havde tænkt mig at drage fordel af, men jeg kunne tænke mig at der var mange der ville, hvis de kunne. Og da det er en meget simpel teknik at mestre, synes jeg ikke at man bør lave kode, hvor SQL-Injections er mulig. Og man kan slet ikke tillade sig, ikke at tage højde for det, hvis det er noget man skal sælge videre.
Du skal være logget ind for at skrive en kommentar.
t