aidan Wed Aug 11 06:03:20 2004 EDT
Modified files:
/phpdoc/en/reference/mysql/functions mysql-real-escape-string.xml
Log:
Removed initial example
Added a massive example with information about sql injection attacks
Added more information to the % and _ note
Added a variablelist
http://cvs.php.net/diff.php/phpdoc/en/reference/mysql/functions/mysql-real-escape-string.xml?r1=1.10&r2=1.11&ty=u
Index: phpdoc/en/reference/mysql/functions/mysql-real-escape-string.xml
diff -u phpdoc/en/reference/mysql/functions/mysql-real-escape-string.xml:1.10
phpdoc/en/reference/mysql/functions/mysql-real-escape-string.xml:1.11
--- phpdoc/en/reference/mysql/functions/mysql-real-escape-string.xml:1.10 Wed
Aug 11 06:01:42 2004
+++ phpdoc/en/reference/mysql/functions/mysql-real-escape-string.xml Wed Aug 11
06:03:20 2004
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- $Revision: 1.10 $ -->
+<!-- $Revision: 1.11 $ -->
<!-- splitted from ./en/functions/mysql.xml, last change in rev 1.100 -->
<refentry id="function.mysql-real-escape-string">
<refnamediv>
<refname>mysql_real_escape_string</refname>
<refpurpose>
- Escapes special characters in a string for use in a SQL statement, taking into
account the current charset of the connection.
+ Escapes special characters in a string for use in a SQL statement,
+ taking into account the current charset of the connection.
</refpurpose>
</refnamediv>
<refsect1>
@@ -16,46 +17,131 @@
<methodparam
choice="opt"><type>resource</type><parameter>link_identifier</parameter></methodparam>
</methodsynopsis>
<para>
+ <variablelist>
+ <varlistentry>
+ <term><parameter>unescaped_string</parameter></term>
+ <listitem><simpara>The string to escape</simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><parameter>link_identifier</parameter> (optional)</term>
+ <listitem><simpara>The mysql connection resource</simpara></listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ <para>
This function will escape special characters in the
<parameter>unescaped_string</parameter>, taking into account the current
charset of the connection so that it is safe to place it in a
- <function>mysql_query</function>.
+ <function>mysql_query</function>. If you wish to insert binary data
+ you must use this function.
+ </para>
+ <para>
+ mysql_real_escape_string calls MySQL's library function of the
+ same name, which prepends slashes to the following characters:
+ <literal>NULL</literal>, <literal>\x00</literal>, <literal>\n</literal>,
+ <literal>\r</literal>, <literal>\</literal>, <literal>'</literal>,
+ <literal>"</literal> and <literal>\x1a</literal>.
+ </para>
+ <para>
+ You must always (with few exceptions) use this function
+ to make your data safe before inserting. If you have
+ <link linkend="ini.magic-quotes-gpc">magic_quotes_gpc</link> enabled,
+ you must first <function>stripslashes</function> your data. If you don't use
+ this, you'll leave yourself open to SQL Injection Attacks. Here's an example:
</para>
- <note>
- <simpara>
- <function>mysql_real_escape_string</function> does not escape
- <literal>%</literal> and <literal>_</literal>.
- </simpara>
- </note>
<para>
<example>
- <title><function>mysql_real_escape_string</function> example</title>
+ <title>An example SQL Injection Attack</title>
<programlisting role="php">
<![CDATA[
<?php
-$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
-if (!$link) {
- die('Could not connect: ' . mysql_error());
-}
-$item = "Zak's and Derick's Laptop";
-$escaped_item = mysql_real_escape_string($item, $link);
-printf("Escaped string: %s\n", $escaped_item);
+// Query database to check if there are any matching users
+$query = "SELECT * FROM users WHERE user='{$_POST['username']}' AND
password='{$_POST['password']}'";
+mysql_query($query);
+
+// We didn't check $_POST['password'], it could be anything the user wanted! For
example:
+$_POST['username'] = 'aidan';
+$_POST['password'] = "' OR 1=1";
+
+// This means the query sent to MySQL would be:
+echo $query;
?>
]]>
</programlisting>
- <para>
- The above example would produce the following output:
- </para>
+ <para>
+ The query sent to MySQL:
+ </para>
<screen>
<![CDATA[
-Escaped string: Zak\'s and Derick\'s Laptop
+SELECT * FROM users WHERE name='fred' AND password='' OR 1=1
]]>
</screen>
+ <para>
+ This would allow anyone to log in without a valid password! Using
+ <function>mysql_real_escape_string</function> around each variable
+ prevents this.
+ </para>
+ <programlisting role="php">
+<![CDATA[
+<?php
+/**
+ * Apply stripslashes recursively
+ */
+function stripslashes_deep($value)
+{
+ $value = is_array($value) ?
+ array_map('stripslashes_deep', $value) :
+ stripslashes($value);
+
+ return $value;
+}
+
+/**
+ * Quote a variable to make it safe for insertion
+ */
+function quote_smart($value)
+{
+ // Stripslashes if we need to
+ if (get_magic_quotes_gpc()) {
+ $value = stripslashes_deep($value);
+ }
+
+ // Quote it if it's not an interger
+ if (!is_int($value)) {
+ $value = "'" . mysql_real_escape_string($value) . "'";
+ }
+
+ return $value;
+}
+
+// Connect
+$link = mysql_connect('localhost', 'mysql_user', 'mysql_password')
+ OR die('Could not connect: ' . mysql_error());
+
+// Make a safe query
+$query = sprintf("SELECT * FROM users WHERE user=%s AND password=%s",
+ quote_smart($_POST['username']),
+ quote_smart($_POST['password']));
+
+mysql_query($query);
+?>
+]]>
+ </programlisting>
+ <para>
+ Our query is now safe no matter what the user submits!
+ </para>
</example>
</para>
+ <note>
+ <simpara>
+ <function>mysql_real_escape_string</function> does not escape
+ <literal>%</literal> and <literal>_</literal>. These are wildcards in MySQL
+ if not bounded by quotes.
+ </simpara>
+ </note>
<para>
See also
- <function>mysql_escape_string</function>,
<function>mysql_client_encoding</function>,
<function>addslashes</function>, and the
<link linkend="ini.magic-quotes-gpc">magic_quotes_gpc</link>