2010-04-04 26 views
11

Estoy tratando de protegerme de inyección SQL y estoy usando:decodificación mysql_real_escape_string() para dar salida HTML

mysql_real_escape_string($string); 

Cuando la publicación de HTML que se ve algo como esto:

<span class="\&quot;className\&quot;"> 
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p> 
</span> 

estoy no estoy seguro de cuántas otras variaciones añade real_escape_string, por lo que no quiero reemplazar unos pocos y perder otros ... ¿Cómo puedo "decodificar" esto en HTML correctamente formateado, con algo como:

html_entity_decode(stripslashes($string)); 
+0

Si el usuario puede controlar $ cadena, entonces esta es una vulnerabilidad XSS. – rook

Respuesta

12

La página del manual mysql_real_escape_string() le dice qué se escapan caracteres:

mysql_real_escape_string() llama biblioteca de funciones mysql_real_escape_string de MySQL, que antepone barras invertidas a los siguientes caracteres: \ x00 \ n \ r, \, ', "y \ x1a.

Puede revertir con éxito el escape reemplazando los caracteres que se han escapado con sus formularios no escaneados.

mysql_real_escape_string() no se debe utilizar para desinfectar HTML sin embargo ... no hay ninguna razón para usarlo antes de la salida de datos de la página web. Solo debe usarse en datos que está a punto de poner en la base de datos. Su proceso de desinfección debe ser algo como esto:

entrada

  1. aceptar la entrada del usuario desde un formulario o solicitud HTTP
  2. Crear una consulta de base de datos utilizando mysql_real_escape_string()

salida

  1. obtener los datos de la base de datos
  2. Ejecutar los datos definidos por el usuario a través de htmlspecialchars() antes de imprimir

El uso de un controlador de base de datos diferente, como MySQLi o PDO se permitirá utilizar declaraciones preparadas, que se ocupan de escapar la mayoría de las entradas para ti. Sin embargo, si no puede cambiar o aprovechar esos, entonces definitivamente use mysql_real_escape_string() ... solo utilícelo antes de insertar datos.

+0

