Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
KindaRails2Shell — Single-file PoC for Rails CVE-2026-66066: arbitrary file read, secret recovery, threaded scanning, and conditional RCE via signed image variations. | Kitploit
Tools/GitHubGitHub/0xsha/kindarails2shell
Vulnerability ScannersExploitationWeb Application ExploitationWeb SecurityPenetration TestingPayload DevelopmentLabs & Practice
GitHub0xsha/kindarails2shell

KindaRails2Shell

Single-file PoC for Rails CVE-2026-66066: arbitrary file read, secret recovery, threaded scanning, and conditional RCE via signed image variations.

View Repository
22102 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

KindaRails2Shell: CVE-2026-66066

A zero-dependency, single-file proof of concept and loopback-only Docker lab for the Rails Active Storage/libvips arbitrary-file-read vulnerability. It also demonstrates the advisory's conditional escalation from a recovered secret_key_base to a forged image variation and command execution.

  • Affected: Rails 7.2.0–7.2.3.1, 8.0.0–8.0.5, and 8.1.0–8.1.3
  • Fixed: Rails 7.2.3.2, 8.0.5.1, and 8.1.3.1
  • Runtime: Python 3.11+, standard library only
  • Scope: authorized testing and local research

Primary references: Rails advisory, Rails forensic analysis, the Ethiack technical write-up, and the 8.1.3.1 release.

Demo

https://github.com/user-attachments/assets/fdcb5651-c1d1-4bc4-b322-8f1205b09635

Why this PoC is useful

kr2s.py contains the complete client in one file:

  • an embedded, patchable HDF5/MAT payload with no h5py or numpy;
  • direct-upload delivery and automatic CSRF handling;
  • variation-key harvesting from an existing Active Storage thumbnail;
  • a strict, standard-library PNG decoder for byte-exact recovery;
  • arbitrary offsets and reads up to 16 MiB per request;
  • secret discovery and a pure-Python Rails variation signer;
  • command-output read-back with a random marker and best-effort cleanup;
  • threaded passive or explicitly active scanning with JSON reports;
  • proxy, custom path, TLS, timeout, and user-agent controls.

The tool does not install packages, start a callback listener, require curl on the target, or depend on make. The RCE stage uses the built-in Active Storage representation route and does not require a Marshal gadget.

Quick start

Start the vulnerable lab:

cd lab
RAILS_VERSION=8.1.3 docker compose up --build

The Compose port is bound to 127.0.0.1 and the container runs as an unprivileged user with all Linux capabilities dropped.

In another terminal:

# Intrusive: uploads a blob, then confirms /etc/hostname is readable.
python3 kr2s.py check http://127.0.0.1:3000

# Recover a fixed-size prefix. Binary output goes to stdout unless -o is used.
python3 kr2s.py read http://127.0.0.1:3000 /etc/passwd --size 4096
python3 kr2s.py read http://127.0.0.1:3000 /etc/passwd -o passwd.bin

# Recover selected environment secrets. Values are redacted by default.
python3 kr2s.py secrets http://127.0.0.1:3000

# Display complete matched environment values for authorized analysis.
python3 kr2s.py secrets http://127.0.0.1:3000 --show-full

# Passive preflight of one target or a file containing one target per line.
python3 kr2s.py scan http://127.0.0.1:3000
python3 kr2s.py scan targets.txt --threads 10 --json scan.json

# Intrusively confirm file read on every target in the list.
python3 kr2s.py scan targets.txt --active

# Probe selected libvips loaders.
python3 kr2s.py probe http://127.0.0.1:3000

# Conditional escalation. This executes the supplied command.
python3 kr2s.py rce http://127.0.0.1:3000 "id; uname -a"

Run python3 kr2s.py COMMAND --help for all overrides. Common real-application controls include --harvest-url, --show-path, --proxy, --insecure, and --skb.

secrets --show-full prints complete matched environment-variable values. Without it, the tool prints only the first 12 characters and an ellipsis. Files requested with --also-read, including the default Rails credential paths, are printed up to 600 characters when readable.

Passive scan only reports whether the page exposes a harvestable Active Storage representation; it cannot identify the installed Rails patch level. scan --active uploads a malicious blob and attempts the canary read. A failed active result is labelled BLOCKED_OR_INCONCLUSIVE, not SAFE, because WAFs, authentication, unsupported variations, and the Rails fix can look identical from outside the application.

Stop the lab with:

cd lab
docker compose down

What the exploit does

  1. The client reserves an Active Storage direct upload declared as image/png.
  2. It uploads a hybrid MATLAB/HDF5 file. The HDF5 dataset uses external storage whose filename and offset point to a file in the Rails process.
  3. A server-signed variation key is harvested from an existing thumbnail and reused with the malicious blob's signed ID.
  4. Vulnerable Rails passes the data to libvips matload; target-file bytes become image pixels and return in a generated PNG.
  5. The client validates and decodes the PNG, then reverses matio's column-major layout to recover the original bytes.

The hybrid file satisfies two parsers at once: its text starts with MATLAB 5.0, while the version word at offset 124 selects the HDF5-backed MATLAB 7.3 path. Rails' fix blocks libvips operations marked untrusted before an attacker-controlled file can reach matload.

Conditional RCE

rce first reads SECRET_KEY_BASE from /proc/self/environ, unless --skb is provided. It derives the Active Storage verifier key and signs a JSON variation containing an instance_eval operation. On the affected vips path, the operation reaches Vips::Image.public_send. The PoC sends it through the built-in representation route, runs the supplied command through /bin/sh, and captures both output streams.

This second stage is conditional on recovering the signing secret and reaching the vulnerable vips transformation behavior described in Ethiack's analysis of CVE-2025-24293. The CVE-2026-66066 patch closes the file-read entry point; it is not a general fix for previously leaked signing secrets. Rotate secrets after suspected exposure, as the Rails advisory recommends.

Command output is written to a random /tmp/.kr2s_* file, recovered through the same file-read primitive, and then removed with a second signed payload.

Read behavior and limits

Reads return the requested fixed-size region. If the source is shorter, its prefix is followed by zero bytes. Use --offset for subsequent regions.

The default lab variation only converts to PNG, so recovery is byte-exact. Real applications may resize variants. The harvested-key mode uses a one-pixel column to avoid horizontal resampling, but a variation with a lower height can still change the geometry. In that case the client fails explicitly; reduce --size or harvest a non-resizing representation.

Every command is intrusive: it creates persistent Active Storage blobs and may create processed variants. rce additionally executes the supplied command.

Version matrix

The matrix script builds each release, runs real read and RCE checks on vulnerable versions, asserts that reads are blocked on fixed versions, and returns nonzero on any mismatch:

./lab/matrix.sh
./lab/matrix.sh 8.1.3
./lab/matrix.sh 8.1.3.1:PATCHED

Validated on 2026-07-31 with Ruby 3.4.10, image_processing 1.14.0, ruby-vips 2.3.0, and libvips 8.16.1:

RailsFile readRCE checkResult
7.2.3.1READ-OKRCE-OKpass
7.2.3.2blockednot runpass
8.0.5READ-OKRCE-OKpass
8.0.5.1blockednot runpass
8.1.3READ-OKRCE-OKpass
8.1.3.1blockednot runpass

Patched rows deliberately do not fire an RCE payload with a pre-supplied signing secret; the matrix tests the CVE's file-read boundary.

Research utilities

research/craft.py regenerates candidate payloads for loader research and requires h5py plus numpy. It is not imported by the release PoC. lab/probe/probe.sh inspects those candidates with ruby-vips inside a lab image:

Download Tool