entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

htmlspecialchars() vs htmlentities() en PHP

Hola a la comunidad de entredesarrolladores,

Tengo una duda sobre el método de los que propone PHP para el saneado y el escapado de caracteres introducidos por parte del usuario en un formulario es el mas seguro.

Como se que pueden haber respuestas tipo "Eso dependerá de cada caso" es por eso que propongo que me digáis cual es el método/procedimiento que asta el día de hoy puedan evitar la gran mayoría de ataques XSS, ya que estos es lo que cualquier administrador no desea en su sitio web(ademas de otros ataques que no entran etc...)

Yo no se si utilizar métodos son los mejores, los que encontrado son:

htmlspecialchars
addslashes
stripslashes
htmlspecialchars

Pues eso no se si con uno en especial es el mejor o usarlos en conjunto, concatenar métodos etc...

Yo propongo este --> addslashes(htmlspecialchars($_POST['texto'], ENT_QUOTES));

Espero vuestra respuesta, saludos!

3 Respuestas

3votos

white Puntos75820

htmlspecialchars es diferente de htmlentities,

htmlspecialchars bastaria para filtrar contenido que se muestre en el navegador, si la codificacion de tu página es diferente de ISO-8859-1 o UTF-8 entonces se utilizaría htmlentities. la idea no es cual es mejor ni como combinados trabajen mejor sino cuando utilizarlos, cuando combinarlos y el orden para cada funcion. eso depende el tipo de $POST['texto'].

por un ejemplo si _POST[texto] fuese un email, entonces se debe validar antes de sanitizarlo correctamente. ya que podrias estar filtrando un carácter del email e ingresarlo erroneamente en la base de datos.

hay alternativas, como librerias especificas para filtrar valores, en php 5 tienes funciones como filter_input y filter_var

https://php.net/manual/es/function.filter-input.php
https://php.net/manual/es/function.filter-var.php
https://php.net/manual/es/filter.filters.sanitize.php

0voto

pabeni comentado

Hola white,

Una cosa en que te basas exactamente a la hora de emplear un método u el otro según el tipo de codificación ISO-8859-1 y UTF-8?

Por cierto estos métodos que mencionas ya los conocía filter_input y filter_var pero mi objetivo no es validar datos o campos que se espera un patrón como puede ser un email, contraseña, IP, URL, etc... Si no de campos que el usuario pueda aproveche para meter código malicioso a su antojo(ojo con esto no quiero decir que también aproveche los campos del email...ya que realmente cualquier campo esta expuesto a testear por el usuario malintencionado).

Un saludo!

0voto

white comentado

con htmlspecialchars podría haber problemas con caracteres especiales, dependiendo de la codificacion del fichero, la base de datos y la página, podria codificarse antes de ingresar a la base de datos:

<!DOCTYPE html>
<html lang="es">
    <head>
        <meta charset="ISO-8859-15">
        <title>Document</title>
    </head>
    <body>
    <?php header('Content-Type: text/html;charset=ISO-8859-15');

        echo htmlentities('áéíóú âêîôû € Š š Ž ž Œ œ Ÿ', ENT_QUOTES);
        // áéíóú âêîôû € Š š Åœ ÅŸ Œ œ Ÿ

        echo '<br>';

        echo htmlspecialchars('áéíóú âêîôû €ŠšŽžŒœŸ', ENT_QUOTES);
        // áéíóú âêîÎû €ŠšŜşŒœŞ 
    ?>
    </body>
</html>

filter_input y filter_var no solo va para validar sino tambien para sanitizar, dispones de varios filtros para esto:

https://php.net/manual/es/filter.filters.sanitize.php
http://runnable.com/Um6DqB7LHJBTAAEy/how-to-sanitize-input-variables-using-filter_input-and-sanitize-filters

aca un articulo con varios metodos xss: https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

0voto

pabeni comentado

Muchas gracias por vuestra ayuda,

white de ese modo lo importante que es el tipo de codificación a la hora de utilizar estos métodos.

Un saludo!

0voto

Leonardo-Tadei comentado

Hola @white,

htmlspecialchars() no falla si le pasás como tercer parámetro el tipo de codificación.

En tu ejemplo, si bien el documento tiene las cabeceras de definición ISO-8859-15, el juego de caracteres que tenga tu string literal puede ser otro (el del tipo de documento en el disco o el de la cabecra que emita el servidor)

3votos

carlossevi Puntos63540

De la documentación de addslashes():

