CVE-2024-37164 (YAML, published 2024-06-13T15:15Z)
Description: value: Computer Vision Annotation Tool (CVAT) is an interactive video and image annotation tool for computer vision. CVAT allows users to supply custom endpoint URLs for cloud storages based on Amazon S3 and Azure Blob Storage. Starting in version 2.1.0 and prior to version 2.14.3, an attacker with a CVAT account can exploit this feature by specifying URLs whose host part is an intranet IP address or an internal domain name. By doing this, the attacker may be able to probe the network that the CVAT backend runs in for HTTP(S) servers. In addition, if there is a web server on this network that is sufficiently API-compatible with an Amazon S3 or Azure Blob Storage endpoint, and either allows anonymous access, or allows authentication with credentials that are known by the attacker, then the attacker may be able to create a cloud storage linked to this server. They may then be able to list files on the server; extract files from the server, if these files are of a type that CVAT supports reading from cloud storage (media data (such as images/videos/archives), importable annotations or datasets, task/project backups); and/or overwrite files on this server with exported annotations/datasets/backups. The exact capabilities of the attacker will depend on how the internal server is configured. Users should upgrade to CVAT 2.14.3 to receive a patch. In this release, the existing SSRF mitigation measures are applied to requests to cloud providers, with access to intranet IP addresses prohibited by default. Some workarounds are also available. One may use network security solutions such as virtual networks or firewalls to prohibit network access from the CVAT backend to unrelated servers on your internal network and/or require authentication for access to internal servers.
Severity: nan (CVSS v3 base score: )
Weakness: NVD-CWE-noinfo \u2014 Insufficient Information
There is insufficient information about the issue to classify it; details are unkown or unspecified.
Repository: https://github.com/cvat-ai/cvat
Files changed:
changelog.d/20240610_143947_roman_ssrf_s3.md
cvat/apps/engine/cloud_provider.py
supervisord/worker.export.conf
tests/allow_minio.sh
tests/docker-compose.minio.yml
Commit message: Merge pull request from GHSA-q684-4jjh-83g6

S3 storages support user-specified endpoint URLs, and Azure storages support
user-specified connection strings (which can contain endpoint URLs), so they
are susceptible to SSRF. Make S3 and Azure requests go through smokescreen
to fix this.

AFAIK, there is no way to configure a custom URL for Google Cloud storages,
so those aren't vulnerable.

Co-authored-by: Nikita Manovich <nikita@cvat.ai>

Vulnerable code:
        self._s3 = session.resource("s3", endpoint_url=endpoint_url)
            self._blob_service_client = BlobServiceClient.from_connection_string(connection_string)
            self._blob_service_client = BlobServiceClient(account_url=self.account_url, credential=sas_token)
            self._blob_service_client = BlobServiceClient(account_url=self.account_url)

Fixed code:
### Security

- Fixed an SSRF vulnerability with custom cloud storage endpoints
  (<https://github.com/cvat-ai/cvat/security/advisories/GHSA-q684-4jjh-83g6>)
from botocore.client import Config
from cvat.utils.http import PROXIES_FOR_UNTRUSTED_URLS
        self._s3 = session.resource("s3", endpoint_url=endpoint_url,
            config=Config(proxies=PROXIES_FOR_UNTRUSTED_URLS or {}),
        )
            self._blob_service_client = BlobServiceClient.from_connection_string(
                connection_string, proxies=PROXIES_FOR_UNTRUSTED_URLS)
            self._blob_service_client = BlobServiceClient(
                account_url=self.account_url, credential=sas_token, proxies=PROXIES_FOR_UNTRUSTED_URLS)
            self._blob_service_client = BlobServiceClient(
                account_url=self.account_url, proxies=PROXIES_FOR_UNTRUSTED_URLS)

[program:smokescreen]
command=smokescreen --listen-ip=127.0.0.1 %(ENV_SMOKESCREEN_OPTS)s
# Same as allow_webhooks_receiver.sh, but for minio.
minio_ip_addr="$(getent hosts minio | head -1 | awk '{ print $1 }')"
export SMOKESCREEN_OPTS="$SMOKESCREEN_OPTS --allow-address=\"$minio_ip_addr\""
x-allow-minio: &allow-minio
  depends_on:
    - minio
  volumes:
    - ./tests/allow_minio.sh:/etc/cvat/init.d/allow_minio.sh:ro

  cvat_server: *allow-minio
  cvat_worker_export: *allow-minio
  cvat_worker_import: *allow-minio