Prepared statement + htmlspecialchar vs XSS y SQLi

Iniciado por Tersk, 1 Agosto 2013, 03:15 AM

0 Miembros y 1 Visitante están viendo este tema.

Tersk

Buenas a todos, espero que este sea el lugar apropiado para postear mi duda, llevo tiempo informándome sobre la seguridad y es dificil sacar algo en claro (debido a la gran cantidad de información demasiado dispar).

Por lo que he sacado en claro... es que dentro de los métodos que hay para evitar SQLinjection uno de lo más eficaces si no el que más es introducir los datos en la base de datos mediante "prepared statement", porque separa lo que es la sintaxis de la query del valor a introducir...


Supongamos un caso:
Tenemos un textarea que guardaremos en nuestra base de datos (por ejemplo los comentarios de un producto o de una foto) (parto de la base de que con los prepared statment se soluciona el SQLi por lo que ya sólo nos quedaría el posible ataque XSS)... ese comentario puede tener texto malintencionado (o no...) tipo <h1>Hola</h1> o Scripts más molestos como alerts o algo más maliciosos, mi duda viene a que si yo alojé en mi base de datos ese textarea tal cual: "<h1>Hola</h1>"... cuando vaya a mostrarse eso en dicha foto nos fatidiaría.
Para evitarlo yo lo que desde mi ignorancia se me ocurre es usar el htmlspecialchars, para que ANTES de mostrar ese texto por pantalla los caracteres recurrentes a realizarnos ataques XSS se pogan en modo de %gt; y asi en pantalla se mostrará sin problema: "<h1>Hola</h1> sin que ocasione daño alguno.
Es seguro de esta manera que he comentado??? Hay alguna forma de saltarse esta "defensa" o hay ataques que no se tendrían en cuenta así a los que seriamos vulnerables??

He visto que hay sitios que realizan strip_tags.... pero si por cualquier razón nuestro usuario quisiera poner un "<" o algún caracter similar.... entiendo que lo eliminaría y no se mostraría, por lo que no me parece eficaz de ser así.

Disculpad tanta parrafada, espero que alguien con más experiencia pueda arrojarme algo de luz jeje,

Un saludo!

GenR_18

#1
Pues mira, no soy un experto pero te puedo decir


Se supone (ya que todos sabemos que nada es 100% seguro) que con los prepare statement (PDO o MySQLi) son suficientes para para un SQLi.

Por lado del XSS, te recomiendo que si los datos que recibes del usuario son guardados en una bd uses strip_tags() al guardarlos, y al mostrarlos en pantalla uses htmlentities($str, ENT_QUOTES, "UTF-8"), esto es lo que usabamos unos amigos y yo al montar un sistema "seguro".

Hay un tipo de ataque, que si no mal recuerdo el truco era cambiar el tipo de encoding a UTF-7 o no recuerdo exactamente y con ciertos carácteres se lograba un XSS, no recuerdo si fue sirdarcat o WHK quien lo publicó acá hace un tiempesito.

Edito:

Me puse a investigar y acá te dejo lo que te hablé:

http://foro.elhacker.net/nivel_web/bypass_de_htmlentities-t251657.0.html
http://shiflett.org/blog/2005/dec/google-xss-example

A mi la verdad es que no me funcionó, prueba y me dices...

Salu2!

Tersk

#2
Gracias por responder, sí yo tambien había leido algo respecto a lo del UTF-8, que siendo 7 podían hacerte un ataque XSS, la verdad es que ya se me había hasta olvidado y posiblemente se me habría pasado ponerlo :P, lo del ENT_QUOTES sí lo tenía claro.

El problema que veo con lo que me comentas de strip_tags() para guardar en la base de datos es que se pierde información... por ejemplo cuando escribimos aquí respuestas en el foro fijate que nos deja poner sin problema "<h1>Hola</h1>"... al meterle ese strip_tag() antes de guardarse en la base de datos quedaría sólamente "Hola", pues nos eliminaría las etiquetas html, por lo que cuando lo querramos mostrar sólo podrá mostrar "Hola" pues lo otro se eliminó. A las malas.... lo que podría hacerse es a la hora de mostrar, después de un htmlspecialchar hacer un strip_tag() para asegurarse 100%,aunque creo que no tendría demasiado sentido... sería algo así:

echo strip_tags(htmlspecialchars($reg['comentario']));

(ese $reg es el array asociativo que devuelve el fetch al hacer un select). Pero lo veo un sin sentido... pues supuestamente el htmlspecialchars ya "cambia" todos esos caracteres y por tanto strip_tags() nunca eliminará nada.