[PHP] Schutz gegen SQL Injection

01/05/2013 12:33 PoziCs#1
Hallo,
in einem Projekt von mir wird eine Information aus der URL per GET abgefragt.
Danach wird die Information mit der aus einer MySQL Datenbank abgeglichen.
Das sieht dann ungefähr so aus:

localhost/verkaufen.php?item=Wolle

Nun habe ich gelesen, dass man sich vor Eingaben schützen sollte, die Befehle einschleusen.
Reicht das, wenn ich das folgendermaßen mache?

PHP Code:
$item $_GET['item'];
$item preg_replace("/[^a-zA-Z0-9_\-]+/"""$item);
$item mysql_real_escape_string($item); 


//Hier unten wird dann mit $item gearbeitet


echo "Du hast " $item " verkauft!"
Danke im Vorraus
01/05/2013 12:37 Yakiyo#2
Von PHP habe ich nicht so viel Ahnung, aber schau dir das mal an: [Only registered and activated users can see links. Click Here To Register...]

@Deine Frage
Probier's doch einfach aus ;)
01/05/2013 12:42 PoziCs#3
Ja ich habe es schon mit "SQL Injection Scanner Tools" versucht, die haben angeblich nix gefunden, aber ich bin mir da nicht so sicher deswegen frage ich mal aber danke für die Antwort^^
01/05/2013 12:42 nkkk#4
Quote:
Originally Posted by PoziCs View Post
Hallo,
in einem Projekt von mir wird eine Information aus der URL per GET abgefragt.
Danach wird die Information mit der aus einer MySQL Datenbank abgeglichen.
Das sieht dann ungefähr so aus:

localhost/verkaufen.php?item=Wolle

Nun habe ich gelesen, dass man sich vor Eingaben schützen sollte, die Befehle einschleusen.
Reicht das, wenn ich das folgendermaßen mache?

PHP Code:
$item $_GET['item'];
$item preg_replace("/[^a-zA-Z0-9_\-]+/"""$item);
$item mysql_real_escape_string($item); 


//Hier unten wird dann mit $item gearbeitet


echo "Du hast " $item " verkauft!"
Danke im Vorraus
mm ich kenn zwar die php regexp sytax nicht aber wenn "/[^a-zA-Z0-9_\-]+/" dafür sorgt das nur buchstaben, ziffern und die - ,_ zeichen zugelassen werden ist das genug, dann bruchst du auch mysql_real_escape_string nicht mehr.
01/05/2013 12:45 Yakiyo#5
Quote:
Originally Posted by PoziCs View Post
Ja ich habe es schon mit "SQL Injection Scanner Tools" versucht, die haben angeblich nix gefunden, aber ich bin mir da nicht so sicher deswegen frage ich mal aber danke für die Antwort^^
Die sind normalerweise eig. recht genau, aber manuell ist immernoch am besten.
01/05/2013 12:50 PoziCs#6
Alles klar Danke!
01/06/2013 14:03 martrixmarc#7
verwende doch einfach mysql_real_escape_string(), das eigentlich das beste was du tun kannst ^^
01/06/2013 14:07 nkkk#8
Quote:
Originally Posted by martrixmarc View Post
verwende doch einfach mysql_real_escape_string(), das eigentlich das beste was du tun kannst ^^
nein wenn man nicht unbedingt sonderzeichen braucht (und das ist meistens der fall) ist eine eigene funtion (die alle zeichen ausser Ziffren und Buchstaben löscht) wie er sie hat besser
01/06/2013 14:08 martrixmarc#9
Ja, nur im Normalfall verwendet man auch Sonderzeichen ^^, es kommt halt immer auf den Anwendungsort an.
01/06/2013 14:18 nkkk#10
Quote:
Originally Posted by martrixmarc View Post
Ja, nur im Normalfall verwendet man auch Sonderzeichen ^^, es kommt halt immer auf den Anwendungsort an.
man kann die whitelist natürlich um "harmlose" sonderzeichen erweitern.
und das reicht dan wirklich für 90% der fälle.

das problem bei mysql_real_escape_string() ist, das die db ja nicht das ende ist, sondern das die daten danach auchnoch weiterverwendet werden. und selbst wenn die daten ohne probeme in die db kommen, kann das programm was die daten hinterher weiterverarbeitet damit probleme bekommmen und Sicherheitslücken öffnen.
01/06/2013 14:21 martrixmarc#11
Deswegen verwende ich bei jeder weiteren verarbeitung immer mysql_real_escape_string, dafür habe ich mir ne klasse gemacht und ich hab mich ziemlich daran gewöhnt, da alle abfragen dann einfach durch das gehen.
01/06/2013 18:16 MrSm!th#12
#moved
01/06/2013 18:54 PseudoPsycho#13
Also, denn geb' ich auch mal meinen Senf dazu:
Am besten verwendet man MySQLi prepared statements, dann hat man schonmal 'ne Typ-Abfrage, ohne wirklich was tun zu müssen.
mysql_real_escape_string, bzw. $mysqli->real_escape_string ist an sich 'ne gute Sache, funktioniert aber natürlich nur bei Strings. Wenn es sich bei der abgefragten get/post-Variable z.B. um einen Integer handelt, sollte man stattdessen intval() verwenden, etc.
Damit reservierte Ausdrücke nicht in jedem Fall einen Fehler schmeißen, schreibt man die Variablen am besten auch noch in Backticks.
Also im Endeffekt etwas wie:
PHP Code:
$db=mysqli_connect(...);
$id=intval($_GET['id']);
$nick=$db->real_escape_string($_GET['nick']);
$sql=$db->prepare('INSERT INTO `mytable` (`id`, `nick`) VALUES (`?`, `?`)');
if(
$db->errno>0)
    echo 
$db->errno,': ',$db->error;
$sql->bind_param('is'$id$nick);
$sql->execute();
$sql->close(); 
01/07/2013 22:55 Synatex#14
Ich würde dir von msqli abraten. Ganz einfach: Es sind einfach nur "verbesserte" Versionen der normalen MySQL Funktionen, in OOP verpackt. Wenn du dir die Mühe machen solltest:

1.) Baue dir deine eigene DB Klasse mit der du das erreichst was du willst
2.) Oder benutz PDO. PDO bietet alles was mysql(i) bietet, ist universal einsetzbar, kommt mit fast allen Datenbanken von MySQL, MSSQL, PostGreSQL bis SQLite aus. Da biste auf der sicheren Seite.
01/07/2013 23:05 PseudoPsycho#15
Quote:
Originally Posted by Synatex View Post
Es sind einfach nur "verbesserte" Versionen der normalen MySQL Funktionen, in OOP verpackt.
Ganz genau. Und die Verbesserungen enthalten:
- Verschlüsselung (sichere Verbindung)
- Typvalidierung & Schutz vor SQL-Injections via prepared statements
Entsprechend ist es kein Wunder, dass von offizieller Seite her empfohlen wird, mysql nicht mehr zu verwenden und stattdessen mysqli einzusetzen. ;)