Avatar billede kjeldsted Novice
23. juni 2008 - 22:44 Der er 10 kommentarer og
1 løsning

MySQL injection

Hej Alle.

Jeg ville hører om der er nogle der kan give lidt råd til hvordan jeg kan undgå MySQL injection på mine PHP sider hvor jeg bruger MySQL forbindelser.

Hvordan validere jeg bedst inputs, som brugernavn og kode til logind, div. forms til ændring af brugeroplysninger m.m.?

Håber jeg kan få et par gode råd så jeg bliver lidt mere sikker.
Avatar billede pidgeot Nybegynder
23. juni 2008 - 22:51 #1
Kort og godt: brug mysqli-funktionerne og parameteriserede SQL-sætninger. På den måde er SQL injection umulig.

Udover det skal du også tænke på XSS - det håndterer du ved aldrig at udskrive nognen form for tekst direkte fra noget en bruger kan indtaste. I stedet skal du køre det gennem htmlspecialchars først for på den måde ikke at tillade at evt. HTML kan blive skrevet direkte ud. Hvis brugeren skal kunne lave noget med noget formatering, så bør du bruge et system a la BBCode til det.
Avatar billede kjeldsted Novice
24. juni 2008 - 00:22 #2
Jeg gør i forvejen som hovedregel det at jeg udskifter de to tegn '<' og '>' for at forhindre at brugeren indsætter fx JS koder.

Og kunne jeg få dig til at forklare lidt nærmere om "mysqli-funktionerne og parameteriserede SQL-sætninger"? Det er nemlig lige et punkt som jeg aldrig har fået undersøgt, hvilket er grunden til jeg søger hjælp hér ;-)
Avatar billede olebole Juniormester
24. juni 2008 - 00:28 #3
<ole>

http://dk.php.net/manual/en/book.mysqli.php
http://dk.php.net/manual/en/mysqli.prepare.php

Tjek eksemplerne og de andre funktioner i menuen  =)

/mvh
</bole>
Avatar billede kjeldsted Novice
24. juni 2008 - 00:50 #4
Mange tak olebole. Kigger på det i morgen eller hvornår der nu bliver tid.
Avatar billede kjeldsted Novice
26. juni 2008 - 16:43 #5
Hvis nu jeg sætter følgende linje indi koden før at der bliver kørt en MySQL forespørgsel hvor den finder et id fra en $_GET, vil jeg så kunne undgå en MySQL injection via denne id?

if(preg_match("/\D+/",$_GET['sektion'])){die('Der er sket en fejl. Id\'et for sektion er ugyldig. Hvis du kom fra et link så tryk tilbage og prøv igen. Fortsætter fejlen kontakt da webmaster.<script type="text/javascript">window.history.back();</script>');}
Avatar billede pidgeot Nybegynder
26. juni 2008 - 18:41 #6
Lige når det er tal, er is_numeric nok et bedre valg, men ja - lige netop hvor det er tal vil det.

Det hjælper bare ikke et hak de steder hvor der er tekst involveret - og det er nu engang pænere at holde sig til en måde at lave en given ting på *-)
Avatar billede kjeldsted Novice
26. juni 2008 - 19:43 #7
Nå, ja. Vist en smutter jeg ikke brugte in_numeric() lige her.. Gør jeg de andre steder med id. Og de steder hvor den indeholder tekst (dog meget sjældent disse er $_GET, som regel $_POST, tjekker jeg om der findes andet en [a-zA-Z_] i. Hvis der kun er [a-zA-Z_] burde man vel ikke kunne lave en MySQL injction....?
Avatar billede pidgeot Nybegynder
26. juni 2008 - 20:07 #8
Nej - men det er da et exceptionelt restriktivt tegnsæt du tillader så. Hvad med æ, ø, å og é (ja, den bruger vi også på dansk!)? Tegnsætning, inkl. mellemrum? Tal?

Der skal MEGET særlige omstændigheder til før man kan retfærdiggøre en kraftig begrænsning af de mulige tegn - ikke engang e-mail adresser kan man reelt sætte begrænsninger på, udover at de skal følge formen *@*.* - så gør nu dig selv den tjeneste at lave det ordentligt, ved at bruge parameters. Så gør du også dine brugere en tjeneste ved ikke at sætte besynderlige krav der ikke har nogen relevans

Kun hvis du på ingen mulig måde har adgang til mysqli (og du bør virkelig gøre alt hvad du kan for at få det!) bør du bruge noget andet - i det tilfælde skal du sende strenge gennem funktionen mysql_real_escape_string inden du sætter dem ind i din SQL-sætning. Det skal dog i allerhøjeste grad betragtes som en nødløsning, for der kan også være fejl i de escaping-funktioner - for at det ikke skal være løgn har der allerede været det *-)

