5

I'm a little confused about XSS vulnerabilities when serving img.src and background url. From what I understand, the only way to execute javascript in this case, is to use javascript protocol. Let's consider this example:

if (location.hash.indexOf('javascript:') !== 0) {
    img.style.backgroundImage='url("'+location.hash+'")';
 }
 img.src='some/local/path/'+location.hash;

Is there an XSS vulnerability in this code?

Maciej Krawczyk
  • 211
  • 1
  • 2
  • 9
  • I can't think of any situation where `location.hash.indexOf('ANY_STRING')` would return `0` since `location.hash` contains `#`, so any string in the URL hash value would be at least on index `1`. The only exception is of course `location.hash.indexOf('')`. So before discussing any XSS vuln, the check in your code already fails. – Adi Jun 01 '16 at 21:10
  • 1
    Not an XSS issue, but I could craft a link to your site that sets the background image to anything I like, including something beginning with `http://`. That could be abused to scare away customers - they click on a link to your site, and are greeted with something offensive. – Anders Jun 01 '16 at 21:24
  • I thought of location.hash just as an example for any string. I forgot it starts with #. The link serves as a wallpaper image, only the user who is using the app can set and access it. – Maciej Krawczyk Jun 02 '16 at 04:00
  • Please edit your question so that it matches what you mean - it could help others. Don't forget to use @username if you want to notify people of your reply. – SilverlightFox Jun 02 '16 at 14:19

2 Answers2

8

No, in modern browsers no XSS is possible via the style or src attribute of an <img> tag.

So neither of these would execute the JS code in any up-to-date browser:

<img src="javascript:alert(1)">
<img src="x.jpg" style=background-image:url('javascript:alert(2)')">

Support for Javascript in CSS attributes has long been abandoned. You can find some older references about it here.

Analysis of your example code

location.hash always starts with a # symbol. Since this character is illegal in JS and not a valid beginnig of a new URL, no XSS would be possible in the first place. (For instance, eval(location.hash) always produces a syntax error.)

Let's assume, you ignore the # and location.hash could really contain any string you want.

Then this security check is flawed:

(location.hash.indexOf('javascript:') !== 0)

An attacker could still construct a URL starting with JaVaScRiPt:. Also, it's risky to assume that no implementation would ever allow leading spaces or control characters (e.g. \t\x00javascript:). And what about URL-encoding? A payload starting with javascript%3a would pass your filter. Also, do you want to allow the data: protocol? If you like to restrict the URL to absolute locations, you could whitelist the beginnings http:// and https:// instead of blacklisting javascript:.

This is fine:

img.src='some/local/path/'+location.hash;

Even if the src attribute was susceptible to script code, your prefix some/local/path/ ensures that it cannot be turned into a JS URL. However, an attacker could specify any relative path to an image file on the same server, which you might find undesirable.

NB: This is about constructing malicious javascript: URLs. If you want to use user-controlled values like location.hash for HTML output or a different context, you have to properly sanitize the string.

Arminius
  • 43,922
  • 13
  • 140
  • 136
  • Thank you. I'm actually already using http:// and https:// as a whitelist for every url, but I was interested if url starting with javascript: is everything there is. Now I see how ease it is to bypass blacklist filter. I viewed the html5 security cheatsheet and there seem to be other issues. https://html5sec.org/#92 But that is only for IE6 and also something like characters ignored in URI scheme https://html5sec.org/#101 but I'm not sure which characters are these. Anyway, protocol whitelist should protect me against it. – Maciej Krawczyk Jun 02 '16 at 04:08
3

Yes, it is a problem, maybe even a big problem, but "XSS" probably isn't the right term.

What could possibly go wrong?

  1. remote code execution using svg, especially older browsers
  2. off-site images leak your user's IP address (aka lat/lon), userAgent, and net performance
  3. malicious images themselves been vectors, lots of 0days in the past
  4. A special or even just big-and-crappy GIF can bring the page/CPU to grind
  5. big images can be used to inject lots of known data to help break encryption
  6. your site could "advertise" something you don't want to be associated with
  7. an off-site image can confirm a specific user got a specific link and visited

While none of those are traditional XSS, they are bummers.

I would recommend some sort of choice from a white-list of on-site images if you want customization capabilities.

dandavis
  • 2,658
  • 10
  • 16