Lucene search
K

containerd Image Volume Insecure Handling Exploit

🗓️ 24 Mar 2022 00:00:00Reported by Felix WilhelmType 
zdt
 zdt
🔗 0day.today👁 401 Views

containerd insecure handling of image volume

Related
Code
ReporterTitlePublishedViews
Family
IBM Security Bulletins
Security Bulletin: Multiple Security Vulnerabilities may affect IBM Robotic Process Automation for Cloud Pak
25 Aug 202202:03
ibm
IBM Security Bulletins
Security Bulletin: IBM Cloud Kubernetes Service is affected by a containerd security vulnerability (CVE-2022-23648)
18 Mar 202218:48
ibm
IBM Security Bulletins
Security Bulletin: IBM Cloud Transformation Advisor is vulnerable to multiple vulnerabilities found in Java, Node.js and IBM WebSphere Application Server Liberty
13 Mar 202503:39
ibm
IBM Security Bulletins
Security Bulletin: Multiple vulnerabilities that affects IBM Db2 Data Management Console (CVE-2022-23648, CVE-2022-32149)
3 Jul 202509:32
ibm
IBM Security Bulletins
Security Bulletin: Multiple vulnerabilities affect IBM Db2® on Cloud Pak for Data, and Db2 Warehouse® on Cloud Pak for Data
19 Apr 202420:11
ibm
IBM Security Bulletins
Security Bulletin: QRadar Suite Software includes components with multiple known vulnerabilities
1 Mar 202419:27
ibm
IBM Security Bulletins
Security Bulletin: Multiple Vulnerabilities in IBM Concert Software.
18 Aug 202504:31
ibm
IBM Security Bulletins
Security Bulletin: IBM Edge Application Manager 4.5 addresses multiple security vulnerabilities
31 May 202305:42
ibm
IBM Security Bulletins
Security Bulletin: IBM MQ Operator and Queue manager container images are vulnerable to multiple vulnerabilities from containerd, gnupg2, runc and IBM WebSphere Application Server Liberty
20 Oct 202212:19
ibm
IBM Security Bulletins
Security Bulletin: Open Source Dependency Vulnerability
15 May 202318:50
ibm
Rows per page
containerd: Insecure handling of image volumes

containerd's cri plugin handles image volumes containing path traversals insecurely. This can be used to copy arbitrary host directories to a container-mounted path.

OCI images contain a JSON config file described in https://github.com/opencontainers/image-spec/blob/main/config.md. As part of this config,
an image can specify \u"Volumes\u" which describe \u2018where the process is likely to write data specific to a container instance' when the image is used to run a container.

When this configuration is converted into an OCI runtime config, containerd tries to follow the spec at https://github.com/opencontainers/image-spec/blob/main/conversion.md:

\u"Implementations SHOULD provide mounts for these locations such that application data is not written to the container's root filesystem. If a converter implements conversion for this field using mountpoints, it SHOULD set the destination of the mountpoint to the value specified in Config.Volumes. An implementation MAY seed the contents of the mount with data in the image at the same location\u" 

The seeding is implemented in (*criService).CreateContainer (cri/server/container_create.go)

var volumeMounts []*runtime.Mount
if !c.config.IgnoreImageDefinedVolumes {
  // Create container image volumes mounts.
  volumeMounts = c.volumeMounts(containerRootDir, config.GetMounts(),   
                 &image.ImageSpec.Config)
} else if len(image.ImageSpec.Config.Volumes) != 0 {
  ....
}


func (c *criService) volumeMounts(..) .. 
var mounts []*runtime.Mount
\u2026
for dst := range config.Volumes {
        \u2026
        volumeID := util.GenerateID()
        src := filepath.Join(containerRootDir, \"volumes\", volumeID)
        mounts = append(mounts, &runtime.Mount{
            ContainerPath: dst,
            HostPath:    src,
            SelinuxRelabel: true,
        })
    }
    return mounts
}


