2010-08-28 5 views

Respuesta

8

Creo que está confundiendo dos problemas de seguridad: SQL injection y cross-site scripting (XSS).

Un sitio web es vulnerable a la inyección SQL cuando se utiliza una entrada del usuario incorrectamente desinfectada en una consulta SQL que se envía a la base de datos SQL.Este código, por ejemplo, presenta una vulnerabilidad de inyección SQL:

mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . $_POST['postmessage'] . "')"); 

Este problema es fácil de solucionar por escapar de la entrada del usuario con una función como mysql_real_escape_string:

mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string($_POST['postmessage']) . "')"); 

Eso es todo lo que tiene que hacer , pero la parte difícil es recordar hacer esto para cada parte de la entrada del usuario que se utiliza en una declaración de SQL.

Un sitio web es vulnerable a las secuencias de comandos entre sitios cuando la entrada del usuario se utiliza en HTML que se envía a un cliente. Este código, por ejemplo, presenta una vulnerabilidad XSS:

echo "<div class='postmessage'>" . $_POST['postmessage'] . "</div>"; 
vulnerabilidad

A XSS se fija por escapar de la entrada del usuario con una función como htmlspecialchars:

echo "<div class='postmessage'>" . htmlspecialchars($_POST['postmessage']) . "</div>"; 

nuevo, esto es fácil de hacer, pero fácilmente olvidado

Normalmente, la entrada del usuario que se coloca en una base de datos para ser utilizada en el envío posterior de HTML se guarda sin modificaciones. Es decir, solo se usa mysql_real_escape_string. Sin embargo, se podía escapar la entrada del usuario para evitar XSS, y luego escapar de la cadena XSS-seguro para evitar la inyección de SQL:

mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string(htmlspecialchars($_POST['postmessage'])) . "')"); 

La ventaja es que no es necesario recordar para escapar de los valores de la base de datos con htmlspecialchars antes de escribirlos en HTML. El inconveniente es que algunos valores pueden necesitar escaparse con diferentes funciones. Por ejemplo, un nombre de usuario probablemente se escaparía con htmlspecialchars, pero un "mensaje posterior" podría permitir BBcode, Markdown o un subconjunto de HTML. Si escapó a todas las entradas para evitar XSS, entonces necesitaría deshacer los valores de la base de datos con, por ejemplo, htmlspecialchars_decode.

Un problema es que al desempañar la cadena escapada no siempre se devuelve la cadena original (unescape(escape($orig)) no es necesariamente lo mismo que $orig). Incluso con htmlspecialchars y htmlspecialchars_decode, usar un estilo de cita diferente causará este problema. Otro ejemplo es que si se utiliza strip_tags, la información se elimina irrecuperablemente; no podrá deshacer el strip_tags. Por lo tanto, muchos desarrolladores eligen usar mysql_real_escape_string solo para guardar valores en la base de datos y htmlspecialchars (o lo que sea) para preparar una cadena de la base de datos que se usará en HTML.

+0

¿No sería mejor usar declaraciones preparadas, más limpio para mirar y posiblemente más fácil de trabajar una vez que lo domine? –

+1

@Xeross: Definitivamente. Las declaraciones preparadas hacen que sea más fácil escapar de manera consistente la entrada del usuario. Sin embargo, al responder la pregunta de OP, quería asegurarme de que entendía las razones para usar 'mysql_real_escape_string' (o algún mecanismo de escape DB) y' htmlentities' (o algún mecanismo de escape XSS). –

21

mysql_real_escape_string() es el único método que necesita aquí.
No debe hacer un htmlentities() ni urlencode() antes de insertar datos en su base de datos. Estos métodos suelen ser códigos durante la representación de la Vista que ofrece a sus usuarios.

Una mejor forma de evitar la inyección de SQL es el uso de declaraciones preparadas.


Recursos:

Sobre el mismo tema:

+0

+1 para declaraciones preparadas. También pueden ayudar con el rendimiento en las situaciones correctas. –

+0

+1 para declaraciones preparadas –

+0

<3 Declaraciones preparadas :) –

1

También debe asegurarse de usar "alrededor del lugar donde inserta su código.

Por ejemplo si haces

$_POST['userid'] = mysql_real_escape_string($_POST['userid']); 
mysql_query('SELECT * FROM user WHERE userid = '. $_POST['userid']); 

mysql_real_escape_string no ayudaría nada. Es porque $ _POST ['userid'] no está rodeado por '.

Por lo que debe hacer

$_POST['userid'] = mysql_real_escape_string($_POST['userid']); 
mysql_query('SELET * FROM user WHERE userid = \''. $_POST['userid'] .'\''); 

lugar.

Por lo tanto, usar mysql_real_escape_string en sus variables no significa automáticamente que sean seguras en ninguna consulta.

Otro enfoque sería utilizar declaraciones preparadas.

1

Sí, pero hay una razón para no usar mysql_real_escape_string(). Primero, es doloroso escribir. Segundo, debes recordar usarlo todo el tiempo. En tercer lugar, hace que tu código sea feo. En cuarto lugar, debe recordar citar sus cadenas. En quinto lugar, es más difícil insertar blobs en un db de esta manera.

Aprender PDO hará que su vida sea mejor a largo plazo. Es más difícil de aprender que simplemente usar mysql_real_escape_string(), pero los beneficios a largo plazo superan los inconvenientes de una curva de aprendizaje.

Cuestiones relacionadas