Español | English
rss facebook linkedin Twitter

Seguridad en Ruby on Rails (II)

En un post anterior comentamos algunos errores de seguridad típicos del desarrollo de aplicaciones web con el framework Ruby on Rails. En esta ocasión profundizaremos un poco más en este tema. Para ello veremos las diferentes soluciones disponibles en RoR para mejorar la seguridad de nuestra aplicación, así como otras recomendaciones a tener en cuenta desde la fase inicial de diseño hasta el despliegue de la aplicación.



¿Cómo podemos evitar vulnerabilidades XSS en el código de una aplicación Rails?

Las vulnerabilidades de Cross Site Scripting (XSS), aunque a priori pueden parecer bastante inofensivas, dejan de serlo cuando se combinan con otras técnicas. En ocasiones aprovechando fallos con pocas posibilidades de solución. Me refiero a la estupidez humana (ingeniería social). Se me vienen a la mente dos casos bastante recientes que han tenido gran repercusión. Uno de ellos en los medios generalistas. El otro en un ámbito más técnico.

- El caso del supuesto "hackeo" a la Web de la presidencia europea con la "modificación" de la página oficial por una imagen de Mr.Bean.

- La intrusión en varios servidores de la fundación Apache a mediados de Abril de 2010, para la cual se sirvieron de una vulnerabilidad XSS en JIRA, una aplicación de gestión de bugs para desarrolladores de software.

En el primer caso (que se sepa) no se llegó a producir una intrusión real. Lo que ocurrió fue que se filtró una captura de pantalla donde se podía ver una fotografía de Mr.Bean, insertada mediante javascript en la página mostrada por el navegador de un usuario. Las consecuencias, una repercusión brutal en los medios y como mínimo un daño importante a la imagen de las empresas y entidades relacionadas.

En el segundo caso la intrusión si fue real, afectando a varios servidores de la infraestructura de la fundación apache. El 5 de Abril los atacantes abrieron un ticket en el sistema JIRA con un supuesto nuevo bug. El ticket contenía un enlace de tinyurl.com (un acortador de direcciones url) que redirigía a la propia instancia de JIRA en el servidor de Apache, en una url que explotaba una vulnerabilidad XSS. El ataque logró obtener las cookies de sesión de varios administradores. La explicación de los pasos posteriores de la intrusión, aunque interesantes se salen por completo del ámbito de este documento.

En definitiva, no se deben menospreciar las vulnerabilidades de tipo XSS.

Las versiones de Rails anteriores a la 2, proporcionaban soluciones de filtrado para evitar esta vulnerabilidad utilizando un enfoque de lista negra. Es decir, trataban de filtrar todos los posibles caracteres inválidos proporcionados por los usuarios que en su salida al código html devuelto por la aplicación permitiesen explotar esta vulnerabilidad.

De manera que el uso de strip_tags() permitía la inserción de código como el siguiente:


strip_tags("texto<<b>script>alert('hola')<</b>/script>")


Lo que devolvía "texto<script>alert('hola')</script>", siendo interpretado por el navegador y posibilitando un ataque de tipo XSS.

Este enfoque es totalmente incorrecto. Se trata de una tarea imposible debido al elevado número de posibles combinaciones y técnicas de serialización (uso de diferentes encodings).

El enfoque correcto pasa por aplicar un filtrado de lista blanca, teniendo en cuenta sólo los caracteres permitidos. Rails a partir de la versión 2 permite hacer esto utilizando el método sanitize(). A modo de ejemplo es posible definir un listado de etiquetas html permitidas como el siguiente:


tags = %w(a acronym b strong i em li ul ol h1 h2 h3 h4 h5 h6 blockquote br cite sub sup ins p)

s = sanitize(datos_facilitados_por_el_usuario, :tags => tags, :attributes => %w(href title))


Para filtrar la salida de los datos proporcionados por los usuarios que vaya a ser incluida en el código html de las diferentes páginas, se pueden utilizar las siguientes alternativas:

- escapeHTML() ó su alias h()
- Plugins:

* http://github.com/nzkoz/rails_xss (Para Rails 2.3)
* http://agilewebdevelopment.com/plugins/safe_erb
* http://code.google.com/p/xss-shield/ (Tainting way)

El método h() sustituye los caracteres &,",<,> por sus representaciones en HTML (&, ",< and >). Para evitar descuidos se puede utilizar el plugin safe_erb. Este plugin genera una excepción si el desarrollador se ha olvidado de utilizar el método h() en los templates rhtml de las vistas.

Se debe prestar especial atención a las acciones de un controlador que devuelven un string en lugar de renderizar una vista. Hay que escapar los valores usando el método h(). En las plantillas rjs de código javascript, si se utiliza contenido facilitado por el usuario hay que escaparlo utilizando "escape_javascript()" y en las partes de código html utilizar h().

La versión 3 de Rails modifica el comportamiento por defecto al incluir strings en las plantillas que generarán el código html, escapando automáticamente los caracteres, por lo que ya no es preciso utilizar el método h(). Se ha realizado la integración del plugin rails_xss que funcionaba para la versión 2.3, con algunas optimizaciones.

En Rails 3, los Strings que se incluyen en las plantillas con <%= %> se escapan automáticamente. Si el String no está "limpio" se puede llamar a su método html_safe: "texto".html_safe . Si es necesario mostrar un String intacto se puede utilizar el helper raw: raw("texto")

¿Cómo evitar inyecciones de código SQL?

Veamos primeramente el "hola mundo" de los métodos de autenticación de usuarios en versión Rails. Un ejemplo clásico y claramente vulnerable.



def comprueba_login

if @usuario = Usuario.find(:first, :conditions =>

"nombre = '#{params[:usuario][:nombre]}' "

"AND password = '#{params[:usuario][:password]}'" )

session[:usuario_id] = @usuario.id

redirect_to usuario_path(@usuario)

else

flash[:notice] = "La contraseña para el usuario #{params[:usuario][:nombre]}, "

flash[:notice] << "es incorrecta"

redirect_to '/login'

end

end



Como se puede apreciar, se hace una búsqueda utilizando el modelo Usuario, en la cual se establecen las condiciones a partir de las credenciales facilitadas en el formulario de autenticación. ActiveRecord transforma este código en la siguiente sentencia SQL:


SELECT * FROM usuarios WHERE (nombre = '' AND password = '' ) LIMIT 1


De este modo, si un usuario introduce como nombre por ejemplo "s21sec" y como contraseña algo similar a: "loquesea ' OR 'a'='a" el código del método comprueba_login, al utilizar la contraseña del usuario en las condiciones de la búsqueda sin realizar ningún filtrado, permitirá modificar la lógica de la consulta SQL, concediendo el acceso al usuario.

La sentencia quedaría así:


SELECT * FROM usuarios WHERE (nombre = 's21sec' AND password = 'fake' OR 'a' = 'a' ) LIMIT 1


Sólo si la aplicación Rails está ejecutándose en modo desarrollo (RAILS_ENV establecido a development), al introducir cualquier carácter que provoque un error de SQL, veríamos un error de ActiveRecord::StatementInvalid con los detalles. Si el entorno está configurado como producción mostraría un error más genérico.

Existen varias alternativas para arreglar este código. Las más sencillas, y centrándonos exclusivamente en impedir la inyección de sentencias SQL serían:

- Efectuar búsquedas utilizando los métodos de los modelos find_(id) o los métodos dinámicos de búsquedas como find_by_algo(algo), delegando la validación de estos parámetros al framework ActiveRecord.

- Pasar un array a las condiciones de la búsqueda usando el método find con "named bind variables":

Usuario.find(:first, :conditions => ["nombre = ? AND password = ?", nombre_usuario, clave])

- También se puede pasar un hash en las condiciones del método find:

Usuario.find(:first, :conditions => {:nombre => nombre_usuario, :password => clave})

Estas tres opciones garantizan la inmunidad de la aplicación ante vulnerabilidades de inyección de sentencias SQL.

Otra alternativa que puede resultar interesante para determinadas aplicaciones en las que los datos provienen no sólo de los formularios Web es implementar la lógica de validación en los modelos. Si se necesita un filtrado complejo, puede ser más práctico, ya que se estaría facilitando la reutilización de estas protecciones para otros puntos de entrada de datos.