Para escapar parámetros de bases de datos, deberían usarse funciones
de escape específicas de cada SGBD por razones de seguridad (p.ej.
mysqli_real_escape_string() para MySQL o pg_escape_literal(),
pg_escape_string() para PostgreSQL). Los SGBD poseen una
especificación de escape diferente para identificadores (p.ej. Nombre
de tabla, nombre de campo) que para parámetros.

Por lo tanto, también depende de si estás "escapando" caracteres de una cadena para mostrar por pantalla (evitar XSS) o para usarlo en una consulta a la base de datos (evitar SQL injection).

0voto

pabeni comentado

Hola carlossevi,

Gracias por la aclaración, pero lo que quiero es saber cual es la medida mas efectiva para parar los ataques XSS, como yo propongo mi método quiero que me digáis que os parece y que me propongáis alternativas mejores que conozcáis.

En cuando al SQLi yo hago uso de consultas preparadas en PDO que por lo que he leído es de lo mejorcito para evitar estos ataques ya que el usuario no interactua directamente con la consulta a la hora de introducir el valor(como parámetro) ya que lo que hace es hacer un machin par valor de este modo el usuario mal intencionado no puede modificar la consulta(como por ejemplo crear una subconsulta para su beneficio)...

4votos

Leonardo-Tadei Puntos227020

Hola @pabeni,

las funciones htmlspecialchars() y htmlentities() hacen cosas diferentes.

htmlspecialchars() te reemplaza por sus equivalentes HTML solo &, ', ", < y >

htmlentities() te reemplaza todos los caracteres que encuentre con sus equivalentes HTML

El uso de addslashes() no debería ser necesario en un servidor bien configurado, porque se supone que tiene activadas las MAGIC_QUOTES y las comillas ya llegan escapadas.

En tu propuesta, el uso de addslashes() no tiene sentido, porque la función anterior te reemplazó ya todas las ' y las " por los &quot.

Lo que tenés que tener siempre en cuenta es no mezclar el uso de funciones, porque si no diferentes partes del software tendrán que tratar de diferente manera los strings... también ser muy cuidadoso de evitar el doble saneo, porque un & se transforma en un &amp; que se transforma en un &amp;amp; con lo que se te rompe todo.

Por lo de la DB, si estás haciendo consultas preparadas con PDO, no tenés problemas de inyección.

Saludos

0voto

pabeni comentado

Hola Leonardo-Tadei,

Con lo de doble saneo te refieres a que si por ejemplo hago uso de la función addslashes('Hola que tal "estáis"') me remplazaría la cadena de la siguiente manera Hola que tal &quotestais&quot con lo que al emplearle a esa cadena la función htmlspecialchars() se comería las & no mostrando correctamente la cadena no interpretando correctamente la cadena con las & si no con amp; no?

Por lo que entiendo y las pruebas que he realizado es lo siguiente:

  • htmlspecialchars(): Este método me va a mantener todos los tags que el usuario introduzca junto al texto, pero este texto no cogerá formato cuando lo muestre por pantalla, así como el Javascript.

  • htmlentities() : Este método tiene como finalidad no escapar los tags, directamente lo que hace es suprimirlos, con lo que el código HTML/Javascript que el usuario introduzca no se mantendrá.

  • addslashes() : Este método tiene como finalidad suprimir todos las comillas dobles y simples(',"). Pero tengo entendido que se pueden saltar fácilmente haciendo su equivalencia en otro tipo de codificación como por ejemplo el código ASCII.

  • MAGIC_QUOTES : Activar esta directiva en el servidor tengo entendido que es totalmente des aconsejable por el mismo motivo que antes visto con el método addslashes().

Que procedimiento me propones Leonardo-Tadei para evitar mas o menos por completo estos ataques en el lado del cliente?

Un saludo!

0voto

Leonardo-Tadei comentado

Acá usamos

trim(htmlentities($var));

en la entrada, con lo que todo caracter problemático es reemplazado por su equivalente HTML y de paso sacamos blancos superfluos.

Lo bueno de esto es que, de ser necesario, se puede convertir el juego de caracteres entrante para ser tomado como el cliente lo envía. De esta forma la visualización es independiente del juego de caracteres a usar.

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

Luego para mostrar usamos

print( html_entity_decode($var) );

y recuperamos el formato original.

La contra de esto es que tenés que prever campos VARCHAR más largos, ya que los caracteres codificados en HTML ocupan más.

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta