Code-Injection: Qué es y Cómo prevenirlo (II)

publicado el 2007-10-31 por ikki - categoría: Programación

Code-Injection: Qué es y Cómo prevenirlo (II)

Como mencionamos en el artículo de la semana pasada, validar la data que ingresa por distintas vías a tu sitio (formularios de login, foros, etc.) es muy importante para mantener la seguridad del mismo. Prevenir que un code injection te afecte es sencillo si te apegas a las siguientes normas:

  • No confíes en los usuarios: trata todas las entradas de datos como ataques.
  • Cuando sea posible, envía la data vía POST: así evitas un ataque por URL.
  • Evita o al menos limita el ingreso de TAGS a tus formularios.
  • No muestres mensajes de error muy detallados: evita darle más info a tu atacante.
  • Valida que el tipo de datos que estás recibiendo sea el esperado: si esperas un integer, chequea si la data enviada lo es.
  • Y aunque suene repetitivo: siempre filtra toda la data!

Una forma de prevenir, por ejemplo, un sql injection es escapar siempre la data ingresada. ¿Qué es "escapar"? Es un anglicismo derivado de escape que podría traducirse como anular, cancelar, etc. Si tu base de datos es MySql, ellos ofrecen una función llamada mysql_real_escape_string que se encarga de colocar backslashes a los caracteres x00, \n, \r, \, ', " y \x1a, lo que impide que interfieran con la ejecución normal del query. Un ejemplo práctico de cómo utilizarlo sería el siguiente:

function sanitize_quotes($value) {
    // si magic_quotes_gpc está activo, elimino los backslashes
    if( get_magic_quotes_gpc() ) { 
       $value = stripslashes( $value );
    }

    // verifico si existe la función mysql_real_escape_string para poder aplicarla
    if( function_exists( "mysql_real_escape_string" ) ) {
	$quote_con = conectar();
	$value = mysql_real_escape_string( $value, $quote_con );
	mysql_close($quote_con);
    }    
    else { // en el caso de que no, uso addslashes
	$value = addslashes( $value );
    }
    return $value;
}

$my_string = sanitize_quotes($my_string);

... y luego ya puedes utilizar la variable con los queries hacia tus bases de datos de MySql. Explico un poco el código: la función recibe el valor que quieres limpiar, valida si magic_quotes_gpc está activo y de ser así elimina los backslashes añadidos a tu string, luego si existe la función mysql_real_escape_string la aplica a tu variable para escaparla. En el caso de que no pueda utilizarse la función, se colocan de nuevo los backslashes.

En el caso de los ataques por URL, estos aprovechan aquellos formularios (o links) que envían data a través de la barra de direcciones vía $_GET, por ejemplo http://www.tusitio.com/buscar?id=24, el cual puede ser fácilmente cambiado por http://www.tusitio.com/buscar?id=drop database revistas simplemente con tipearlo en la barra de direcciones del navegador. Evita enviar data de formularios vía $_GET, pero si realmente no tienes otra alternativa entonces pudieses aplicar la función que mencioné arriba para anular la acción.

También mencioné que debes evitar permitir a los usuarios el ingreso de código a los campos de tu formulario. Sí, sé que es nice que tus visitantes puedan utilizar etiquetas html para customizar sus mensajes o que puedan añadir videos o imágenes, pero eso para tí representa un ataque potencial conocido como Cross-site Scripting. Imagina que, por ejemplo, un usuario ingresa en el campo Comentario algo como<script>alert("Cuidado con el Cross-site Scripting!");</script>: esto mostraría una ventana de alerta con el mensaje "Cuidado con el Cross-site Scripting!". Sí, sé que este ejemplo es un poco irreal, pero imagina que alguien pueda ejecutar cualquier código desde tu sitio. Insisto: evitar que los usuarios puedan colocar tags en los formularios, o límitalos utilizando white-lists (listas de tags permitidos).

Como dijo una vez algún conocido: cuando se trata de seguridad, nunca es suficiente.