2010-01-03 4 views
8

: es la prevención de XSS (cross-site scripting) tan simple usando strip_tags en cualquier campo de entrada guardados en funcionamiento htmlspecialchars en cualquier mostrado salida y la prevención de ... Inyección de SQL mediante el uso de instrucciones preparadas por PHP PDO?es la prevención de XSS y SQL Injection tan fácil como lo hace esta pregunta

He aquí un ejemplo:

// INPUT: Input a persons favorite color and save to database 
// this should prevent SQL injection (by using prepared statement) 
// and help prevent XSS (by using strip_tags) 
$sql = 'INSERT INTO TABLE favorite (person_name, color) VALUES (?,?)'; 
$sth = $conn->prepare($sql); 
$sth->execute(array(strip_tags($_POST['person_name']), strip_tags($_POST['color']))); 


// OUTPUT: Output a persons favorite color from the database 
// this should prevent XSS (by using htmlspecialchars) when displaying 
$sql = 'SELECT color FROM favorite WHERE person_name = ?'; 
$sth = $conn->prepare($sql); 
$sth->execute(array(strip_tags($_POST['person_name']))); 
$sth->setFetchMode(PDO::FETCH_BOTH); 
while($color = $sth->fetch()){ 
    echo htmlspecialchars($color, ENT_QUOTES, 'UTF-8'); 
} 
+0

No te atrapé del todo - ¿vas a mysql_query() el valor $ save_to_database? Entonces todavía necesita llamar 'mysql_real_escape_string()' antes de enviar su consulta, de lo contrario no estará protegido de las inyecciones de SQL (que no es XSS, nuevamente) – naivists

+2

@naivists: ¿Está seguro de eso? Él está usando declaraciones preparadas. – Erlend

Respuesta

8

Es aún más sencilla. Solo htmlspecialchars() (con estilo de cita y juego de caracteres) en la entrada controlada por el usuario es suficiente. El strip_tags() solo es útil si ya desea desinfectar los datos antes de procesar/guardar en la base de datos, que a menudo no se usa en el mundo real. El código HTML no daña en la fuente PHP, pero el código PHP puede hacerlo si usa eval() en una entrada no desinfectada por el usuario o ese tipo de cosas malvadas.

Sin embargo, esto no le ahorra de SQL injections, pero esa es otra historia.

actualización: para obtener limpia de entrada usuario de la petición de evitar magic quotes en la entrada controlada por el usuario, puede utilizar la siguiente función:

function get_string($array, $index, $default = null) { 
    if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) { 
     return get_magic_quotes_gpc() ? stripslashes($value) : $value; 
    } else { 
     return $default; 
    } 
} 

que puede ser utilizado como:

$username = get_string($_POST, "username"); 
$password = get_string($_POST, "password"); 

(se puede hacer para simliar get_number, get_boolean, get_array, etc)

Para preparar la consulta SQL para evitar SQL injections, hacer:

$sql = sprintf(
    "SELECT id FROM user WHERE username = '%s' AND password = MD5('%s')", 
     mysql_real_escape_string($user), 
     mysql_real_escape_string($password) 
); 

Para mostrar de entrada controlado por el usuario para evitar XSS, hacer:

echo htmlspecialchars($data, ENT_QUOTES, 'UTF-8'); 
+0

¿Cómo puedo modificar para protegerme también de las inyecciones de SQL además de XSS? – TimTim

+1

Use 'mysql_real_esacpe_string()': http://php.net/manual/en/function.mysql-real-escape-string.php. Además, también debe tener en cuenta 'get_magic_quotes_gpc()'. Si esto devuelve verdadero en el entorno de PHP, necesita ejecutar 'stripslashes()' en la entrada también. – BalusC

+0

Si utilicé declaraciones preparadas con PDO, ¿eso previene la inyección SQL? – TimTim

4

strip_tags no es necesario. En la mayoría de los casos, strip_tags es simplemente irritante, porque algunos de sus usuarios pueden querer usar < y > en sus textos. Simplemente use htmlspecialchars (o htmlentities si lo prefiere) antes de hacer eco de los textos en el navegador.

(No se olvide mysql_real_esacpe_string antes de insertar cualquier cosa en su base de datos!)

2

Respuesta simple: no

Respuesta larga: Hay formas de inyectar XSS que strip_stags PHP no puede evitar.

Para una mejor protección intentar HTML purifier

+0

¡Gracias por el consejo! No creo que sea la única solución para este problema exacto, pero es definitivamente bueno si quiero permitir algún formato HTML. –

+1

Imaginemos que tenemos una página con solo '' En su cuerpo. ¿Qué inyecciones son posibles aquí? – naivists

+0

.. cuando 'strip_tags()' se usa * sin * 'htmlspecialchars()'. – BalusC

5

Depende de dónde y cómo se desea utilizar los datos de usuario. Necesita saber el contexto en el que desea insertar sus datos y los metacaracteres de ese contexto.

Si solo desea permitir que el usuario coloque texto en su sitio web, htmlspecialchars es suficiente para escapar de los metacaracteres HTML.Pero si desea permitir cierto HTML o desea insertar datos de usuario en elementos HTML existentes (como una URL en un elemento A/IMG), htmlspecialchars no es suficiente, ya que no está en el contexto HTML sino en el contexto URL.

Así entrar <script>alert("xss")</script> en un campo URL de la imagen producirá:

<img src="&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt" /> 

Pero entrar javascript:alert("xss") tendrá éxito:

<img src="javascript:alert(&quot;xss&quot;)" /> 

Aquí tiene que echar un vistazo a la fabulosa XSS (Cross Site Scripting) Cheat Sheet para ver qué contextos su los datos del usuario se pueden inyectar en.

