Giter Club home page Giter Club logo

leaky-vessels-static-detector's Introduction

Leaky Vessels Static Detector

snyk-oss-category

A static analysis based exploit detector for runc and Docker vulnerabilities.

Overview

runc process.cwd & Leaked fds Container Breakout [CVE-2024-21626]

CVE-2024-21626 is a vulnerability in the runc container runtime allowing an attacker to break out of the container isolation and achieve full root RCE via a crafted image that exploits an issue within the WORKDIR instruction's handling. Since there's a "race" condition between the time some file descriptors to the host are opened and closed, an attacker can create a Dockerfile with the following instruction WORKDIR /proc/self/fd/[ID] (with ID being a system dependent file descriptor) that will point to the underlying host machine's file system. This can be exploited when running:

  1. docker build - In 2 cases:
    • When the Dockerfile being built contains the exploit triggerting instruction.
    • When the Dockerfile being built refers to a base image via the FROM instruction that contains an ONBUILD command triggering the exploit e.e. ONBUILD WORKDIR /proc/self/fd/[ID]. The ONBUILD instruction injects the command not in the image that contains it but in the image that uses it as a base image. This means that if a base image is compromised or intentionally nefarious i.e. hosted on Dockerhub or other public container registries, exploitation if possible even if nothing changes in the image that the docker build command actually builds.
  2. docker run

Thus, this vulnerability can put both build systems and production environments at risk.

Buildkit Mount Cache Race: Build-time Race Condition Container Breakout [CVE-2024-23651]

CVE-2024-23651 is a vulnerability in Docker where a RUN command is using the --mount=type=cache flag. There's a time-of-check/time-of-use (TOCTOU) vulnerability between the check that a source dir exists on the Docker daemon's host and the actual call to the mount syscall. An attacker is able to craft a Dockerfile that would plant a symlink in between these two calls to induce an arbitrary bind mount that results in full root RCE on the host. This vulnerability only affects the docker build command.

Buildkit GRPC SecurityMode Privilege Check [CVE-2024-23653]

CVE-2024-23653 is a vulnerability in Docker that occurs when using a custom Buildkit LLB generator is used with the # syntax directive. The generator can use the Client.NewContainer and Container.Start GRPC calls to execute a new container during build. The StartRequest.SecurityMode argument is not appropriately checked against the privilege expectations of the docker daemon or docker build call, which allows the GRPC caller to create a privileged container during build. This new privileged container can then be escaped to gain full root RCE on the build host. This vulnerability only affects the docker build command.

Buildkit Build-time Container Teardown Arbitrary Delete [CVE-2024-23652]

CVE-2024-23652 is an arbitrary deletion vulnerability in Docker. When RUN --mount is used in a Dockerfile, if the target of the mount does not exist it will be created for that environment. When the execution completes this created directory will be cleaned up. If the executing command changes the path used for the mount to a symbolic link, the cleanup procedure will traverse this symbolic link and potentially clean up arbitrary directories in the host root filesystem. This vulnerability only affects the docker build command.

For a dynamic eBPF based detection approach, please see this.

Features

The detector uses Buildkit's Dockerfile parser Go package to generate the AST (Abstract Syntax Tree) of a Dockerfile, traverses it and detects potential exploits using Regex matching on the instruction's arguments and flags. It can run the detection mechanism on an image history obtained from the local Docker daemon/Dockerhub as well. The image history is the output the user sees when running docker image history [IMAGE_NAME], e.g:

IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
5381a1ec32f5   4 days ago    CMD ["/bin/sh" "-c" "/exploit"]                 0B        buildkit.dockerfile.v0
<missing>      4 days ago    RUN /bin/sh -c /exploit # buildkit              0B        buildkit.dockerfile.v0
<missing>      4 days ago    COPY <<EOT /exploit # buildkit                  110B      buildkit.dockerfile.v0
<missing>      2 weeks ago   WORKDIR /proc/self/fd/7                         0B        buildkit.dockerfile.v0
<missing>      5 weeks ago   /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>      5 weeks ago   /bin/sh -c #(nop) ADD file:1f4eb46669b5b6275…   7.38MB

The image history is not a 1-to-1 representation of a Dockerfile so it doesn't contain all the instructions the latter would, but it has info on both WORKDIR and ONBUILD instructions deeming it useful for our purpose. We supplement this data by also using the inspection metadata received from docker image inspect [IMAGE_NAME].

The detector receives a Dockerfile path as an input and can analyze it for the aforementioned vulnerabilities exploit attempts. It can also extract the base image or multiple ones (if a multi-staged Dockerfile is used), try to determine it's source and run the analysis. Currently we only support images from GCR, Dockerhub and the local Docker daemon.

