
Rails CVE-2026-66066 के लिए एकल-फ़ाइल PoC: मनमाना फ़ाइल रीड, सीक्रेट रिकवरी, थ्रेडेड स्कैनिंग, और हस्ताक्षरित इमेज वेरिएशन के ज़रिए सशर्त RCE।
एक शून्य-निर्भरता, एकल-फ़ाइल प्रूफ-ऑफ-कॉन्सेप्ट और केवल-लूपबैक Docker लैब, जो Rails Active Storage/libvips की मनमानी-फ़ाइल-पढ़ने की भेद्यता के लिए है। यह सलाहकार (advisory) की सशर्त उन्नयन क्षमता को भी प्रदर्शित करता है, जो एक प्राप्त secret_key_base से एक जाली छवि वेरिएशन और कमांड निष्पादन तक जाती है।
प्राथमिक संदर्भ: Rails एडवाइज़री, Rails फोरेंसिक विश्लेषण, Ethiack तकनीकी विवरण, और 8.1.3.1 रिलीज़.
https://github.com/user-attachments/assets/fdcb5651-c1d1-4bc4-b322-8f1205b09635
kr2s.py में पूरा क्लाइंट एक फ़ाइल में समाहित है:
h5py या numpy नहीं है;यह उपकरण पैकेज स्थापित नहीं करता, कॉलबैक लिसनर प्रारंभ नहीं करता, लक्ष्य पर curl की आवश्यकता नहीं रखता, और make पर निर्भर नहीं करता। RCE चरण अंतर्निहित Active Storage प्रतिनिधित्व रूट का उपयोग करता है और इसके लिए Marshal gadget की आवश्यकता नहीं है।
भेद्य लैब शुरू करें:
cd lab
RAILS_VERSION=8.1.3 docker compose up --build
Compose पोर्ट 127.0.0.1 से बंधा है और कंटेनर एक अविशेषाधिकार प्राप्त उपयोगकर्ता के रूप में चलता है, जिसमें सभी Linux क्षमताएँ हटा दी गई हैं।
दूसरे टर्मिनल में:
# 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"
सभी ओवरराइड के लिए python3 kr2s.py COMMAND --help चलाएँ। सामान्य वास्तविक-अनुप्रयोग नियंत्रणों में --harvest-url, --show-path, --proxy, --insecure, और --skb शामिल हैं।
secrets --show-full मिलान किए गए पर्यावरण-चर मानों को पूर्ण रूप से प्रिंट करता है। इसके बिना, उपकरण केवल पहले 12 अक्षर और एक ellipsis प्रिंट करता है। --also-read के साथ अनुरोधित फ़ाइलें, जिनमें डिफ़ॉल्ट Rails क्रेडेंशियल पथ शामिल हैं, पठनीय होने पर 600 वर्णों तक प्रिंट की जाती हैं।
निष्क्रिय scan केवल यह रिपोर्ट करता है कि पृष्ठ एक संग्रहणीय Active Storage प्रतिनिधित्व उजागर करता है या नहीं; यह स्थापित Rails पैच स्तर की पहचान नहीं कर सकता। scan --active एक दुर्भावनापूर्ण ब्लॉब अपलोड करता है और कैनरी रीड का प्रयास करता है। एक विफल सक्रिय परिणाम को SAFE नहीं, बल्कि BLOCKED_OR_INCONCLUSIVE लेबल किया जाता है, क्योंकि WAF, प्रमाणीकरण, असमर्थित वेरिएशन, और Rails फिक्स एप्लिकेशन के बाहर से समान दिख सकते हैं।
लैब बंद करने के लिए:
cd lab
docker compose down
image/png घोषित किया गया है।matload को डेटा भेजता है; लक्ष्य-फ़ाइल बाइट्स छवि पिक्सेल बन जाते हैं और उत्पन्न PNG में लौट आते हैं।हाइब्रिड फ़ाइल एक साथ दो पार्सर्स को संतुष्ट करती है: इसका टेक्स्ट MATLAB 5.0 से शुरू होता है, जबकि ऑफ़सेट 124 पर वर्जन शब्द HDF5-समर्थित MATLAB 7.3 पथ का चयन करता है। Rails का फिक्स उन libvips ऑपरेशनों को ब्लॉक करता है जो अविश्वसनीय के रूप में चिह्नित हैं, इससे पहले कि कोई हमलावर-नियंत्रित फ़ाइल matload तक पहुँच सके।
rce पहले /proc/self/environ से SECRET_KEY_BASE पढ़ता है, जब तक कि --skb प्रदान न किया गया हो। यह Active Storage वेरिफायर कुंजी प्राप्त करता है और एक instance_eval ऑपरेशन वाले JSON वेरिएशन पर हस्ताक्षर करता है। प्रभावित vips पथ पर, ऑपरेशन Vips::Image.public_send तक पहुँचता है। PoC इसे अंतर्निहित प्रतिनिधित्व रूट के माध्यम से भेजता है, आपूर्ति किए गए कमांड को /bin/sh के माध्यम से चलाता है, और दोनों आउटपुट स्ट्रीम कैप्चर करता है।
यह दूसरा चरण हस्ताक्षरित गुप्त को पुनर्प्राप्त करने और Ethiack के CVE-2025-24293 के विश्लेषण में वर्णित भेद्य vips ट्रांसफ़ॉर्मेशन व्यवहार तक पहुँचने पर सशर्त है। CVE-2026-66066 पैच फ़ाइल-रीड प्रवेश बिंदु को बंद करता है; यह पहले लीक हुए हस्ताक्षरित गुप्तों के लिए सामान्य सुधार नहीं है। संदिग्ध जोखिम के बाद गुप्तों को घुमाएँ, जैसा कि Rails एडवाइज़री अनुशंसा करती है।
कमांड आउटपुट एक रैंडम /tmp/.kr2s_* फ़ाइल में लिखा जाता है, उसी फ़ाइल-रीड प्रिमिटिव के माध्यम से पुनर्प्राप्त किया जाता है, और फिर दूसरे हस्ताक्षरित पेलोड से हटा दिया जाता है।
रीड अनुरोधित निश्चित-आकार क्षेत्र लौटाता है। यदि स्रोत छोटा है, तो उसके उपसर्ग के बाद शून्य बाइट्स आते हैं। बाद के क्षेत्रों के लिए --offset का उपयोग करें।
डिफ़ॉल्ट लैब वेरिएशन केवल PNG में परिवर्तित होता है, इसलिए पुनर्प्राप्ति बाइट-सटीक होती है। वास्तविक अनुप्रयोग वेरिएंटों का आकार बदल सकते हैं। हार्वेस्टेड-कुंजी मोड क्षैतिज रीसैम्पलिंग से बचने के लिए एक-पिक्सेल कॉलम का उपयोग करता है, लेकिन कम ऊँचाई वाला वेरिएशन फिर भी ज्यामिति बदल सकता है। ऐसे मामले में क्लाइंट स्पष्ट रूप से विफल हो जाता है; --size घटाएँ या एक गैर-आकार-बदलने वाला प्रतिनिधित्व हार्वेस्ट करें।
हर कमांड इंट्रूसिव है: यह स्थायी Active Storage ब्लॉब बनाता है और संसाधित वेरिएंट बना सकता है। rce अतिरिक्त रूप से आपूर्ति किए गए कमांड को निष्पादित करता है।
मैट्रिक्स स्क्रिप्ट प्रत्येक रिलीज़ को बनाती है, भेद्य वर्जनों पर वास्तविक रीड और RCE जाँच चलाती है, यह सुनिश्चित करती है कि समाधान किए गए वर्जनों पर रीड अवरुद्ध हैं, और किसी भी बेमेल पर गैर-शून्य लौटाती है:
./lab/matrix.sh
./lab/matrix.sh 8.1.3
./lab/matrix.sh 8.1.3.1:PATCHED
2026-07-31 को Ruby 3.4.10, image_processing 1.14.0, ruby-vips 2.3.0, और libvips 8.16.1 के साथ मान्य किया गया:
समाधान की गई पंक्तियाँ जानबूझकर पूर्व-आपूर्ति किए गए हस्ताक्षरित गुप्त के साथ RCE पेलोड नहीं चलाती हैं; मैट्रिक्स CVE की फ़ाइल-रीड सीमा का परीक्षण करता है।
research/craft.py लोडर शोध के लिए उम्मीदवार पेलोड पुनः उत्पन्न करता है और इसके लिए h5py और numpy की आवश्यकता होती है। इसे रिलीज़ PoC द्वारा आयात नहीं किया जाता है। lab/probe/probe.sh उन उम्मीदवारों को लैब इमेज के अंदर ruby-vips के साथ निरीक्षित करता है:
uv run --script research/craft.py all -o /tmp/kr2s-payloads
docker run --rm \
-v "$PWD/lab/probe:/probe:ro" \
-v /tmp/kr2s-payloads:/payloads:ro \
--entrypoint /probe/probe.sh kr2s-rails:8.1.3
निर्भरता-मुक्त यूनिट परीक्षण इस प्रकार चलाएँ:
python3 -m unittest discover -s tests -v
MAT/HDF5 पेलोड और निर्भरता-मुक्त क्लाइंट स्थानीय परीक्षण के माध्यम से विकसित किए गए थे। सार्वजनिक PoC सामने आने के बाद, इस रिलीज़ में Zer0SumGam3 के PoC द्वारा प्रलेखित वेरिएशन-कुंजी संग्रहण और अंतर्निहित Active Storage रूट्स को शामिल किया गया। यहाँ Python कार्यान्वयन मौलिक और केवल-मानक-पुस्तकालय है।
एक पहले के संशोधन ने प्रदर्शित किया कि RCE एक हस्ताक्षरित Marshal पेलोड के साथ भी संभव था, जो Puma::MiniSSL::Context और एक ActiveSupport प्रॉक्सी का उपयोग करता था, जो Behrad Taher के सार्वजनिक gadget शोध पर आधारित था। उस रूट ने लक्ष्य-पक्षीय हेल्पर बाइनरी से परहेज किया, लेकिन इसके लिए Marshal-सक्षम हस्ताक्षरित-ID सिंक के साथ-साथ लोडेड Puma और ActiveSupport gadget क्लासेस की आवश्यकता थी। Ethiack रिसर्च टीम द्वारा अपना KindaRails2Shell तकनीकी विवरण प्रकाशित करने के बाद इसे बदल दिया गया, जो सरल हस्ताक्षरित JSON वेरिएशन तकनीक का दस्तावेजीकरण करता है। यह एक स्टॉक रूट का उपयोग करता है और उन पूर्व-शर्तों को हटा देता है।
खोज श्रेय André Baptista (0xacb), Bruno Mendes (s3np41k1r1t0), Rafael Castilho और Ethiack रिसर्च टीम, और RyotaK (GMO Flatt Security) को जाता है। Abdelmounaim Moulahcene (bl0rph) ने समन्वित प्रकटीकरण से कुछ समय पहले स्वतंत्र रूप से अंतर्निहित प्रिमिटिव प्रकाशित किया। अनुरक्षकों की पूरी समयरेखा और श्रेय के लिए Rails फोरेंसिक रिपॉजिटरी देखें।
केवल उन प्रणालियों पर उपयोग करें जिनके आप स्वामी हैं या जिनके परीक्षण के लिए आप स्पष्ट रूप से अधिकृत हैं। लेखक दुरुपयोग के लिए कोई दायित्व स्वीकार नहीं करते हैं। इस शोध कलाकृति में समस्याओं की रिपोर्ट करने के लिए SECURITY.md देखें।
MIT License के अंतर्गत जारी किया गया।
| Rails | फ़ाइल रीड | RCE जाँच | परिणाम |
|---|
| 7.2.3.1 | READ-OK | RCE-OK | पास |
| 7.2.3.2 | अवरुद्ध | नहीं चला | पास |
| 8.0.5 | READ-OK | RCE-OK | पास |
| 8.0.5.1 | अवरुद्ध | नहीं चला | पास |
| 8.1.3 | READ-OK | RCE-OK | पास |
| 8.1.3.1 | अवरुद्ध | नहीं चला | पास |