En el caso de código que ejecuta las sentencias sql directamente utilizando los métodos connection.execute() o Modelo.find_by_sql() será preciso realizar el filtrado a mano.

Las sesiones en Rails

Las sesiones en una aplicación Web son colecciones de variables que permiten hacer un seguimiento del estado de un usuario en particular. Las sesiones se pueden almacenar en una cookie, en archivos, en una base de datos ... etc. En el caso de Rails, se crea una nueva sesión automáticamente cada vez que un nuevo usuario accede a la aplicación, usando una sesión ya existente si el usuario ya ha utilizado la aplicación con anterioridad.

La sesión habitualmente consiste en un hash (también llamado diccionario) de valores, y un identificador de sesión (id) que suele ser un string de 32 caracteres para identificar el hash. Cuando el usuario solicita una página a la aplicación Web, su navegador envía una cookie que contiene el identificador de sesión y de igual forma cuando recibe la página recibe también la cookie con el identificador de sesión.

Cuando las cookies no son el lugar de almacenamiento de las sesiones, se guarda un identificador (id) en la cookie de forma que Rails pueda localizar los datos de sesión donde estén almacenados, por ejemplo en una base de datos.

El identificador de sesión (id) es un hash de un string aleatorio. Este string contiene la hora actual, un número entre 0 y 1, el id del proceso correspondiente al interprete de Ruby y una constante.

Rails ofrece varios mecanismos para el manejo de sesiones:

- PStore (por defecto en Rails 1.x)
- CookieStore (por defecto en Rails 2.x)
- ActiveRecordStore
- DRbStore
- FileStore
- MemoryStore
- MemCacheStore

Las dos más populares son ActiveRecordStore y CookieStore.

En el caso de ActiveRecordStore, las sesiones se almacenan en una tabla de la base de datos, guardando el hash y el id. La aplicación guarda y recupera el hash con cada petición.

CookieStore es el mecanismo por defecto a partir de la versión 2 de Rails. El hash de sesión del usuario se almacena directamente en las cookies, eliminando la necesidad de realizar consultas a la base de datos y por lo tanto mejorando el rendimiento de la aplicación. Sin embargo, este mecanismo no está exento de polémica y se deben tener en cuenta ciertas consideraciones de seguridad:

- En primer lugar, se debe hacer un uso responsable de los datos almacenados en las sesiones. No es conveniente almacenar datos críticos ni tampoco gran cantidad de información. En el caso de las cookies, su propia naturaleza impone un límite de 4Kb.

- Los usuarios de la aplicación van a poder ver todo lo que se almacena en la sesión, ya que los valores no están cifrados. Simplemente se codifican en Base64 por una cuestión de serialización. Para evitar que se pueda realizar una manipulación del hash de la sesión, se calcula un resumen a partir de la sesión utilizando una clave secreta almacenada en el servidor. Este resumen se añade al final de la cookie.

La seguridad de este método de almacenamiento se basa en el algoritmo utilizado para realizar el resumen (SHA512) y en la calidad del secreto almacenado en el archivo config/initializers/session_store.rb:



ActionController::Base.session = {

:key => '_prueba_session',

:secret => 'a5d412ce3610d722d2d3ddcf3311f9ed0a0133052652e4f0054b11bd4a93be650ec84a98fdad541fb9371f0ebc43af709e107d1b93457fabf07cecd34516ffd9'

}



Para garantizar la robustez del valor secreto, este debe ser como mínimo de 30 caracteres y no contener palabras que puedan aparecer en diccionarios. Si por algún motivo se necesita cambiar el valor secreto se puede ejecutar "rake secret". Esta tarea de rake nos proporcionará un nuevo valor. Se debe tener en cuenta que al cambiar el valor secreto todas las cookies en uso quedarán anuladas.

Uno de los problemas de la implementación de las sesiones utilizando cookies es la posibilidad de efectuar ataques de replicación. Un ejemplo clásico y que se entiende muy bien es el de un usuario que realiza una compra en una aplicación online. El usuario puede manipular la cookie que recibe del servidor y reenviarla en el momento de la compra con el valor de su crédito disponible modificado. Si la aplicación es vulnerable, el usuario podría llegar a realizar una compra sin necesidad de tener el suficiente crédito.

Teniendo esto en cuenta, se debe evitar guardar en la sesión valores sensibles como puedan ser créditos de usuarios en tiendas online, o utilizar variables que sirvan para identificar el nivel de acceso de un usuario (ej: variable es_administrador). El seguimiento de este tipo de datos de debe implementar almacenándolos en la base de datos y guardando en la sesión el id que identifique al usuario autenticado en la aplicación.

Si nos hemos decidido por utilizar CookieStore en nuestra aplicación Web y además queremos añadir cifrado a las cookies, podemos hacerlo utilizando un plugin para Rails 2.3 desarrollado por el equipo de Phusion (creadores del módulo mod_rails para Apache): Encrypted cookie store. (http://github.com/FooBarWidget/encrypted_cookie_store)

Otra de las consideraciones a tener en cuenta en la implementación y uso de las sesiones es la posibilidad de que la aplicación contenga una vulnerabilidad de fijación de sesión. Este tipo de vulnerabilidades se producen cuando un usuario es capaz de forzar a otro a utilizar un identificador de sesión ya conocido, de manera que una vez que el usuario se autentica se tiene acceso a su sesión autenticada. La forma de evitar esto es hacer que la aplicación Web renueve la sesión de los usuarios una vez que se autentican, invalidando el identificador de sesión anterior al proceso de autenticación.

En Rails se crea una sesión nueva con: reset_session

El tiempo durante el cual es válida una sesión también es importante. Es aconsejable limitar este tiempo a un valor razonable (ej:15-20 minutos) así como proporcionar la opción de realizar un "logout" haciendo que la aplicación caduque el token de sesión del usuario.

Medidas para evitar vulnerabilidades de tipo CSRF

Las vulnerabilidades conocidas como Cross-Site Request Forgery (CSRF) son aquellas que permiten forzar a un usuario a realizar acciones no deseadas en una aplicación Web en la cual ya está autenticado, sirviéndose por ejemplo de técnicas de ingeniería social como puede ser el envío de un enlace ofuscado por correo electrónico.

Si el usuario que sufre este tipo de ataques tiene permisos de administración en la aplicación Web, se puede llegar a comprometer la aplicación por completo.

Rails proporciona al desarrollador algunos mecanismos para tratar de evitar el éxito de ataques de tipo CSRF. A partir de la versión 2, se incluye la posibilidad de utilizar tokens de seguridad en todas las peticiones Web que no sean de tipo GET. De este modo se asegura que todas las peticiones de formularios y AJAX proceden de la propia aplicación Web.

Mediante la inclusión del método protect_from_forgery :secret => "123456789012345678901234567890" en el controlador de la aplicación, se activa el uso de un token de seguridad calculado a partir del secreto que se le pasa a este método y de la sesión en uso.

Es importante tener en cuenta que esto no efectuará comprobaciones con las peticiones a las APIs XML que pueda tener la aplicación.

Si la aplicación Web sigue los principios de la técnica de arquitectura REST (Representationa State Transfer), es recomendable hacer uso de otra medida que proporciona Rails: la posibilidad de especificar las acciones de los controladores que serán permitidas en función de los métodos Web necesarios. Las aplicaciones RESTful hacen uso de los métodos Web POST, GET, PUT y DELETE, equiparando su uso a las operaciones CRUD típicas (ej: para borrar un proyecto se enviaría su identificador usando el método DELETE).

Es posible asociar y restringir el uso de determinadas acciones a determinados métodos HTTP. Para ello se utiliza el método verify en los controladores.

Ej:


verify :method => :delete, :only => [:destroy], :redirect_to => {:action => :denegar}



De este modo, un ataque CSRF que fuerce al navegador de un usuario a realizar la siguiente petición GET con el objetivo de borrar un proyecto fracasará, ya que la aplicación primeramente espera que esa acción sólo se pueda solicitar mediante un método HTTP Delete.



<img src="http://dominio/projecto/1/destroy">



Es posible utilizar javascript para crear formularios de forma dinámica y de este modo realizar peticiones usando métodos Web diferentes, por ello es preciso tomar la precaución de activar el token de seguridad con el método protect_from_forgery.

Otra contramedida para evitar este tipo de vulnerabilidades es asegurarse de realizar una gestión efectiva de las cookies de sesión, limitando su tiempo de validez a un periodo aceptable en función de los requisitos de la aplicación (ej:15 minutos).

Almacenamiento seguro de información sensible

Cuando la aplicación Web requiere el almacenamiento de información sensible (ej: ciertos datos personales de los usuarios) es conveniente ser prudentes y guardar estos datos de forma cifrada. Seleccionar un algoritmo de cifrado adecuado es vital para garantizar la confidencialidad de la información.

Para el caso de datos sensibles que deban poder ser recuperados, como pudiera ser el caso de la respuesta a una pregunta que permita iniciar el proceso de restablecimiento de la contraseña de un usuario, son más recomendables determinado tipo de algoritmos.

Una buena opción puede ser el uso del algoritmo simétrico AES con block_mode CBC y una longitud de clave de 128 bits. Para implementar esta opción en Rails, lo más aconsejable es usar la librería estándar de OpenSSL, por ejemplo creando un módulo con los métodos de cifrado y descifrado y después haciendo uso de los callbacks de ActiveRecord para cifrar / descifrar los atributos del modelo cuando se almacenen o se recuperen de la base de datos.

Un caso especial puede ser una aplicación que precise sólo el almacenamiento de información con un alto requerimiento de confidencialidad, o cuando se trata de información que se intercambia con otra aplicación. Para estas situaciones, una opción a considerar puede ser el uso de criptografía asimétrica.

En Rails es posible llegar a implementar un sistema de cifrado basado en claves pública/privada que sirva para almacenar este tipo de datos, de forma bastante simple utilizando Strongbox (http://github.com/spikex/strongbox). Se trata de un proyecto a mi parecer muy interesante, ya que nos va a permitir generar un juego de llaves RSA mediante openssl y utilizarlas en nuestro sistema de cifrado, de forma que será posible limitar el uso de la llave privada (utilizada para descifrar los datos) desde un servidor privado. Mediante una tarea rake/Capistrano podemos eliminar fácilmente la llave privada del listado de archivos a desplegar en el servidor en producción.

Uso de soluciones de anti-automatización
En determinadas aplicaciones Web, es interesante contemplar el uso de soluciones que proporcionen medidas anti-automatización. En este sentido, la implantación de CAPTCHAS (http://es.wikipedia.org/wiki/Captcha) permite distinguir el uso automatizado de la aplicación, pudiendo ser muy eficiente con el fin de evitar:

- La publicación automática en blogs, foros ..etc.

- La creación automática de cuentas de usuarios (ej: cuentas de correo electrónico).

- Situaciones en las que se permite el envío automático de muchas peticiones Web y se necesita integrar un factor limitante del tiempo (ej: envío de sms o correos).

- Vulnerabilidades que permiten la enumeración de usuarios, cuentas de e-mail, números de teléfono ...etc.

Rails cuenta con diferentes alternativas para integrar una solución de CAPTCHA. Teniendo en cuenta una serie de características de seguridad que deben cumplir las imágenes CAPTCHA generadas, y que no procede tratar a fondo aquí, una de las mejores opciones es el plugin recaptcha (http://github.com/ambethia/recaptcha).

Utilizando este plugin, se externaliza la generación de CAPTCHAS añadiendo helpers a la aplicación Rails que permiten el uso sencillo de la API del servicio reCAPTCHA (recaptcha.net). A veces es mejor utilizar algo que ya funciona bien a empeñarse en reinventar la rueda.

Autenticación y autorización de usuarios

Existen múltiples plugins para Rails que facilitan el desarrollo de procesos de autorización y autenticación. Los más utilizados para implementar la autenticación de los usuarios son RestfulAuthentication y Authlogic.

La autenticación de usuarios es el proceso de identificar y verificar a un usuario. Es decir, se trata de saber qué usuario está interactuando con la aplicación y poder tener la certeza de que en efecto sí es él.

Existen diferentes formas de implementar la autenticación. La más común es la autenticación descentralizada, en la cual no se requiere infraestructura adicional para autenticar a los usuarios. El caso contrario es la autenticación centralizada: Sistemas de Single Sign On (SSO) que permiten la autenticación de usuarios entre múltiples aplicaciones sin la necesidad de que estos proporcionen sus credenciales de acceso cada vez que desean identificarse.

Algunos sistemas SSO populares son:

- OpenID
- CAS
- Kerberos
- GSS-API
- SPNEGO
- OAuth

En el caso de los entornos empresariales, es común la presencia de Servidores LDAP (Lightweight Directory Access Protocol). Desde Rails también se puede utilizar LDAP mediante la gema ruby-net-ldap, de forma que es viable implementar un sistema de autenticación mixto (usuarios de la aplicación + usuarios procedentes de LDAP).

En general, es aconsejable separar el código encargado de los procesos de autenticación del que se ocupa de la autorización. Esto permite una mayor flexibilidad y además es más fácil de mantener si se detecta una vulnerabilidad en alguno de los procesos.

La autorización referida a los usuarios de una aplicación, es el proceso de permitir o denegar el acceso a un determinado recurso, o realizar una determinada acción o grupos de acciones. También se le conoce como control de accesos.

Existen diferentes enfoques para de cara a implementar la autorización:

- Mandatory Access Control (MAC): Se permite el acceso a los recursos en función del tipo de información contenida en los objetos y en la autorización formal de los usuarios. Por ejemplo, información confidencial, pública ...etc.

- Discretionary Access Control (DAC): Se permite acceso a los objetos en base a la identidad de los usuarios o grupos a los que pertenezcan. Un ejemplo es la implementación de permisos de archivos de sistemas operativos como Windows o unix.

- Role-based Access Control (RBAC): Se asocian controles de acceso con las acciones en un sistema a un nivel superior al de los objetos. Es decir, el acceso se controla mediante permisos basados en asignación de roles.

Hay múltiples opciones para implementar un sistema de autorización en Rails. Para las aplicaciones que no requieran de un alto grado de detalle, quizá una buena opción sea crear un sistema propio desde cero, o bien partiendo de soluciones sencillas como role_requirement (http://code.google.com/p/rolerequirement/). También existen plugins bastante interesantes, capaces de lidiar con escenarios complejos como es el caso de DeclarativeAuthorization.

Este plugin, proporciona un mecanismo de autorización basado en roles (RBAC). DeclarativeAuthorization (http://github.com/stffn/declarative_authorization) destaca porque las reglas de autorización están agrupadas en un archivo de políticas, y los privilegios se utilizan dentro del código del plugin para forzar las restricciones necesarias. Es decir, implementa las reglas fuera de la capa lógica del código, haciéndolo de forma más limpia que otras soluciones.

Otros plugins interesantes son:

- ActiveRbac (http://active-rbac.rubyforge.org/). Facilita la implementación de un control de accesos RBAC.
- ModelSecurity (http://perens.com/FreeSoftware/ModelSecurity/). Implementa el control de acceso en el modelo de datos.

Tanto si optamos por el uso de alguno de los plugins más populares, como si nos decidimos por el desarrollo de uno propio desde cero, hay una serie de recomendaciones de seguridad que es aconsejable tener en cuenta:

- El proceso de recuperación de contraseñas: Algunas aplicaciones Web implementan de forma inapropiada este proceso. Es aconsejable no permitir la recuperación de las contraseñas de los usuarios. En su lugar, se debe iniciar un proceso de restablecimiento, permitiendo al usuario recibir una nueva contraseña generada de forma automática, con un mínimo de robustez. Idealmente, esta contraseña debe ser temporal, siendo necesario que el usuario la cambie pasado un tiempo razonable.

- Cambio de contraseñas de usuarios: Si el usuario requiere efectuar el cambio de su contraseña, es aconsejable que la aplicación solicite la vieja contraseña, contribuyendo a evitar la explotación de vulnerabilidades de tipo CSRF.

- El proceso de cambio de cuenta de e-mail: siempre debe solicitar la contraseña, por si la cuenta ha sido comprometida.

- Dependiendo de la aplicación, puede ser interesante disponer de un proceso de activación de cuentas. En el caso de que se haga uso de esta funcionalidad, es importante que los enlaces de activación contengan tokens de un solo uso, y que estos caduquen en un tiempo razonable.

- Almacenamiento de contraseñas: En el caso de las contraseñas de los usuarios, es recomendable el uso de funciones de hash que utilicen algoritmos con un coste computacional elevado. En este sentido, una de las mejores alternativas para Rails, es la utilización de la librería bcrypt de Ruby. Esta librería implementa el popular algoritmo bcrypt utilizado en FreeBSD para cifrar las contraseñas. Bcrypt se basa en el uso del algoritmo Blowfish. Su principal ventaja reside en la capacidad de realizar el hash de la contraseña no sólo una vez sino en varias iteraciones, añadiendo bits aleatorios de la "sal", incrementando considerablemente el tiempo necesario para llevar a cabo un ataque de fuerza bruta de contraseñas.

Un error habitual para la generación de los hashes de las contraseñas es la utilización de algoritmos considerados inseguros como (DES o MD5) y además no utilizar un valor "sal" o utilizar siempre el mismo. Debemos evitar esto y como mínimo implementar una solución con SHA1 variando la sal para cada usuario. Estas dos medidas dificultarán en gran parte la labor de alguien que haya podido obtener los hashes de algún modo.

Algunos de los plugins mencionados antes, cumplen en parte con estos requisitos. Por ejemplo RestfulAuthentication ya incluye un sistema de activación de usuarios que permite enviar por correo electrónico un enlace de activación.

Conclusión

Además de las medidas de seguridad que se han comentado, otras recomendaciones que pueden contribuir a establecer un buen nivel de seguridad en una aplicación Rails son:

- Separar la interfaz administrativa en una aplicación aparte, con su propio sistema de autenticación, colocando el panel de administración en un subdominio.

- Establecer un acceso administrativo limitado por ip. (comprobar request.remote_ip), requiriendo el uso de certificados digitales para poder realizar el acceso.

- Implementar un sistema de registro de errores relacionados con sucesos de seguridad (ej: autenticación incorrecta, token inválido, borrado de usuarios, creación de usuarios con privilegios ...etc)

- Implantar un sistema de alertas que recoja información de los registros de errores de autenticación y comportamientos inusuales de los usuarios.

- Configurar la sesión para el uso de protocolos de cifrado (preferiblemente ssl v3) para la transmisión de información sensible. (ActionController::Base.session_options[:session_secure] = true)

- Activar el acceso de las cookies sólo por http con el atributo httponly y hacer un uso apropiado del atributo secure.

- Ojo con el despliegue de la aplicación: Se deberá evitar el despliegue de archivos y directorios de subversion. Cuidado con database.yml y los archivos que contienen los valores secretos para impedir la manipulación de las cookies según las distintas versiones de Rails.


Tampoco se debe olvidar la seguridad de la infraestructura dónde esté hospedada la aplicación Rails. Es importante securizar los servidores de producción y establecer medidas básicas que mitiguen la posible explotación de potenciales vulnerabilidades, como la creación de una cuenta con permisos limitados en los gestores de bases de datos utilizados desde la aplicación Web.

En definitiva, como se ha podido ver a lo largo de este documento, las aplicaciones Web desarrolladas con Ruby on Rails no están exentas de riesgos de seguridad.

Sin embargo, no es difícil aplicar las medidas oportunas que impidan la presencia de vulnerabilidades. Ya sea partiendo de plugins que faciliten el desarrollo o bien creando las funcionalidades desde cero. En cualquier caso, será una tarea que llevará tiempo, pero que claramente merece la pena a medio-largo plazo.

----
Daniel Peláez.
Dept. Auditoría S21sec

(+34 902 222 521)


24 horas / 7 días a la semana



© Copyright S21sec 2013 - Todos los derechos reservados


login