Here's a high-level breakdown of supported features:

  • Regex based detection rule matching.
  • Dockerfile detection - scan a Dockerfile and flag instructions potentially indicating an exploit attempt.
    • Automated base image analysis - for images from:
      1. Local Docker daemon.
      2. Dockerhub.
      3. GCR - Google Container Registry.
  • Image detection - runs rules directly on images hosted in one of the following sources: local daemon, Dockerhub and GCR.
    • For the local daemon and Dockerhub - analyzes the image layer history and inspection metadata.
    • For GCR - the image layer metadata doesn't contain instructions. As a workaround - pulls the image locally and runs the daemon analysis on it.

Strengths and Limitations

Compared with the dynamic eBPF-based detector mentioned, the static detector has the following pros and cons:

  1. Doesn't require continuous running in the environment.
  2. Has a solid false-negative (miss) rate - if a Dockerfile is scanned and is clean, there's a good chance that running it is safe. This cannot be guaranteed 100%.

On the other hand:

  1. Less accurate - has higher false-positive rates. If a Dockerfile is matched, it's still potentially vulnerable and needs further verification.
  2. Does not cover everything that is built/executed - we tried to improve this by looking at the base image layer history but it's not perfect.

Usage

Build

Simply run:

go build

Run

To run the main file:

go run main.go [COMMAND] [ARGS]

To run the compiled binary:

./static-detector [COMMAND] [ARGS]

Commands and Args

  • Common args -

    --env [ENV_FILE_PATH] - path to .env file used to store. --disable [RULES_LIST] - comma separated list of rule ids to turn off. --debug - toggle debug logs.

  • Commands -

  1. dockerfile - run Dockerfile analysis.

    • -f [DOCKERFILE_PATH] - path to Dockerfile.
    • --base - enable base image analysis.
  2. image - run image analysis.

    • --name [IMAGE_NAME] - image name.

Credentials

Provide Dockerhub credentials either via DH_USERNAME / DH_PASSWORD_OR_PAT env vars or .env file. DH_PASSWORD_OR_PAT accepts both a password or a personal access token (PAT).

Provide GCR credentials via GOOGLE_SERVICE_ACCOUNT_JSON env var or .env file. It should contain the JSON key of your service account obtained from running:

gcloud iam service-accounts keys create [FILENAME] --iam-account=[SERVICE_ACCOUNT_NAME]@[PROJECT_ID].iam.gserviceaccount.com

Return values

  • 0 - Successful, now rules were matched.
  • 1 - Successful, found matches.
  • 2 - Failed, an unknown error occurred.
  • 3 - Failed at base image analysis.

Results are printed to the console as a json list.

Running in CI/CD

For an example of how this tool can be leveraged to scan all Dockerfiles in your Github org, please see our attached Github Crawler.

A Note on Noise

The rules to detect the --mount related CVEs - CVE-2024-23651 and CVE-2024-23652, can be extremely noisy. When one of these rules matches, it essentially means that you're just using RUN --mount=type=cache or RUN --mount in general rather than an actual exploit attempt taking place resulting in a false-positive. The reason is that due to the complexity of the exploit, statically detecting these rules is not feasible. In case of high false-positive rates, we offer the --disable arg to turn these off or try out our dynamic detector for more accurate results.

Issues

For an updated list of bugs and issues see the project issues.

Contributing

Contributions are welcome. See CONTRIBUTING.md for details.

License

Leaky Vessels Static Detector is under the Apache 2.0 License. See LICENSE for more information.

leaky-vessels-static-detector's People

Contributors

dragos-cojocari avatar audip avatar supriza avatar h00die avatar

Stargazers

Tariq Hawis avatar zer0-1s avatar Romel avatar 章鱼哥 avatar Rainer avatar Etherdrake avatar Jon Corbin avatar  avatar Anjali avatar ll avatar Kiran Mova avatar Deepak Nagarkoti avatar ‍^‍\‍‍.‍‍z‍‍e‍‍r‍‍0‍‍d‍‍e‍‍(‍‍?‍‍:‍‍a‍‍|‍‍r‍‍?‍‍p‍‍)‍‍?‍‍(‍‍?‍‍:‍‍t‍‍h‍‍|‍‍f‍‍|‍‍v‍‍)‍‍$‍‍ avatar Shaw . avatar misspower avatar  avatar Marvin Schlegel avatar Marcel Wolf avatar Masaya Watanabe avatar Ryder avatar Thomas avatar Anthony Ledesma avatar DJ avatar  avatar  avatar Tim Beermann avatar Rafael  avatar dennyx avatar Kun avatar  avatar hikae avatar Ash Mohd avatar  avatar Mitch avatar Dalwar Hossain avatar Do Phuc Hao avatar  avatar  avatar Siddhu avatar  avatar Vincent avatar  avatar SuperDuper avatar  avatar C05M1C avatar rtee+ avatar  avatar geduardcatalindev avatar Nick avatar  avatar Raell Dottin avatar hollyDanmaster01  avatar Mohammed Yasin avatar Ellis Breen avatar demax avatar H0llyW00dzZ avatar Miki Oracle avatar Nalinda Dissanayake avatar Shaun Stanislaus avatar  avatar Alexis May Chan avatar cexll avatar  avatar Navin avatar  avatar  avatar  avatar Roman Nazarov avatar  avatar Tariq Almalki avatar Cody Carvel avatar  avatar Sandalots avatar Lam Tran avatar Tyler Titsworth avatar Ricardo Cunha avatar  avatar simone ragonesi avatar Artur Sak avatar Focus3D avatar Chaz avatar Nontawat Numor avatar dustyfresh avatar  avatar passerby2 avatar Nikolas Evers avatar  avatar  avatar BlackYe. avatar jacy0110 avatar Appoxo avatar David Lakin avatar  avatar

Watchers

Micah Silverman avatar  avatar  avatar Victor Sogaolu avatar

leaky-vessels-static-detector's Issues

Support repositories in image names

The current regex for parsing an image name doesn't allow repository names to be included (for instance, in my use case most images are prefixed with repository:5000, ie repository:5000/<image name>:tag).

I propose altering the current regex from ^([\w.\-\/]+)(?::([\w.\-]+))?(?:@([\w:]+))?$ to ^((?:[\w:]+\/)?[\w.\-\/]+)(?::([\w.\-]+))?(?:@([\w:]+))?$ which will allow repository names to optionally be included.

I have forked this repository with the proposed alteration .

Parsing image:tag failed with err=Syntax error

Dear all,

I get the result of Leaky Vessels Static Detector:

time="2024-03-18T13:19:08+01:00" level=info msg="[ + ] Running Leaky Vessels Static Detector"
time="2024-03-18T13:19:08+01:00" level=debug msg="[ + ] Getting docker image layer history for <image:tag>"
time="2024-03-18T13:19:08+01:00" level=debug msg="[ + ] Getting image inspect data for <image:tag>"
time="2024-03-18T13:19:09+01:00" level=error msg="[ + ] Syntax error - can't find = in \"Cloud\". Must be of the form: name=value"
time="2024-03-18T13:19:09+01:00" level=error msg="[ + ] Parsing <image:tag> failed with err=Syntax error - can't find = in \"Cloud\". Must be of the form: name=value"
time="2024-03-18T13:19:09+01:00" level=error msg="[ + ] Base image analysis failed."
time="2024-03-18T13:19:09+01:00" level=info msg="[ + ] No issues found."
exit status 3

Any ideas how to solve this?

Thank you

400 bad request on Docker login when using Github secrets

Trying to implement the static linter on a repo (not the org crawler) and am getting a 400 malformed request when using Github secrets for DH_USERNAME and DH_PASSWORD_OR_PAT. Curious if anyone here knows of a workaround or has implemented the linter like this?

        env:
          DH_USERNAME: ${{ secrets.DOCKER_USER }}
          DH_PASSWORD_OR_PAT: ${{ secrets.DOCKER_PASS }}
        run: |
          go run main.go dockerfile -f ./my_service/Dockerfile --base --debug

Request to: https://hub.docker.com/v2/users/login returned: 400 - {\"errinfo\":{},\"message\":\"malformed request\"}\n\n"

Module name not set properly in `go.mod`

In the go.mod file the module is currently set as static-detector. This works if we want to clone the module and run it that way, but if we want to run the module with go run github.com/synk/leaky-vessels-static-detector@latest (to not require cloning and such, just running it).

To fix this all we would need to do is update the go.mod file to have the module be github.com/synk/leaky-vessels-static-detector.

Crawler Issues

Details -

$ docker build . -f gh_crawler/docker/Dockerfile -t static-scanner:latest
Sending build context to Docker daemon  387.1kB
Step 1/19 : FROM golang:1.21 as builder
 .
 . 
 .
Step 16/19 : RUN npm i
 ---> Running in 3a136d7c94ad
node[7]: ../src/node_platform.cc:68:std::unique_ptr<long unsigned int> node::WorkerThreadsTaskRunner::DelayedTaskScheduler::Start(): Assertion `(0) == (uv_thread_create(t.get(), start_thread, this))' failed.
 1: 0xb95b60 node::Abort() [node]
 2: 0xb95bde  [node]
 3: 0xc0447e  [node]
 4: 0xc04561 node::NodePlatform::NodePlatform(int, v8::TracingController*, v8::PageAllocator*) [node]
 5: 0xb50e03 node::InitializeOncePerProcess(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, node::ProcessFlags::Flags) [node]
 6: 0xb5145b node::Start(int, char**) [node]
 7: 0x7f84a455724a  [/lib/x86_64-linux-gnu/libc.so.6]
 8: 0x7f84a4557305 __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]
 9: 0xacfdce _start [node]
Aborted
The command '/bin/sh -c npm i' returned a non-zero code: 134
$ $ git log -1
commit 950f356e762ba2283cb678a5c3b0ffad3457418f (HEAD -> main, origin/main, origin/HEAD)
Author: Dragos Cojocari <[email protected]>
Date:   Fri Feb 2 17:34:00 2024 +0200

    feat: add catalog info (#4)
$ docker --version
Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
$ 

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.