Just a little something I like to use....
$_GET = array_map('trim', $_GET);
$_POST = array_map('trim', $_POST);
$_COOKIE = array_map('trim', $_COOKIE);
$_REQUEST = array_map('trim', $_REQUEST);
if(get_magic_quotes_gpc()):
$_GET = array_map('stripslashes', $_GET);
$_POST = array_map('stripslashes', $_POST);
$_COOKIE = array_map('stripslashes', $_COOKIE);
$_REQUEST = array_map('stripslashes', $_REQUEST);
endif;
$_GET = array_map('mysql_real_escape_string', $_GET);
$_POST = array_map('mysql_real_escape_string', $_POST);
$_COOKIE = array_map('mysql_real_escape_string', $_COOKIE);
$_REQUEST = array_map('mysql_real_escape_string', $_REQUEST);
Seems to do the trick ALOT of the time, but I'm going to be honest, it can be a [EDITED] sometimes >_>
mysql_real_escape_string
(PHP 4 >= 4.3.0, PHP 5)
mysql_real_escape_string — Maskiert spezielle Zeichen innerhalb eines Strings für die Verwendung in einer SQL-Anweisung
Beschreibung
Maskiert spezielle Zeichen im unescaped_string unter Berücksichtigung des aktuellen Zeichensatzes der Verbindung, so dass das Ergebnis ohne Probleme in mysql_query() verwendet werden kann. Wenn Sie Binärdaten einfügen wollen, müssen Sie die Funktion auf jeden Fall verwenden.
mysql_real_escape_string() ruft die Funktion mysql_real_escape_string der MySQL-Bibliothek auf, die folgende Zeichen mit einem Backslash ('\') versieht: \x00, \n, \r, \, ', " und \x1a.
Die Funktion muss immer (mit wenigen Ausnahmen) verwendet werden, um Daten abzusichern, bevor sie per Query an MySQL übermittelt werden.
Parameter-Liste
- unescaped_string
-
Der zu maskierende String.
- Verbindungs-Kennung
-
Die MySQL-Verbindung. Wird die Verbindungskennung nicht angegeben, wird die letzte durch mysql_connect() geöffnete Verbindung angenommen. Falls keine solche Verbindung gefunden wird, wird versucht, eine Verbindung aufzubauen, wie es beim Aufruf von mysql_connect() ohne Angabe von Argumenten der Fall wäre. Falls zufällig keine Verbindung gefunden oder aufgebaut werden kann, wird eine Warnung der Stufe E_WARNING erzeugt.
Rückgabewerte
Gibt einen maskierten String oder im Fehlerfall FALSE zurück.
Beispiele
Beispiel #1 Einfaches mysql_real_escape_string()-Beispiel
<?php
// Verbindung herstellen
$link = mysql_connect('mysql_host', 'mysql_user', 'mysql_password')
OR die(mysql_error());
// Anfrage erstellen
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
?>
Beispiel #2 Ein beispielhafter SQL Injection Angriff
<?php
// Datenbankabfrage zur Ueberpruefung der Logindaten
$query = "SELECT * FROM users WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'";
mysql_query($query);
// Wir haben $_POST['password'] nicht geprueft, es koennte also alles darin
// stehen, was der User will. Zum Beispiel:
$_POST['username'] = 'aidan';
$_POST['password'] = "' OR ''='";
// Das bedeutet, der an MySQL gesendete Query wuerde sein:
echo $query;
?>
Die Abfrage, die an MySQL übermittelt wird:
SELECT * FROM users WHERE user='aidan' AND password='' OR ''=''
Dies würde jedermann erlauben, sich ohne valides Passwort einzuloggen.
Anmerkungen
Hinweis: Sie müssen eine Verbindung zu MySQL geöffnet haben, bevor Sie mysql_real_escape_string() verwenden, ansonsten erhalten Sie einen Fehler vom Typ E_WARNING und der Rückgabewert wird zu FALSE. Ist link_identifier nicht angegeben, wird die letzte MySQL-Verbindung verwendet.
Hinweis: Ist magic_quotes_gpc aktiviert, wenden Sie zuerst stripslashes() auf die Daten an. Das Bearbeiten bereits in irgend einer Form maskierter Daten durch mysql_real_escape_string führt ansonsten dazu, dass bereits Maskiertes doppelt maskiert wird.
Hinweis: Wenn die Funktion nicht verwendet wird, um die Daten zu maskieren, ist der Query anfällig für SQL Injection Angriffe.
Hinweis: mysql_real_escape_string() maskiert weder % noch _. Diese Zeichen werden in MySQL als Platzhalter interpretiert, wenn sie mit LIKE, GRANT oder REVOKE kombiniert werden.
Siehe auch
- mysql_client_encoding() - Liefert den Namen des Zeichensatzes
- addslashes() - Stellt bestimmten Zeichen eines Strings ein "\" voran
- stripslashes() - Entfernt aus einem gequoteten String alle Quotes
- Die magic_quotes_gpc-Direktive
- Die magic_quotes_runtime-Direktive
mysql_real_escape_string
19-Aug-2009 01:17
02-Aug-2009 12:45
I use the following code in my database connection include file (which is of course called at the start of every page that needs to do some SQL)...
Therefore, all POST and GET vars are automatically escaped before being used anywhere in SQL statements.
<?php
//This stops SQL Injection in POST vars
foreach ($_POST as $key => $value) {
$_POST[$key] = mysql_real_escape_string($value);
}
//This stops SQL Injection in GET vars
foreach ($_GET as $key => $value) {
$_GET[$key] = mysql_real_escape_string($value);
}
?>
27-Jul-2009 10:05
Don't forget that if you're using Mysqli (ie, the "improved" Mysql extension) then you need to use the corresponding mysqli function mysqli_real_escape_string(). The parameter order is also different.
13-Jul-2009 05:30
It is because you swapped $key and $item:
Just change this:
<?php
function mysql_safe ( $item, $key, $type )
?>
To:
<?php
function mysql_safe ( $key, $item, $type )
?>
And it will work as expected.
12-Jul-2009 08:06
I had wanted to see the merits of dynamically and "automatically" applying mysql_real_escape_string() to $_GET and $_POST as arrays rather than manually each time I would type up a query. I used array_walk_recursive() to call my function "mysql_safe" to apply mysql_real_escape_string() to each key of the $_GET and $_POST arrays.
My function is part of a class, and it is called each time I connect to the database to perform a query:
<?php
class MyClass {
function mysql_safe ( $key, $item, $type )
{
switch( $type )
{
case 'get':
if( count( $_GET ) > 0 )
{
$_GET[$item] = mysql_real_escape_string( $key );
}
break;
case 'post':
if( count( $_POST ) > 0 )
{
$_POST[$item] = mysql_real_escape_string( $key );
}
break;
}
}
function safe_get ( )
{
#Flag to only run function once
if( $this->get_flag == true ) { return true; }
array_walk_recursive( $_GET, array( $this, 'mysql_safe' ), 'get' );
array_walk_recursive( $_POST, array( $this, 'mysql_safe' ), 'post' );
$this->get_flag = true;
}
}
?>
However, after using this function, I find that it does indeed work, it also creates new $_GET and $_POST values in which $item and $key are swapped. So I end up with $_GET[$item] = $key, as well as $_GET[$key] = $item. I have not yet determined if this is due to the actual coding itself, or my particular method of implementation.
[EDIT BY danbrown AT php DOT net: Contains a bugfix by "Anonymous" on 13-JUL-09 to reorder the user function parameters.]
13-Jun-2009 09:37
I always use this function so I don't have to retype over and over the mysql_real_escape_string function.
<?php
function safe($value){
return mysql_real_escape_string($value);
}
?>
Then, when I am using my code, I simply use:
<?php
$name = safe($_POST["name"]);
$password = safe($_POST["password"]);
?>
25-Mar-2009 10:07
<?php
// Here is a simple named binding function for queries that makes SQL more readable:
// $sql = "SELECT * FROM users WHERE user = :user AND password = :password";
// mysql_bind($sql, array('user' => $user, 'password' => $password));
// mysql_query($sql);
function mysql_bind(&$sql, $vals) {
foreach ($vals as $name => $val) {
$sql = str_replace(":$name", "'" . mysql_real_escape_string($val) . "'", $sql);
}
}
?>
24-Mar-2008 08:46
This function won't help you when inserting binary data, to me it will get mallformed into the database. Probably UTF-8 combinations will be translated by this function or somewhere else when inserting data when running mysql in UTF-8 mode.
A better way to insert binary data is to transfer it to hexadecimal notation like this example:
<?php
$string = $_REQUEST['string'];
$binary = file_get_contents($_FILE['file']['tmp_name']);
$string = mysql_real_escape_string($string);
$binary_hex = bin2hex($binary);
$query = "INSERT INTO `table` (`key`, `string`, `binary`, `other`) VALUES (NULL, '$string', 0x$binary_hex, '$other')";
?>
03-Mar-2008 07:57
My escape function:
Automatically adds quotes (unless $quotes is false), but only for strings. Null values are converted to mysql keyword "null", booleans are converted to 1 or 0, and numbers are left alone. Also can escape a single variable or recursively escape an array of unlimited depth.
<?php
function db_escape($values, $quotes = true) {
if (is_array($values)) {
foreach ($values as $key => $value) {
$values[$key] = db_escape($value, $quotes);
}
}
else if ($values === null) {
$values = 'NULL';
}
else if (is_bool($values)) {
$values = $values ? 1 : 0;
}
else if (!is_numeric($values)) {
$values = mysql_real_escape_string($values);
if ($quotes) {
$values = '"' . $values . '"';
}
}
return $values;
}
?>
27-Dec-2007 10:49
In response to Michael D - DigitalGemstones.com:
Check the example again: sprintf(%d) already does the int conversion for you, so it's both perfectly save as well as more elegant than manually casting.
28-Aug-2007 02:16
if you're doing a mysql wildcard query with
LIKE, GRANT, or REVOKE
you may use addcslashes to escape the string:
<?php
$param = mysql_real_escape_string($param);
$param = addcslashes($param, '%_');
?>
06-Sep-2006 06:25
mysql_real_escape_string is a bit annoying when you need to do it over an array.
<?php
function mysql_real_escape_array($t){
return array_map("mysql_real_escape_string",$t);
}
?>
this one just mysql_real_escape's the whole array.
ex) <?php $_POST=mysql_real_escape_array($_POST); ?>
and then you dont have to worry about forgetting to do this.
18-Jul-2006 10:19
It seems to me that you could avoid many hassels by loading valid database values into an array at the beginning of the script, then instead of using user input to query the database directly, use it to query the array you've created. For example:
<?php
//you still have to query safely, so always use cleanup functions like eric256's
$categories = sql_query("select catName from categories where pageID = ?",$_GET['pageID']);
while ($cts = @mysql_fetch_row($categories)) {
//making $cts both the name and the value of the array variable makes it easier to check for in the future.
//obviously, this naming system wouldn't work for a multidimensional array
$cat_ar[$cts[0]] = $cts[0];
}
...
//user selects sorting criteria
//this would be from a query string like '?cats[]=cha&cats[]=fah&cats[]=lah&cats[]=badValue...', etc.
$cats = $_GET['cats'];
//verify that values exist in database before building sorting query
foreach($cats as $c) {
if ($cat_ar[$c]) { //instead of in_array(); maybe I'm just lazy... (see above note)
$cats1[] = "'".mysql_real_escape_string($c)."'";
}
}
$cats = $cats1;
//$cats now contains the filtered and escaped values of the query string
$cat_query = '&& (category_name = \''.implode(' || category_name = \'',$cats).'\')';
//build a sql query insert
//$cat_query is now "&& (category_name = 'cha' || category_name = 'fah' || category_name = 'lah')" - badValue has been removed
//since all values have already been verified and escaped, you can simply use them in a query
//however, since $pageID hasn't been cleaned for this query, you still have to use your cleaning function
$items = sql_query("SELECT * FROM items i, categories c WHERE i.catID = c.catID && pageID = ? $cat_query", $pageID);
30-May-2006 10:38
Note that mysql_real_escape_string doesn't prepend backslashes to \x00, \n, \r, and and \x1a as mentionned in the documentation, but actually replaces the character with a MySQL acceptable representation for queries (e.g. \n is replaced with the '\n' litteral). (\, ', and " are escaped as documented) This doesn't change how you should use this function, but I think it's good to know.
