Avatar billede nemlig Professor
12. december 2007 - 21:48 Der er 19 kommentarer og
2 løsninger

Sikkerhed mod SQl-injektion

Hej.
Jeg har en kontaktform med nogle input-felter, som er defineret jf. nedenfor:
Men sikkerheden er vist nok hullet som en si.
Kan I bidrage lidt med, hvad der kan gøres.

<input type="text" name="adresse1" size="40">

Jeg smider dem i MySQL sådan her:
$sql = "INSERT INTO tabelnavn SET                adresse1='".$_POST['adresse1']."'";
database($sql);


Og database funktionen ser sådan her ud:
function database($sql){//Funktion der laver alm databasekald og returnerer resultatet
  $config = ini();//Hent databaseparametre
  $conn = mysql_connect($config[db_serv],$config[db_user],$config[db_pass]);//Åben databaseforbindelse
  if (!$conn) {
  die('Could not connect: ' . mysql_error());
  }
  $res = mysql_db_query($config[db_base],$sql); //Udfør forespørgsel
  mysql_close($conn);//Luk databaseforbindelse
  if (!$res) {//Tjek om det gik godt
    die("<b>Databasefejl:<br></b>" . mysql_error($conn) ."<b><br>MySQL-sætningen var:<br></b>". $sql);//Udskriv fejlmelding og stop udførsel
  }
  return $res;//Returner resultat af forespørgsel
}
Avatar billede nielle Nybegynder
12. december 2007 - 22:06 #2
Avatar billede nemlig Professor
12. december 2007 - 22:13 #3
Jeps - jeg er i gang med at kigge begge steder.
Men jeg kan ikke helt gennemskue, hvordan jeg i ovenstående eksempel kan anvende "mysql_real_escape_string". Jeg leger lidt med det, men har I et nemt forslag, vil jeg da gerne se det.
Avatar billede nielle Nybegynder
12. december 2007 - 22:18 #4
Det skal gøres på data *før* at de kommer i SQL strengen:

$adresse1 = mysql_real_escape_string($_POST['adresse1']);

$sql = "INSERT INTO tabelnavn SET adresse1='$adresse1'";
database($sql);
Avatar billede nemlig Professor
12. december 2007 - 22:21 #5
Ok tusind tak I 2. Sender I lige et svar.
Avatar billede arne_v Ekspert
12. december 2007 - 22:28 #6
Hvis nyere PHP saa var mysqli og prepared statement et godt alternativ.
Avatar billede nemlig Professor
12. december 2007 - 22:36 #7
Hov - jeg får følgende fejl pr. inputfelt:

Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: Access denied for user 'ODBC'@'localhost' (using password: NO) in C:\wamp\www\hummelmosen\kontaktform.php on line 31

Warning: mysql_real_escape_string() [function.mysql-real-escape-string]: A link to the server could not be established in C:\wamp\www\hummelmosen\kontaktform.php on line 31
Avatar billede coderdk Praktikant
12. december 2007 - 22:59 #8
din database-funktion er ikke så smart, da den opretter en connection for hver query... Connect til databasen én gang, og brug så den connection til samtlige queries... Syntaksen for mysql_real_escape_string er mysql_real_escape_string(unescaped_string, database_connection) - Du kan dog nok bruge mysql_escape_string i stedet (uden connection).
Avatar billede jkampmann Nybegynder
12. december 2007 - 23:06 #9
svar
Avatar billede pidgeot Nybegynder
13. december 2007 - 11:03 #10
Du skal *ikke* bruge den alm. escape_string, kun real_escape_string (og da PHP husker den seneste connection kan du faktisk udelade connectionen, såfremt den er åben - hvilket den bør være). Hvis du bruger mysql_escape_string risikerer du problemer hvis forbindelsen bruger et multi-byte tegnsæt, da den opererer på byte-niveau, og ikke tegn-niveau.

Helt optimalt er at benytte mysqli og parameters (der har før været fejl i databasernes escaping-kode), men det er ikke altid en mulighed.
Avatar billede coderdk Praktikant
13. december 2007 - 12:37 #11
Yep, hvis du bruger andet end ISO-8859-1/Latin-1 som tegnsæt, må du ikke bruge mysql_escape_string - Hvis du gør, er den ok - Men hellere bare væn dig til at bruge mysql_real_escape_string :)