+0

@Gumbo, ¿mi publicación original actualizada me protege de su ejemplo de no usar una etiqueta de script? – TimTim

+1

@TimTim: solo depende del contexto en el que quiera usar esa información. – Gumbo

+0

@Gumbo ¿cómo previene ese tipo de ataque? Estoy leyendo el enlace owasp que me diste, pero no veo dónde dice cómo prevenir esos ataques. –

3

La regla general/meme es "Entrada de filtro, salida de escape". Usar strip_tags en su entrada para eliminar cualquier HTML es una buena idea para el filtrado de entrada, pero debe ser lo más estricto posible en la entrada que permita. Por ejemplo, si un parámetro de entrada solo se supone que es un entero, solo acepte la entrada numérica y siempre conviértalo en un entero antes de hacer cualquier cosa con ella. Una biblioteca de filtrado de entradas bien revisada te ayudará mucho aquí; uno que no es específico de un marco particular es Inspekt (que escribí, así que estoy un poco parcial).

Para la salida, htmlspecialchars debería ser capaz de escapar de los ataques XSS, pero sólo si se pasan los parámetros correctos. Debe pasar el estilo de escape de cotización y un juego de caracteres.

En general, esta debería eliminar ataques XSS:

$safer_str = htmlspecialchars($unsafe_str, ENT_QUOTES, 'UTF-8'); 

Sin pasar ENT_QUOTES como el segundo parámetro, caracteres de comillas simples no están codificados. Además, los ataques XSS se han demostrado cuando no se pasa el juego de caracteres correcto (normalmente el UTF-8 será adecuado). htmlspecialchars debe llamar siempre con ENT_QUOTES y un parámetro de juego de caracteres.

Tenga en cuenta que PHP 5.2.12 contiene una solución para a multibyte XSS attack.

Puede encontrar el OWASP ESAPI PHP port interesante y útil, aunque la versión de PHP no está completa AFAIK.

+0

@Funkatron, ¿así que mi publicación original actualizada me protege de todo mal? – TimTim

+0

Parece relativamente seguro, sí. – Funkatron

+1

No creo que 'strip_tags' sea una buena idea. Rompe alguna entrada legítima, pero no es suficiente para la seguridad. Solo 'htmlspecialchars()' es suficiente y no tiene pérdida. – Kornel

3

Sí, el uso de sentencias preparadas de PDO protege de la inyección de SQL. El ataque de inyección SQL se basa en el hecho de que los datos enviados por el atacante se tratan como parte de la consulta. Por ejemplo, el atacante envía la cadena "a" o "a" = "a" como su contraseña. En lugar de comparar toda la cadena con las contraseñas de la base de datos, se incluye en la consulta, por lo que la consulta se convierte en "SELECT * FROM users WHERE login = 'joe' AND password = 'a' o 'a' = 'a' ". La parte de la entrada del atacante se interpreta como una parte de la consulta. Sin embargo, en el caso de las declaraciones preparadas, le está diciendo al motor SQL específicamente, qué parte es la consulta y qué parte son los datos (al establecer los parámetros), por lo que no es posible tal confusión.

No, usar strip_tags no siempre lo protegerá de las secuencias de comandos entre sitios. Considera el siguiente ejemplo. Digamos que su página contiene:

<script> 
location.href='newpage_<?php echo strip_tags($_GET['language']); ?>.html'; 
</script> 

El atacante envía la solicitud con el "lenguaje" en " '; somethingevil();'".strip_tags() devuelve esta información como está (no hay etiquetas en ella). El código de la página producido se convierte en:

<script> 
location.href='newpage_';somethingevil();'.html'; 
</script> 

somethingevil() se ejecuta. Reemplazar somethingevil() con el código de explotación XSS real.

Su último ejemplo con htmlspecialchars() protegerá contra este, ya que escapará a las comillas simples. Sin embargo, he visto casos aún más extraños de datos proporcionados por el usuario dentro del código JavaScript, donde ni siquiera está dentro de una cadena entrecomillada. Creo que estaba en la variable o nombre de la función. En ese último caso, ninguna cantidad de escape probablemente ayudará. Creo que es mejor evitar el uso de la entrada del usuario para generar código JavaScript.

+0

'

  • 11. ¿Es esta función suficiente para la detección de xss?
  • 12. Pregunta/aclaración de PHP XSS
  • 13. Pregunta Dapper LIKE para MySql safe contra Sql Injection?
  • 14. SQL-injection: ¿es seguro (oneliner)?
  • 15. Pregunta práctica de Singleton & Dependen Injection
  • 16. Dependency injection container? ¿Qué hace?
  • 17. ¿Por qué este script SQL funciona como lo hace?
  • 18. Resaltado de sintaxis: ¿Cómo lo hace Eclipse tan rápido?
  • 19. ¿Qué tan lejos llega Dependency Injection?
  • 20. Prevención de secuencias de comandos del lado del servidor, XSS
  • 21. Fácil C pregunta enumeración
  • 22. ¿Por qué ValidateRequest = "true" no es suficiente para la prevención de XSS?
  • 23. SQL Injection Protección - comillas simples
  • 24. SQL Server - Dynamic PIVOT Table - SQL Injection
  • 25. ¿Esta búsqueda basada en LINQ es segura contra ataques de inyección SQL/XSS?
  • 26. SQLAlchemy + SQL Injection
  • 27. ¿Cuál es la diferencia entre la prevención de interbloqueos y la prevención de interbloqueos?
  • 28. ¿Son seguras las consultas multilínea sql-injection?
  • 29. ¿Prepara la instrucción prevenir SQL-Injection aquí
  • 30. ¿Cómo piensas y predice el resultado de una pregunta de subprocesamiento como esta?