anchore / stereoscope

go library for processing container images and simulating a squash filesystem
Apache License 2.0
78 stars 43 forks source link

Cycle during symlink resolution prevents syft/grype scans from enumerating vulnerabilities #206

Open mathrock opened 10 months ago

mathrock commented 10 months ago

What happened: We recently came across an image where a user had accidentally created a symlink loop within their container image. This resulted in the image failing both syft and grype scans.

This could be used by an attacker or developer who wants to hide vulnerabilities through malicious compliance. By generating a symlink loop, syft/grype will error and fail to output results. If scan errors are not closely monitored the image could avoid detection.

What you expected to happen: Malformed symlinks should be logged, but allow the rest of the syft or grype scans to complete.

How to reproduce it (as minimally and precisely as possible): Using old, known vulnerable image from webgoat/webgoat-8.0:latest grype shows a bunch of vulns:

% grype webgoat/webgoat-8.0:latest
 ✔ Vulnerability DB                [no update available]
 ✔ Pulled image
 ✔ Loaded image                                                                                                                                                             webgoat/webgoat-8.0:latest
 ✔ Parsed image                                                                                                                sha256:6664051b8808540cf920e5802e7eb025f9cb19346dcb0fc2be137a26979bb111
 ✔ Cataloged packages              [315 packages]
 ✔ Scanned for vulnerabilities     [581 vulnerability matches]
   ├── by severity: 73 critical, 185 high, 152 medium, 60 low, 111 negligible
   └── by status:   304 fixed, 277 not-fixed, 0 ignored

Build a downstream image and create a symlink loop in a cataloged binary, /usr/bin/xz for example:

echo "FROM webgoat/webgoat-8.0:latest
USER root
RUN yes | ln -sfi /usr/bin/xzcat /usr/bin/xz
USER webgoat" | docker build -t symlink-loop:latest .

Syft error:

% syft symlink-loop:latest
 ✔ Loaded image                                                                                                                                                                    symlink-loop:latest
 ✔ Parsed image                                                                                                                sha256:108309a3bb9c201ffe0f2c4fc1300f434485e5216d6edad8c76d6d2ec8d3e7de
 ✔ Cataloged packages              [315 packages]
[0003]  WARN unable to create any package-file relationships cataloger=dpkgdb-cataloger error=unable to find path for path="/usr/bin/xz": cycle during symlink resolution package=xz-utils
[0003]  WARN unable to process mimetypes=[application/x-executable application/x-mach-binary application/x-elf application/x-sharedlib application/vnd.microsoft.portable-executable]: unable to get ref
[0005]  WARN error while cataloging cataloger=graalvm-native-image-cataloger
1 error occurred:
        * failed to find binaries by mime types: unable to get ref for path="/usr/bin/xz": cycle during symlink resolution

Grype error:

% grype symlink-loop:latest
 ✔ Vulnerability DB                [no update available]
 ✔ Loaded image                                                                                                                                                                    symlink-loop:latest
 ✔ Parsed image                                                                                                                sha256:108309a3bb9c201ffe0f2c4fc1300f434485e5216d6edad8c76d6d2ec8d3e7de
 ✔ Cataloged packages              [315 packages]
[0003]  WARN unable to create any package-file relationships cataloger=dpkgdb-cataloger error=unable to find path for path="/usr/bin/xz": cycle during symlink resolution package=xz-utils
[0003]  WARN unable to process mimetypes=[application/vnd.microsoft.portable-executable application/x-executable application/x-mach-binary application/x-elf application/x-sharedlib]: unable to get ref
[0004]  WARN error while cataloging cataloger=graalvm-native-image-cataloger
1 error occurred:
        * failed to catalog: 1 error occurred:
        * failed to find binaries by mime types: unable to get ref for path="/usr/bin/xz": cycle during symlink resolution

Anything else we need to know?:

This issue was validated on latest syft/grype versions:

% syft version
Application: syft
Version:    0.94.0
BuildDate:  2023-10-20T17:21:07Z
GitCommit:  8f6bdde6662aa8050a71eadbdb7bd5a3b079a56d
GitDescription: v0.94.0
Platform:   linux/amd64
GoVersion:  go1.21.3
Compiler:   gc

% grype version
Application:         grype
Version:             0.72.0
BuildDate:           2023-10-20T18:17:05Z
GitCommit:           04df28051b7694a5e4a28fc5b2ea2068f24ef213
GitDescription:      v0.72.0
Platform:            linux/amd64
GoVersion:           go1.21.3
Compiler:            gc
Syft Version:        v0.94.0
Supported DB Schema: 5

Environment:

REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 7" REDHAT_BUGZILLA_PRODUCT_VERSION=7.9 REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux" REDHAT_SUPPORT_PRODUCT_VERSION="7.9"

wagoodman commented 1 month ago

If I'm understanding correctly, if there is an infinite symlink within a dir, and it's half way through the entires in a directory, then we're not reading the remaining entires in the directory. There may be more cases here I haven't considered. This is the part of the code we should scrutinize further https://github.com/anchore/stereoscope/blob/50ce3be7aa1fb8829234ae648215e7907196bfa5/pkg/filetree/depth_first_path_walker.go#L90-L93

wagoodman commented 1 month ago

@kzantow you pointed out this might play into the known-unknowns work in syft https://github.com/anchore/syft/issues/518 -- specifically noting that there could be symlink loops that is occluding catalogable part of the filetree.