
JSON.generate en Ruby expone memoria heap arbitraria al pasar null bytes en JSON::State.space.
La clase `JSON::State` de Ruby expone parámetros como `space`, `indent`, `object_nl` y `array_nl` para controlar el formato del JSON generado. Al inicializar `space` con null bytes (`"\0" * 1024`), la extensión nativa en C que implementa la json gem no sanitiza el parámetro antes de escribirlo como separador en el buffer de salida.
El resultado: `JSON.generate` incluye en su output contenido arbitrario del heap (la zona de memoria dinámica del proceso — donde Ruby almacena objetos vivos, strings y estructuras internas). En el ejemplo publicado, el leak expone rutas reales del sistema (`mydata/scm/git/ruby/dist/lib/ruby/2.5.0/json/ext.rb`), fragmentos de código interno (`psych/handlers/recorder.rb`, `Gem::Specification.new`) y strings residentes en memoria en ese instante.
La causa raíz es un bug clásico de *binding C*: el código nativo trata `space` como una string opaca y la vuelca directamente al buffer sin comprobar null bytes ni longitud razonable.
Este patrón aparece en bindings C de múltiples lenguajes dinámicos: Python, Ruby, Node.js con addons nativos. El riesgo real no es solo el stack trace visible — es lo que *puede* estar en heap en el momento del request: tokens de sesión, claves API cargadas como strings, credenciales de base de datos en memoria.
Si el endpoint que invoca `JSON.generate` acepta opciones de formato controladas por el cliente (común en APIs que ofrecen pretty-print o indentación variable), esto se convierte en un oráculo de memoria remoto. Un atacante puede variar el offset del `\0` en sucesivos requests y reconstruir regiones del heap de forma sistemática.
La superficie es más amplia de lo que parece: librerías de serialización (JSON, YAML, MessagePack) con bindings nativos son candidatas directas al mismo vector.
La lección técnica es directa: los bindings C no heredan las garantías de seguridad del runtime del lenguaje huésped. Cada parámetro que cruza la frontera nativa necesita validación explícita en el lado Ruby antes del salto — el runtime no te cubre ahí.
Ayuda a que más gente descubra BBLabs News.
¿Quieres recibir noticias así cada día?
Ver todos los artículos