ReleaseJob#unpack builds jobdir = File.join(@releasedir, 'jobs', name) and jobtgz = File.join(@releasedir, 'jobs', "#{name}.tgz") where name returns @jobmeta['name'], a value taken verbatim from the jobs: array of the attacker-supplied release.MF inside the uploaded tarball. These paths are then interpolated into a shell string: Bosh::Common::Exec.sh("tar -C #{jobdir} -xf #{jobtgz} 2>&1", :onerror => :return). Bosh::Common::Exec.sh executes via %x{#{command}} (bosh-common/lib/bosh/common/exec.rb:53), i.e. /bin/sh -c, so any shell metacharacters in name are interpreted. FileUtils.mkdirp(jobdir) on line 49 creates the literal directory (no shell) and succeeds even when the name contains $()/;, so execution reaches the sh call.
Affected versions: - BOSH Director: all versions prior to v282.1.12 (inclusive); fixed in v282.1.12 or later
When the director sends a long-running request (e.g. compilepackage), the agent's reply JSON is consumed by AgentClient. injectcompilelog (line 332-339) reads response['value']['result']['compilelogid'] and formatexception (line 318-325) reads exception['blobstoreid']; both pass the agent-supplied string unmodified to downloadanddeleteblob(blobid) (line 344-349), which calls @resourcemanager.getresource(blobid) and, in an ensure block, @resourcemanager.deleteresource(blobid). Api::ResourceManager forwards the id straight to blobstore.get(id) / blobstore.delete(id). When the director is configured with the local blobstore provider, Blobstore::LocalClient#objectfilepath(oid) is File.join(@blobstorepath, oid) (localclient.rb:54-56) with no normalisation, so oid = "../../jobs/director/config/director.yml" resolves outside the blobstore root.
Affected versions: BOSH Director: All versions prior to v282.1.12
AgentClient#handlemethod (lines 264-303) processes every NATS reply. It calls injectcompilelog (line 273) on every response, which reads response['value']['result']['compilelogid'] (line 332-338) and passes it to downloadanddeleteblob. Separately, any response containing 'exception' goes through formatexception (lines 308-325), which reads exception['blobstoreid'] and also calls downloadanddeleteblob. That helper (lines 344-349) calls ResourceManager#getresource(blobid) and, in an ensure block, ResourceManager#deleteresource(blobid). ResourceManager (resourcemanager.rb:62-70) calls blobstore.delete(id) on the single shared Director blobstore with no UUID-format check, no ownership check, and no namespace prefix.
Affected versions: BOSH Director: All versions prior to v282.1.12