Recomendaría las declaraciones preparadas (por ejemplo, http://www.php.net/manual/en/class.pdostatement.php) sobre 'mysql_real_escape_string'. Y 'htmlspecialchars' no siempre es la elección correcta. A veces, la inclusión en la lista blanca es una mejor opción. –

+0

¡Nota! Si tiene 'magic_quotes' activado, incluso con PDO necesitará usar 'stripslashes()' antes de poner cadenas en la base de datos para evitar doble barra diagonal. – mrserge

+0

Pero ningún sistema moderno debería tener magic_quotes en. Esa característica ha quedado obsoleta por años. –

7

Tienes todo en mal estado.

mysql_real_escape_string no es necesario decodificar.

si obtiene sus datos con barras diagonales, significa que ha sido escapó dos veces. Y en lugar de eliminar las barras adicionales, simplemente no debes agregarlas.

no hablar de que cualquiera que sea el escape es obsoleto y debe

de aplicación preparadas declaraciones

en lugar de cualquier cadena de escape.

Por lo tanto, nunca escape, nunca decodifique.
El problema fue resuelto.

+0

$ query = "INSERT INTO table SET html = '$ html'"; no es SQL estándar, será mejor que use INSERT INTO table (html) VALUES ('contenido'); Esto funciona en todas las bases de datos, no solo en MySQL. –

+0

@Frank Heikens Pero estoy trabajando con mysql. Y utilizo toneladas de características específicas de mysql. Ve y dime que no use PHP, ya que no es compatible en todas partes. ¡Qué comentario sin sentido! –

7

mysql_real_escape_string se usa para evitar la inyección SQL cuando se almacenan los datos proporcionados por el usuario en la base de datos, pero un mejor método sería usar el enlace de datos usando PDO (por ejemplo). Siempre recomiendo usar eso en lugar de meterme con escapar.

Dicho esto, con respecto a su pregunta sobre cómo mostrarlo después: una vez que se almacenan los datos, cuando los recupera, los datos están completos y son válidos sin necesidad de "desconexión". A menos que hayas añadido tus propias secuencias de escape, no hagas eso.

-2

creo una serie de otras respuestas se perdió la cuestión obvia ...

está usando el mysql_real_escape_string en el contenido introducido (como usted debe si no se usa comandos preparados).

Su problema es con la salida.

El problema actual es que llama a html_entity_decode. Con solo tiras, es necesario restaurar el texto original. html_entity_decode es lo que está arruinando tus presupuestos, etc., ya que los está cambiando. De hecho, desea generar el html, no solo texto sin formato (que es cuando usaría html_entities, etc.). Está decodificando algo que quiere codificar.

Si solo desea que aparezca la versión de texto, puede usar las entidades. Si le preocupan las etiquetas incorrectas, use etiquetas adhesivas y permita solo las etiquetas que desee (como b, i, etc.).

Finalmente, recuerde codificar y decodificar en el orden correcto. si ejecutó mysql_real_escape_String (htmlentities ($ str)), entonces necesita ejecutar html_entity_decode (stripslashes ($ str)). El orden de las operaciones es importante.

ACTUALIZACIÓN: No me di cuenta de que html_entity_decode también elimina las barras. No estaba claramente documentado en esa página, y simplemente nunca lo atrapé. Aun así, lo ejecutaré automáticamente, ya que la mayoría de html que presento quiero dejarlos como entidades, e incluso cuando no lo hago, prefiero tomar esa decisión fuera de mi clase de db, caso por caso. De esa manera, sé que las barras se han ido.

Parece que el póster original está ejecutando htmlentities (o su programa de entrada, como tinymce lo está haciendo por él), y quiere volver al contenido. Entonces, html_entity_decode ($ Str) debería ser todo lo que se requiere.

+1

estás equivocado. él no necesita desnudar barras. Necesito agregarlo correctamente Cura el deceso, no el síntoma. –

+0

Él TIENE que quitar las barras, ya que primero ejecutó la cuerda de escape. Lo codificó, ahora necesita decodificarlo para deshacerse de las barras en la salida. De ahí el \ que aparece antes del ". – Cryophallion

+1

No tiene idea de cómo funciona la cosa. Así que es mejor que no respondas hasta que aprendas algo. No se necesita stripping Inténtalo tú mismo. –

0
No

seguro de lo que está pasando con el formato que puedo ver, pero su formulario HTML

<span class="\&quot;className\&quot;"> 
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p> 
</span> 

debe ser simplemente;

<span class="className"> 
<p class="pClass" id="pId"></p> 
</span> 

Al llegar de nuevo, antes de colocarlo en la base de datos a escapar usando mysql_real_escape_string() para asegurarse de que no sufren un ataque de inyección SQL.

Por lo tanto, está escapando de los valores listos para colocar el texto que sigue.

Cuando lo saca de la base de datos (o muestra CUALQUIERA de ellos a los usuarios como html) entonces lo escapa nuevamente listo para ese lugar al que va (html) con htmlentities() etc para proteger a sus usuarios Ataques XSS.

Esto forma la parte EO del mantra FIEO, Entrada de filtro, Salida de escape, que debe tatoo en el interior de sus párpados.

+0

¿Estás seguro de que quiere que se escape este formulario? A estoy en profundas dudas. Si alguien utiliza el formato HTML, generalmente quieren que funcione, no como etiquetas visibles. –

-1

Me preguntaba por qué esta rutina no tiene una rutina de decodificador acompañante. Es probablemente interpretado por MySQL exactamente de la misma manera que si no se hubiera escapado. Obtienes los resultados no escapados cuando haces un $row=mysql_fetch_array($res, MYSQL_ASSOC)';

0

Bueno, apuñalé esto a la manera antigua y hasta ahora no puedo ver nada malo con mi enfoque. Obviamente es un poco crudo pero hace bien el trabajo:

function mysql_unreal_escape_string($string) { 
    $characters = array('x00', 'n', 'r', '\\', '\'', '"','x1a'); 
    $o_chars = array("\x00", "\n", "\r", "\\", "'", "\"", "\x1a"); 
    for ($i = 0; $i < strlen($string); $i++) { 
     if (substr($string, $i, 1) == '\\') { 
      foreach ($characters as $index => $char) { 
       if ($i <= strlen($string) - strlen($char) && substr($string, $i + 1, strlen($char)) == $char) { 
        $string = substr_replace($string, $o_chars[$index], $i, strlen($char) + 1); 
        break; 
       } 
      } 
     } 
    } 
    return $string; 
} 

Esto debería cubrir la mayoría de los casos.

-1

Incluso si es una pregunta anterior ... He tenido el mismo problema que Peter Craig. De hecho, tengo que lidiar con un viejo CMS. Para evitar la inyección SQL, todos los valores $ _POST y $ _GET son "sql-escaped". Desafortunadamente, esto se hace en un punto central por lo que todos sus módulos están recibiendo todos los datos sql-escapó! En algunos casos, desea mostrar directamente estos datos para que se encuentre con un problema: ¿cómo mostrar una cadena sql-escapada sin obtenerla de DB? La respuesta es: stripcslashes uso (NO stripslashes !!)

http://php.net/manual/en/function.stripcslashes.php

-1

utilizar la siguiente función para eliminar las barras mientras se muestra en la página HTML:

stripslashes();

por ejemplo. $ html = stripslashes ($ html); O $ html = stripslashes ($ row ["fieldname"]);