Samtidigt skal du (uanset om du bruger parameters eller er tvunget til escaping) kode som om magic_quotes ikke er slået til(http://dk2.php.net/magic_quotes), og starte hver fil med at fjerne dem hvis de er der (du har sandsynligvis en fil hvor du gemmer dine loginoplysninger til databasen, og som inkluderes fra alle dine andre sider - det kan passende gøres i denne, så længe den inkluderes som det allerførste fra alle sider). Magic quotes er nemlig et forsøg fra PHP's side på at undgå injection ved at kalde addslashes på alt der kommer ind via GET, POST eller cookies - men det skaber i sig selv en masse problemer, hvorfor det fjernes fra PHP 6 *-)
Avatar billede kjeldsted Novice
26. juni 2008 - 21:01 #9
I så fald jeg bruger tekst i en $_GET er det typisk fordi jeg fx frem kalder funktioner el.lign. Og mine funktioner indeholder ikke special tegn ;-). De steder hvor brugeren indtaser tekst der skal gemmes i en mysql database bliver det altid gemt i $_POST og ALDRIG i $_GET. Derfor vil jeg ikke tillade disse tegn da sansynligheden for at det skal bruges i "ulovlig" forstand er 0 %. Og, hm. Nu har jeg ikke nærlæst hele php.net's artikel om mysqli (http://dk.php.net/manual/en/book.mysqli.php) men jeg sidder på en host hos One.com og vil da tro jeg ikke har adgang til dette :s.

Og mht. magic_quotes siger du egentlig at jeg i min config fil, der ganske rigtigt bliver included på alle sider, skal skrive:
set_magic_quotes_runtime(0);
?
Avatar billede pidgeot Nybegynder
26. juni 2008 - 21:48 #10
One *har* adgang til mysqli, og det bør enhver webhost der er bare nogenlunde seriøs også have. Check selv phpinfo ;)

Det er desuden komplet ligegyldigt om du bruger POST eller GET, begge dele er lige nemme mål for injection, så du skal sikre uanset - og som sagt er det bedre at bruge den rigtige fremgangsmåde hver gang *-)

Hvad magic_quotes angår, både og - hvis den var aktiveret skulle den fjernes, men det kræver en aktiv handling fra administratoren før den er det (jeg er ikke bekendt med nogen der bruger det, og One gør heller ikke), og hvis det endelig skulle være vil den funktion blive gjort ubrugelig med PHP6 (den vil faktisk generere en alvorlig fejl), så den skal som minimum lige have et check med get_magic_quotes_runtime inden da. Det store problem er magic_quotes_gpc, for den kan du ikke nå at ændre fra koden - det skal gøres ved at konfigurere PHP, fordi det er slået igennem inden din kode begynder at køre.

magic_quotes_gpc er det der gør at ' bliver til \' når det kommer ind - det duer ikke når man skriver ordentlig kode (fordi \ kommer med direkte), så det skal fjernes igen hvis det er aktivt - og fordi du meget vel kan teste på en lokal server hvor det er slået fra, for så at lægge det op hvor det er slået til.

Som jeg husker det bryder One sig ikke om at du forsøger at deaktivere det via et .htaccess-direktiv, og da du jo ikke har adgang til selve PHP-konfigurationen, må du så "fortryde" disse magic quotes ved at køre stripslashes på alt. Det er der kode til i kommentarerne på den PHP-dokumentationsside jeg linkede dig til, samt under "Disabling Magic Quotes" (linket til fra samme side som den kommentar).
Avatar billede kjeldsted Novice
27. september 2008 - 01:23 #11
Lukker
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester