Bypassing XSS Filters Using Data URIs

One of the web app testers on a team I work with shared a technique for bypassing XSS filters that I hadn’t used (although admittedly I don’t get much hands-on time with web apps anymore) – using data uniform resource identifiers (URIs). Data URIs are defined by RFC 2397 and can be used to embed file in an HTML document without referencing a file stored on the server.

The way this works is by allowing the data to be self-contained within the URI and if a valid MIME type is specified, the data will be rendered. If a MIME type is not specified, it will default to text/plain which would be okay for textualized data, however to embed binary data one would need to specify base64 in the string. The syntax is as follows:

<img src="data:[MIMEtype];base64,[DATA]">

So to embed this PNG

using the method shown, the string would be

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAA3CAAAAACNsI2aAAAACXBIWXMAAAB5AAAAeQBPsriEAAAB6ElEQVR42rVWO46EMAzNadAcY3vaOQMXoXcXKZehS8NpqNxamw8JxDYra1Zjhgge9jhx/By7bYvtl4Y8Qn+tEjty6WxuQ0KkfOM5wJEeEkT1bsigU+xGQV+QfZ2ned0LAkLnyQ4XV2XB/k+jXdTs8Mc1+UlvQehEt5Fit7hLFsUfqfOk3d1lJ9VO+qN1sFvJm+IScB7s3uo8ZVzC8RrsXjIuqp2n0d+sxFNbHxCw9cF34yn2L5jyJWndIprzRfqLpvw0+6PCh1fjgxpP5NL4VzlYEa6zOYDgzyvk0cMbykMek6THipSXAD5/BKh8H/3JGZTxPgM9Px9WDL0CkM1ORJie48nsWAXQ8kW1YxlknKfIWJs/EBXgoZ6Jf2KMNMYz4FgBJjTGkxR/H67vm/H8eP9ShlyRqfli24c0svy0zLNXgOkNtQJEle/P/MPOv8T3TGZIZIbO7sL7BMON74nkuQqUj4XvnMvwiNCBjO+yev2NVDtZLeX5rvD9lu0zauxW+a6dBvJ8H5Gyfzz3wIBkO57rYECyHeeWF+xW+YcT47Jkdzi4TpT+lPNdIv9Z34fxNOxf0PhO91yw5MuMen56AxLPOtG7W9T63SCQ2k9Uol1so3bVnrog2JTyU57n1bb37n3s5s8Of5RfsaTdSlfuyUAAAAA8dEVYdGNvbW1lbnQAIEltYWdlIGdlbmVyYXRlZCBieSBHTlUgR2hvc3RzY3JpcHQgKGRldmljZT1wbm1yYXcpCvqLFvMAAABKdEVYdHNpZ25hdHVyZQA4NWUxYWU0YTJmYmE3OGVlZDRmZDhmMGFjZjIzNzYwOWU4NGY1NDk2Y2RlMjBiNWQ3NmM5Y2JjMjk4YzRhZWJjJecJ2gAAAABJRU5ErkJggg==">

Taking advantage of this feature, an attacker can inject their XSS code into the page. In the case of a system that blocks specific strings like “script” or symbols like parentheses, this method can be used to disguise the payload and evade the protections. An example of this using the default “<script>alert(“XSS”);</script>” payload would be:

<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+Cg==">

HTML tags that are able to carry these payloads are

There are some limitations to this technique though. Most modern browsers support the use of data URIs, however Internet Explorer < 8 does not. IE8 now has support for URIs but only with CSS. Using CSS is not much more difficult than with HTML. Using the image provided above for example, a CSS version would be:

li { 
  background: 
    url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADcAAAA3CAAAAACNsI2aAAAACXBIWXMAAAB5[snip...]) 
    no-repeat 
    left center;
  padding: 5px 0 5px 25px;
}

Resources: