2010-01-16 22 views
21

PLATAFORMA: PHP MySQL &PHP y mySQL: ¿Cuándo usar htmlentities exactamente?

Para mis fines de experimentación, he probado algunas de las inyecciones XSS a mí mismo en mi propio sitio web. Considere esta situación en la que tengo mi formulario textarea de entrada. Como este es un área de texto, puedo ingresar texto y todo tipo de caracteres (en inglés). Aquí están mis observaciones:

A). Si aplico solo strip_tags y mysql_real_escape_string y no uso htmlentities en mi entrada justo antes de insertar los datos en la base de datos, la consulta está rompiendo y me aparece un error que muestra la estructura de mi tabla, debido a la terminación anómala.

B). Si estoy aplicando strip_tags, mysql_real_escape_string y htmlentities en mi entrada justo antes de insertar los datos en la base de datos, la consulta NO está rompiendo y puedo insertar datos del área de texto en mi base de datos.

Por lo tanto, entiendo que las funciones se deben usar a toda costa, pero no se sabe exactamente cuándo se deben usar. Con lo anterior en mente, me gustaría saber:

  1. ¿Cuándo se deben usar htmlentities exactamente? ¿Debería usarse justo antes de insertar los datos en DB o de alguna manera obtener los datos en DB y luego aplicar htmlentities cuando estoy tratando de mostrar los datos del DB?

  2. Si sigo el método descrito en el punto B) anterior (que creo que es la solución más obvia y eficiente en mi caso), aún tengo que aplicar htmlentities cuando intento mostrar los datos de la base de datos ? Si es así, ¿por qué? ¿Si no, porque no? Lo pregunto porque es muy confuso para mí después de haber pasado por el puesto en: http://shiflett.org/blog/2005/dec/google-xss-example

  3. Luego está esta función una más llamada PHP: html_entity_decode. ¿Puedo usar eso para mostrar mis datos de DB (después de seguir mi procedimiento como se indica en el punto B) ya que htmlentities se aplicó en mi entrada? ¿Cuál debería preferir de html_entity_decode y htmlentities y cuándo?

previa de la página:

pensé que podría ayudar a añadir algunos detalles más específicos de una situación específica aquí. Considere que hay una página 'Vista previa'. Ahora cuando presento la entrada desde un área de texto, la página Vista previa recibe la entrada y la muestra html y, al mismo tiempo, una entrada oculta recoge esta entrada. Cuando se presiona el botón de enviar en el botón Vista previa, los datos de la entrada oculta se transfieren a una nueva página y esa página inserta los datos contenidos en la entrada oculta en la base de datos. Si no aplico htmlentities cuando el formulario se envía inicialmente (pero solo se aplican strip_tags y mysql_real_escape_string) y hay una entrada maliciosa en el área de texto, la entrada oculta se rompe y los últimos caracteres de la entrada oculta se ven visiblemente como " /> en la página , lo cual es indeseable Así que, teniendo esto en cuenta, tengo que hacer algo para preservar la integridad de la entrada oculta correctamente en la página de Vista previa y aún recopilar los datos en la entrada oculta para que no la rompa. ¿Cómo hago esto? Disculpa por el retraso en publicar esta información.

Gracias de antemano.

+7

Un consejo: la mayoría de las veces, no debe usar htmlentities, sino htmlspecialchars. htmlentities convierte una tonelada de caracteres, mientras que htmlspecialchars solo convierte aquellos que DEBEN convertirse. –

+0

@Michael Madsen: Gracias por el consejo. El formulario acepta todas las entradas que puedas ingresar usando un teclado basado en los EE. UU. Así que tuve la idea de que el uso de htmlentities lo haría más seguro, en caso de que alguien intente copiar y pegar manualmente algunos caracteres extraños de algún otro sitio web o de su propio sistema localmente. Así que opté por usar htmlentities. ¿Qué piensas? – Devner

+1

No tiene sentido. Sí, los personajes extraños podrían verse ... bueno, raro en su sitio. Pero no estás evitando eso usando htmlentities, porque las entidades son solo una forma diferente de representar al mismo personaje. No tienen ningún significado especial en HTML, por lo que no hay ninguna ventaja en su traducción: el resultado final será el mismo, solo usará más bytes para mirar de esa manera. –

Respuesta

51

Esta es la regla general.

Variables de escape en el último momento posible.

Desea que sus variables sean representaciones nítidas de los datos. Es decir, si usted está tratando de almacenar el apellido de alguien llamado "O'Brien", entonces definitivamente no quiere siguientes:

O'Brien 
O\'Brien 

.. porque, bueno, eso no es su nombre: no hay ampersands o barras en él. Cuando toma esa variable y la emite en un contexto particular (por ejemplo: insertar en una consulta SQL o imprimir en una página HTML), que es cuando la modifica.

$name = "O'Brien"; 