Jeg ville dele din database-funktion op i to, en der connecter og en der fyrer queries af - Eller endnu bedre - Brug en databasewrapper som f.eks. PEAR::MDB2 - http://pear.php.net/package/MDB2

Eller som pidgeot skriver, brug mysqli og prepared statements!
Avatar billede nielle Nybegynder
13. december 2007 - 18:27 #12
Springer over på denne her. :^)
Avatar billede nemlig Professor
13. december 2007 - 19:12 #13
Hold da op, hvor er jeg en klovn. I min funktionsliste ligger der i forvejen en funktion, som sikrer mod SQl-injektion. Den ser sådan her ud:

function mysqlRealEscapeString($input)
{
  $output = ''; //Bruges til output senere.
  $config = ini();//Hent databaseparametre
  $conn = mysql_connect($config[db_serv],$config[db_user],$config[db_pass]);//Åben databaseforbindelse
  $output = mysql_real_escape_string($input);
  mysql_close($conn);//Luk databaseforbindelse
  return $output;
}

Og jeg anvender så funktionen på denne måde:

$adresse1 = MysqlRealEscapeString($_POST['adresse1']);

Og det virker. Jeg forstår ikke, hvorfor den virker jf. kommentarerne ovenfor om gentagne connects.
Avatar billede pidgeot Nybegynder
13. december 2007 - 19:44 #14
Den fungerer, fordi der er en forbindelse den kan tage et tegnsæt fra - men det er enormt ineffektiv kode at åbne og lukke forbindelsen konstant.
Avatar billede nemlig Professor
13. december 2007 - 19:59 #15
Jeg forstår ikke, hvorfor den åbner og lukker hele tiden. Funktionen SQL bliver da kun kaldt 1 gang??
Skal jeg opsplitte funtionen i 2, således jeg connecter med:

$config = ini();//Hent databaseparametre
  $conn = mysql_connect($config[db_serv],$config[db_user],$config[db_pass]);//Åben databaseforbindelse
  if (!$conn) {
  die('Could not connect: ' . mysql_error());
  }

Derefter:

$res = mysql_db_query($config[db_base],$sql); //Udfør forespørgsel
  mysql_close($conn);//Luk databaseforbindelse
  if (!$res) {//Tjek om det gik godt
    die("<b>Databasefejl:<br></b>" . mysql_error($conn) ."<b><br>MySQL-sætningen var:<br></b>". $sql);//Udskriv fejlmelding og stop udførsel
  }
  return $res;//Returner resultat af forespørgsel
}
Avatar billede mungojerrie Nybegynder
13. december 2007 - 21:26 #16
hvorfor vil man bruge databasen til at undgå sql-injection, det kan php da selv klare, så er man også fri for at kalde fra webserver til database server hver gang.......
Avatar billede coderdk Praktikant
14. december 2007 - 12:55 #17
Yep, nemlig, split den op i to så du kun connecter én gang :)
Avatar billede pidgeot Nybegynder
14. december 2007 - 13:04 #18
Mungojerrie, hvis du tænker på addslashes/magic quotes, så tager du komplet fejl. Den kan ikke bruges, da der er andre tegn der kan bruges end dem den håndterer (for ikke at tale om alle de problemer du kan få hvis du bruger et multi-byte tegnsæt til kommunikation med databasen).

Det er ikke uden grund at den anbefalede måde at skrive sikker kode på er at fjerne magic quotes og håndtere det med parameters (eller databasens escaping-funktion, om nødvendigt) - det holder ikke at bruge addslashes eller på anden måde skrive sin egen escaping, fordi du ikke har begreb om hvad der kan forårsage problemer, og næppe får skrevet kode der håndterer forskellige tegnsæt korrekt.

Derudover forsvinder magic quotes langt om længe i PHP6 - så det er heller ikke en løsning der er holdbar i længden.
Avatar billede nemlig Professor
20. december 2007 - 14:31 #19
Jeg takker for alle input. Meld jer lige på banen I andre, så jeg kan tildele point.
Avatar billede pidgeot Nybegynder
20. december 2007 - 14:45 #20
Jeg ved ikke om det inkluderer mig, men ellers står det dig frit for at afvise mit svar :)
Avatar billede coderdk Praktikant
20. december 2007 - 17:34 #21
Ingen til mig :)
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