Image volume mounts are only supported if IgnoreImageDefinedVolumes is false. While the description mentions that this flag is \u"Useful for better resource isolation, security\u2026\u" the default is false and none of the major containerd users seems to overwrite this. 

So in the default config, c.VolumeMounts will be called to create new runtime.Mount entries for all Volumes listed in the image config. There is no validation of the listed paths and the .ContainerPath attribute is completely image/attacker controlled.

Later in the execution, the harmless HostPaths and the attacker controlled ContainerPaths are passed to the customopts.WithVolumes method. While the HostPath is cleaned, ContainerPath is passed through without changes:
    if len(volumeMounts) > 0 {
        mountMap := make(map[string]string)
        for _, v := range volumeMounts {
            mountMap[filepath.Clean(v.HostPath)] = v.ContainerPath
        }
        opts = append(opts, customopts.WithVolumes(mountMap))
    }


The WithVolumes function (pkg/cri/opts/container.go) now tries to copy all files that are under ContainerPath in the container rootfs to the temporary directory at HostPath that will be later mounted into the Container at the same location (This is the optional \u"seeding\u" step described in the spec):
for host, volume := range volumeMounts {
    // The volume may have been defined with a C: prefix, which we can't use here.
    volume = strings.TrimPrefix(volume, \"C:\")
    for _, mountPath := range mountPaths {
    src := filepath.Join(mountPath, volume)
    if _, err := os.Stat(src); err != nil {
        if os.IsNotExist(err) {
            // Skip copying directory if it does not exist.
            continue
        }
        
\u2026
    }
    
if err := copyExistingContents(src, host); err != nil {
        \u2026            }
 
volume is the fully attacker controlled ContainerPath, mountPath a host directory pointing to a part of the containers rootfs. By setting volume to a path like \u"/../../../../../../../../../etc\u", src will become \u"/etc\u" and the copyExistingContents function in the last line will recursively copy the /etc/directory to host. As the directory specified by host will later be mounted into the container, this gives the container full read access to arbitrary files and directories.
Suggested Fix:
mountMap[filepath.Clean(v.HostPath)] = filepath.Clean(v.ContainerPath)
should be sufficient to fix the issue. (But it might be reasonable to surface/log misbehaving images?)

Proof-of-Concept:
fwilhelm ~ % buildah inspect volumes-test | jq '.OCIv1.config.Volumes'
{
 \"/../../../../../../../../var/lib/kubelet/pki/\": {}
}
fwilhelm ~ % kubectl run shell --rm -i --tty --image europe-west3-docker.pkg.dev/[redacted]/test/volumes-test -- /bin/sh 
/ # mount | grep /var/lib/kubelet
/dev/root on /var/lib/kubelet/pki type ext4 (rw,relatime)
/ # ls -la /var/lib/kubelet/pki/
total 20
drwxrwxrwt  2 root   root     4096 Nov 12 15:54 .
drwxr-xr-x  3 root   root     4096 Nov 12 15:54 ..
-rw-r--r--  1 root   root     1135 Nov 4 08:59 kubelet-client.crt
-rw-------  1 root   root      227 Nov 4 08:59 kubelet-client.key
-rw-------  1 root   root       0 Nov 4 08:59 kubelet-client.lock
-rw-------  1 root   root     1496 Nov 4 08:59 kubelet-server-2021-11-04-08-59-06.pem
lrwxrwxrwx  1 root   root      59 Nov 4 08:59 kubelet-server-current.pem -> /var/lib/kubelet/pki/kubelet-server-2021-11-04-08-59-06.pem

Let me know if you need access to the POC image, I did not want to spam the full list with it. 

This bug is subject to a 90-day disclosure deadline. If a fix for this issue is made available to users before the end of the 90-day deadline, this bug report will become public 30 days after the fix was made available. Otherwise, this bug report will become public at the deadline. The scheduled deadline is 2022-02-21. For more details, see the Project Zero vulnerability disclosure policy: https://googleprojectzero.blogspot.com/p/vulnerability-disclosure-policy.html

Related CVE Numbers: CVE-2022-23648.

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation