CWE-82 is a web application that does not neutralize scripting elements within attributes of HTML image tags, such as the src attribute.
It shows up wherever users can post an image: guestbooks, forums, comment systems and markup converters that turn something like a BBcode image tag into HTML.
How it happens
Attackers embed XSS exploits into values for image attributes such as src. The result is streamed to the page and executed in a victim's browser. When the page loads, the exploit runs automatically, with no click needed.
The observed examples center on the javascript scheme in image URLs. CVE-2006-3211 is stored XSS in a guestbook application using a javascript URI in a BBcode image tag. CVE-2002-1649, CVE-2002-1803 and CVE-2002-1804 are described as the javascript URI scheme in an image tag. See CVE-2002-1803, CVE-2002-1804, CVE-2006-3211 and CVE-2002-1649.
Here is the pattern in Python:
# Vulnerable: user supplies the URL unchecked and unescaped
html = '<img src="' + url + '">'
A quote in the value can break out of the attribute, and a script scheme in the value is accepted as is.
What an attacker gains
MITRE lists confidentiality, integrity and availability: reading application data and executing unauthorized code or commands in the victim's session.
How to find it
The record lists no detection methods. Test every feature that accepts an image address, including markup converters, with unusual values, and read the HTML that comes out.
How to fix it
MITRE's listed mitigation is about encoding: use and specify an output encoding the downstream component can handle, such as UTF-8, because browsers guess when none is set, and inconsistent encodings can let attackers slip characters past protections.
Plain steps that follow from the description:
- Escape the value for the attribute context.
- Accept only the URL schemes you expect for images.
- Declare the response encoding.
from urllib.parse import urlparse
from markupsafe import escape
u = urlparse(url)
if u.scheme not in ("http", "https"):
raise ValueError("bad image URL")
html = '<img src="' + str(escape(url)) + '">'
Quick check
Why does an image tag need XSS protection?
Its src attribute can carry a script scheme or break out of the attribute, and the exploit runs when the page loads.