# Vor SQL Injection schützen mit mysql_real_escape_string()



## Spelmann (14. Februar 2009)

Hallo zusammen,
Ich stelle dem User eine einfache Suchfunktion zur Verfügung.
Den Suchbegriff wollte ich mit _mysql_real_escape_string()_ maskieren, um manipulative Eingaben abzuwehren.
Also habe ich mir das so gedacht:


```
$suchbegriff = mysql_real_escape_string($_POST['suche']);
if($ergebnis = $db->query('SELECT * FROM liste WHERE suchbegriffe LIKE "%'.$suchbegriff.'%" ')){
```

So einfach scheint das aber wohl nicht zu funtionieren. Das Ganze erzeugt einen Fehler:


```
Warning: mysql_real_escape_string() [function.mysql-real-escape-string]:
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in...
```

Kann mir jemand erklären, was ich falsch gemacht habe und wie es richtig aussehen muss?


----------



## CookieBuster (14. Februar 2009)

Wenn ich den Fehler richtig Interpretiere hast du keine Verbindung zu deiner Datenbank und MySQL hergestellt. 

Diese Funktion funktioniert aber nur wenn man eine Verbindung zu MySQL hergestellt hat.

Ich rate dir erst einmal mit _get_magic_quotes_gpc()_ prüfen ob bereits Slashes gesetzt sind. Wenn ja diese ersteinmal mit _stripslashes()_ entfernen.


----------



## Spelmann (14. Februar 2009)

Hi CookieBuster,
ne die Datenbankanbindung steht.
ohne _mysql_real_escape_string()_ funktionierts auch.
Wozu soll ich _get_magic_quotes_gpc()_ einsetzen? Ich weiß doch was ich beim Testen ins Feld schreibe. Oder habe ich Dich nicht richtig verstanden?


----------



## Matthias Reitinger (14. Februar 2009)

Spelmann hat gesagt.:


> ne die Datenbankanbindung steht.


Bist du dir sicher, dass die Datenbankverbindung nicht erst durch den Aufruf von $db->query erstellt wird?


----------



## Spelmann (15. Februar 2009)

Mmh. Ich verstehe nicht wirklich was ihr meint.
Hier nochmal auführlicher mit der Datenbankanbindung:


```
require_once("include/db_connect.inc.php");
$db = Singleton::holeVerbindung();
$db->select_db('DB0815');
$suchbegriff = mysql_real_escape_string($_POST['suche']);
if($ergebnis = $db->query('SELECT * FROM liste WHERE suchbegriffe LIKE "%'.$suchbegriff.'%" ')){
```

Was verstehe ich da falsch? Wie gesagt, ohne _mysql_real_escape_string()_ ergibt die Anfrage ja ein Ergebnis!
Würde doch nicht gehen wenn ich keine Verbindung zur Datenbank hätte.
Oder mein ihr, der Befehl an der falschen Position?
So funktionierts aber auch nicht:


```
if($ergebnis = $db->query('SELECT * FROM liste WHERE suchbegriffe LIKE
"%'.mysql_real_escape_string($_POST['suche']).'%" ')){
```

Ich befürchte ich brauche eine etwas ausführlichere Erklärung, um zu verstehen worum es geht.
Vielen Dank.


----------



## Matthias Reitinger (15. Februar 2009)

Spelmann hat gesagt.:


> Würde doch nicht gehen wenn ich keine Verbindung zur Datenbank hätte.


Die Frage ist, wann genau die Verbindung zur Datenbank aufgebaut wird. Konkreter: wann [phpf]mysql_connect[/phpf] aufgerufen wird. Ich weiß nicht was alles in der Datenbank-Klasse passiert, aber möglicherweise wird die Verbindung erst aufgebaut, wenn sie wirklich gebraucht wird – also beim Aufruf von $db->query. Denn eigentlich sollte [phpf]mysql_real_escape_string[/phpf] die Verbindung vom letzten Aufruf von [phpf]mysql_connect[/phpf] verwenden. Ansonsten könntest du mal schauen, ob die Datenbank-Klasse nicht schon eine Methode anbietet, die sich um das Escaping kümmert. Dann wäre diese natürlich vorzuziehen.

Grüße, Matthias


----------



## Spelmann (15. Februar 2009)

Ach, Singleton ist überschaubar:


```
class Singleton{
static $db = null;
function holeVerbindung() {
if (self::$db == null){
self::$db = new mysqli ('localhost', 'root', 'trallala');
}
return self::$db;
}
```

Ich habe diesen Weg eine Datenbankverbindung herzustellen aus einem Tutorial. Verstehe den Vorgang aber nicht wirklich.
Lässt sich denn hieraus ersehen, ob die Verbindung erst nach der Formulierung der Abfrage (darum gehts doch, wie ich ahne zu verstehen) hergestellt wird?