$sql = "SELECT * FROM people " 
    . "WHERE lastname = '" . mysql_real_escape_string($name) . "'"; 

$html = "<div>Last Name: " . htmlentities($name, ENT_QUOTES) . "</div>"; 

Nunca se desea tener htmlentities cadenas codificados con almacenadas en su base de datos. ¿Qué sucede cuando desea generar un CSV o PDF, o cualquier cosa que no sea HTML?

Mantenga los datos limpios, y solo escapes para el contexto específico del momento.

+1

Curioso, si hay un elemento que no le permite al usuario usar ningún html, entonces guarda algo como texto que no es html en mysql, ¿aún necesita usar htmlentities() cuando lo muestra? – JasonDavis

+0

define texto no html? Algo consideraría esto como HTML: 'foo'. También considerarían este HTML: 'x z'. Si no desea que el usuario ingrese HTML, simplemente no trate nada de lo que escriben como HTML, es decir, guárdelo en la base de datos literalmente y htmlentities al hacer eco en la pantalla. – nickf

+0

Gracias por su respuesta. Edité mi publicación original para incluir la información que podría ser útil para arrojar más luz sobre la situación. Por favor refiérase a él y publique su respuesta. Gracias. – Devner

5

En esencia, debe usar mysql_real_escape_string antes de insertar la base de datos (para evitar la inyección de SQL) y luego htmlentities, etc. en el punto de salida.

También deseará aplicar la comprobación de cordura a todas las entradas del usuario para garantizar (por ejemplo) que los valores numéricos sean realmente numéricos, etc. Las funciones como is_int, is_float, etc. son útiles en este punto. (Vea la sección variable handling functions del manual de PHP para más información sobre estas funciones y otras similares.)

+0

@middaparka Gracias. Tienes razón. Pero estaba tratando de asegurarme de que puedo estar seguro de los ataques CSS/XSS. El área de texto acepta todo tipo de entradas, números, caracteres, etc. En resumen, acepta todas las entradas que se puedan ingresar usando un teclado basado en los EE. UU. Entonces is_int, etc. no son de mucha ayuda ya que también se permiten otros tipos de entradas. Incluso edité mi publicación original para incluir información más específica. Por favor refiérase a él y publique su respuesta según corresponda. Muchas gracias. – Devner

5
  1. Sólo antes de imprimir el valor (no importa de DB o desde $ _GET/$ _ POST) en HTML. htmlentities no tienen nada que ver con la base de datos.
  2. B es exagerado. Debe mysql_real_escape_string antes de insertar en DB, y htmlentities antes de imprimir en HTML. No es necesario pelar las etiquetas, después htmlentities etiquetas se mostrarán en la pantalla como < br /> etc

Teóricamente es posible hacer htmlentities antes de insertar a DB, pero esto podría hacer más difícil el procesamiento de datos, si necesitaría texto original.

3. See above 
+0

En mi opinión, no debe usar htmlentities antes de insertar en la base de datos. No está conservando los datos originales si lo hace –

+0

Sí, digo exactamente lo mismo. Pero si uno realmente quiere eso, no representaría un riesgo de seguridad adicional, solo un poco de retraso. – BarsMonster

+0

@ d03boy: Gracias a ambos por sus respuestas. Edité mi publicación original para incluir la información que podría ser útil para arrojar más luz sobre la situación. Por favor refiérase a él y publique su respuesta. Gracias. – Devner

0

He pasado por esto antes y aprendí dos cosas importantes:

Si usted está recibiendo valores de $ _POST/$ _ GET/$ _ REQUEST y planificar para añadir a DB, utilice la función mysql_real_escape_string para desinfectar los valores . No los codifique con htmlentities.

¿Por qué no simplemente codificarlos con htmlentities y ponerlos en la base de datos? Bueno, aquí está el objetivo: el objetivo es hacer que los datos sean lo más significativos y limpios posible, y cuando codifiques los datos con elementos como Jeff's Dog se convierte en Jeff &, el perro ... hará que el contexto de los datos pierda su significado . Y si decide implementar servicios REST y obtiene esa cadena de DB y la coloca en JSON, aparecerá como Jeff &, el perro que no es bonito.Tendría que agregar otra función para decodificar también.

Suponga que desea buscar "Jeff's Dog" con SQL "select * from table where field = 'Jeff \' s Dog '", no lo encontrará porque "Jeff's Dog" no coincide con "Jeff & es perro ". Malo, ¿eh?

Para enviar cadenas alfanuméricas (desde el tipo CHAR) a una página web, use htmlentities - SIEMPRE!

+0

Gracias por su comentario. Estoy de acuerdo contigo. He estado usando mysql_real_escape_string desde que nuestros amigos lo sugirieron. Entonces, ¿qué sugieres que usemos, htmlentities o htmlspecialchars para enviar cadenas alfanuméricas (desde CHAR, tipo VARCHAR) a una página web? – Devner

Cuestiones relacionadas