----------



## ne0hype (15. Februar 2009)

Du solltest mysqli_real_escape_string() verweden!

http://de.php.net/manual/de/mysqli.real-escape-string.php


----------



## Flex (15. Februar 2009)

Da stimme ich zu. Die mysql_ und mysqli_ Funktionen sind voneinander getrennt, weshalb sie auch keine gegenseitigen Verbindungen nutzen können.
[phpf]mysqli_real_escape_string[/phpf] erwartet als ersten Parameter die aktuelle Verbindung, falls du es im prozeduralen Stil verwendest.


----------



## Spelmann (15. Februar 2009)

Ich danke euch für eure Geduld.
Ok. Ich hab es nun mit mysqli_real_escape_string() vesucht.
Bekomme ich auch einen Fehler:

```
Warning: mysqli_real_escape_string() expects exactly 2 parameters, 1 given in...
```

Ist der fehlende Parameter jetzt auch wieder die Datenbankanbindung?
Ich weiß dabei nicht wirklich worin der Unterschied zwischen Objektorientiert und Prozedural besteht.

Wenn die Maskierung innerhalb des query stattfindet ($db->query(...)) muß doch die Verbindung zur Datenbank stehen, oder nicht? Ich verstehe die Logik dahinter nicht.

Bin dankbar für weitere Hilfe, um meinem verrenkten Hirn auf die Sprünge zu helfen.


----------



## ne0hype (15. Februar 2009)

Anscheinend hast du meinen Beitrag nicht ganz gelesen.



> Du solltest mysqli_real_escape_string() verweden!
> 
> http://de.php.net/manual/de/mysqli.real-escape-string.php



Ich verweise hier nochmals auf das Manual hin: http://de.php.net/manual/de/mysqli.real-escape-string.php


----------



## Flex (15. Februar 2009)

Ja, das ist die fehlende Verbindung.

Diese musst du dir jetzt über dein Singleton holen.


----------



## ne0hype (15. Februar 2009)

Felix Jacobi hat gesagt.:


> Ja, das ist die fehlende Verbindung.
> 
> Diese musst du dir jetzt über dein Singleton holen.




JEIN ...

Wenn man sich das Manual genau anschaut wird man feststellen das es eine "Object oriented style" und  eine "Procedural style" gibt.

Da wird hier im "Object oriented style" sind wird es wohl wie auch im Manual beschrieben so gehen:


```
$city = $mysqli->real_escape_string($city);

/* this query with escaped $city will work */
if ($mysqli->query("INSERT into myCity (Name) VALUES ('$city')")) {
    printf("%d Row inserted.\n", $mysqli->affected_rows);
}
```

zum Unterschied mal die prozedurale Variante

```
$city = mysqli_real_escape_string($link, $city);
```


----------



## Spelmann (15. Februar 2009)

@ ne0hype
gelesen ja, verstanden nein.

@ Felix Jacobi
aber die Singleton steckt doch schon in _$db_ woher soll ich sie denn noch holen. Und wohin?


----------



## Flex (15. Februar 2009)

Den Schnippsel habe ich übersehen.


```
require_once("include/db_connect.inc.php");
$db = Singleton::holeVerbindung();
$db->select_db('DB0815');
$suchbegriff = $db->real_escape_string($_POST['suche']);
if($ergebnis = $db->query('SELECT * FROM liste WHERE suchbegriffe LIKE "%'.$suchbegriff.'%" ')){
```

Versuch es mal so.


----------



## ne0hype (15. Februar 2009)

$suchbegriff = $db->real_escape_string($_POST['suche']);


----------



## Spelmann (15. Februar 2009)

@ Felix Jacobi
Ok so funktionierts ohne Fehlermeldung.
Aber ist nun $db->real_escape_string() das Gleiche wie
mysql_real_escape_string() ?
Und wenn ja warum?

(Ich hoffe ich strapaziere Deine Geduld nicht zu sehr)


----------



## Flex (15. Februar 2009)

Also, PHP hat damals einen nativen MySQL Treiber (bin mir gerade wegen der Begrifflichkeit nicht sicher) erstellt, das sind die mysql_* Funktionen.
Mit PH5 hielt auch MySQLi in den PHP Kern Einzug. Überarbeitet mit der Unterstützung von Sun ist er schneller (heißt ja auch improved) und bietet eine prozedurale (die mysqli_* Funktionen) und einen objektorientierten Ansatz (die Klasse MySQLi). 

Wenn man PHP5 hat und sich keine Sorgen um Rückwärtskompatibilität machen muss, sollte man immer MySQLi verwenden. 
Wenn man nicht gerade einen Datenbankwrapper verwendet, wie aus dem Zend Framework, PDO oder ähnliches.


----------

