56

Is it safe to display images from arbitrary domains? I.e. let's say I have an image on my page:

<img src="http://badguy.com/image.gif" />

What if image.gif will return some js attack vector, but not the image? Is there any known vectors?

I've tried to serve javascript:alert(1) or the same, but base64 encoded. But without any luck. Any ideas?

Paul Podlipensky
  • 2,837
  • 4
  • 21
  • 25
  • 18
    It's not a *security* vulnerability, but the bad guy can change the content of the image at any time. I saw one case where a website owner responded to hotlinking by replacing the expected image with bestiality porn. – Ladadadada May 25 '13 at 08:19

5 Answers5

55

There used to be a "vulnerability" where the image could send a HTTP 401 Unauthenticated response, which would trigger a login screen for the user. If you set this as forum avatar, it would spawn a login popup for anyone visiting a page where your avatar appears. Lots of people will then attempt to log in with some username and password combination, probably the one for their forum account.

A friend of mine found this a few years ago, but nowadays it doesn't seem to work anymore. At least I couldn't easily reproduce it a few months back. Edit: I was wrong, this attack is still possible! /edit

As for XSS attacks this way, you're safe. The browser will, or should, always interpret this as an image no matter what it contains or what headers it sends. You can customize the image based on the request (serving a small image to the forum software prechecking the image so that it doesn't downscale it, then large for everyone else). Or feed the browser lots of gif-data until memory runs out or something. But there are no real big vulnerabilities here that allow Remote Code Execution as far as I know.

What you are only moderately safe for are CSRF-attacks. The image can issue a HTTP 302 Moved Temporarily response and link to a new location. For example it could link to, I don't remember the specific URL, something like https://accounts.google.com/logout and log you out of google (this worked a few months ago). Or, slightly more maliciously: http://example.com/guestbook.php?action=post&message=spam-url.example.com.

Only GET requests can be done this way as far as I know. Or if the image was originally being loaded as POST request, I suppose it could also redirect the POST, but not change the POST-data. So that's pretty safe.

Last but not least, if the attacker controls URLs of for example forum avatars (such as in SMF forums), it's possible to obtain information from visitors such as their IP address. I wrote a tool a while ago that used the action=who page of SMF to link IP addresses to usernames. When I started displaying that to users (show "Hello $username with IP: $IP" in the image) all hell broke loose. "How could you possibly know that?!" They were mostly early- to mid-teen techies so they knew what an IP address was, but didn't know that I couldn't hack them with it. It is however considered to be personally identifiable information, at least in the Netherlands, so the admins weren't quite happy about this practice. If you don't display it though, nobody will ever know.

Note: If this post seems hastily written, it is. I'm barely awake too. Perhaps I'll clean it up tomorrow if it's too much storytelling and not naming enough concrete facts and vulnerabilities. Hope this helped anyway!

Luc
  • 31,973
  • 8
  • 71
  • 135
  • 5
    +1 for the 401 attack. And this may be relevant: https://jira.atlassian.com/browse/CONF-28932?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel – LSerni May 25 '13 at 00:02
  • _If this post seems hastily written, it is. I'm barely awake too_ hehe same here, at least you mentioned it, I... _forgot_ to. Anyway, +1 ;) – TildalWave May 25 '13 at 00:03
  • you can instruct the browser not to "sniff" the content (and execute it as such) with X-Content-Type-Options which is only supported by IE and chrome (citation needed). – oreoshake May 25 '13 at 02:12
  • 1
    I notified Google of the logout issue a couple of years ago, but they were uninterested. – Polynomial May 28 '13 at 10:34
  • As you mentioned in your edit, 401 phishing is still a very real issue. It's an unfortunate side effect of the current implementation model for HTTP authentication in browsers. Nobody seems particularly interested in fixing it. – Xander Sep 01 '13 at 16:46
  • How do I read the 401 response from trying to load an ? – nodebase Nov 06 '15 at 01:42
  • @nodebase Look in the HTTP headers. – Luc Nov 06 '15 at 16:47
  • @Luc: Right now I am adding the to the page using document.createElement('img') and setting the src. If unauthorized, it prints the 401 error in the console. I execute this code from a bookmarklet that executes JavaScript. Do I need to be doing this some other way other than document.createElement() ? – nodebase Nov 06 '15 at 16:57
  • @binki Edited the post to clarify/generalize one case. Later, I still mention SMF when it's specifically relevant, as "SMF forums", which you can totally look up without any doubts about which [result](https://en.wikipedia.org/wiki/Simple_Machines_Forum) is the correct one. – Luc Aug 30 '17 at 07:14
18

The IMG tag will attempt to interpret the data as an image, so Javascript won't be executed.

It will be possible to send an image that, once decoded, will require enormous amounts of memory ("PNG bomb"), and it is possible that the graphic routines themselves are vulnerable to malicious content (a carefully crafted image that, when decoded, triggers execution of embedded code). There was such a vulnerability almost ten years ago, and while unlikely, another might pop out.

UPDATE: another did. And another, and this one has a CVSS score of 9.3 -- "There is a total compromise of system integrity. There is a complete loss of system protection, resulting in the entire system being compromised"

Then, the HTTP_REFERER tag will allow the owner of the image site to know what pages have been visited, and through the use of tracking cookies, some information disclosure is possible (e.g. the malicious site hosts an image which is shared between sites A, B and C. The owner of the image can see that a given user on site A is the same person as another user of site B, since the image set a cookie when used on site A, and now the same cookie is arriving from a user of site B). Depending on the scenario, this might be undesirable.

By embedding in the image parts of the design of the host site, an attacker might trick the user into believing that the site is hosting some content that's not actually there. This requires the HTML/CSS to be vulnerable to a sudden image size change. For example, a stock exchange site might display, in lieu of a 200x80 banner, a 200x600 banner whose topmost rows are identical to the original banner, and the part below is crafted to simulate the stock exchange site and is "pushed over" a stock ticker, and reproduces the same stock ticker - but with different values. A unwary user might then be tricked into believing stock figures that are totally bogus. If enough users get convinced, this might allow a sort of "pump and dump" scheme.

A variation of this which reportedly often happens is when you link the image without appropriate permission. The website owner, who bears the cost of carrying and supplying the image to your viewers, has the possibility of switching the image with something completely different. This is sometimes done on purpose beforehand, i.e., a "juicy" image is seeded in the appropriate forums (e.g. a mash against some football team?), then is switched with something with opposite content (the same with that team's arch-rivals). For added fun, the trolling webmaster may record the original IP's that downloaded the image, and keep sending them the original picture. So fans of team A will publicize a raspberry against their own team, and not understand why everybody is laughing - every time they look at the image, they see it mocking team B. Which serves as an alert: do not assume the image YOU are seeing is the same YOUR USERS are seeing.

LSerni
  • 22,521
  • 4
  • 51
  • 60
  • If you're worried about `Referer` [sic] header leaking information, consider adding a new HTTP header `referrer-policy: origin-when-cross-origin` [sic] and modern browsers will always use just the origin info (scheme, port and domain plus one slash) as the `Referer` [sic] value when a link or request goes to separate domain. – Mikko Rantalainen Mar 28 '22 at 19:42
10

JavaScript itself won't be executed, even if the remote server changes MIME Content-Type to text/javascript, because the browsers will aready expect certain MIME types within the IMG tag. That doesn't really mean they're safe to use, though.

One thread I suggest you read is is it safe to allow external images to be attached to Blog or any Web content?. In short though, servers you're linking external images from can still read all the data from the HTTP request that was sent to them by end user's browser (namely request IP address, user agent string, protocol version, and in non-HTTPS originating request also other request headers, among which referer URL string and of course non-secured HTTP cookies).

Remote server could also generate images dynamically, potentially creating other causes for concern (inappropriate content, fear mongering by adding end user request information such as IP address,...), or simply track user activity on your servers by inspecting HTTP request headers described earlier, or dropping third-party tracking cookies with their response. URL exposure in the referer string of non-secured HTTP requests is often neglected and can expose your server's web addresses that you might not really like them to be (CMS location, URL session data,...). Same goes for non-secure cookies that aren't limited to a single domain (location) and can be read and even written over by a third-party.

Additionally, malicious code can propagate through crafted images on client systems that weren't properly patched. One of the more famous such exploits was the GDI+ bug that could allow remote code execution on unpatched earlier versions of Windows. There are also other similar exploits, some of which still not properly addressed on all systems.

Of some latest such exploits, triggering Java (not JavaScript) code from a specially crafted SVG image is possible on some browsers [1][2] :

Exploit-DB - Triggering Java Code from a SVG Image:

SVG is a XML-based file format for static or animated images. Some SVG specifications (like SVG 1.1 and SVG Tiny 1.2) allow to trigger some Java code when the SVG file is opened.

and

Metasploit - Squiggle 1.7 SVG Browser Java Code Execution:

This module abuses the SVG support to execute Java Code in the Squiggle Browser included in the Batik framework 1.7 through a crafted SVG file referencing a jar file. In order to gain arbitrary code execution, the browser must meet the following conditions: (1) It must support at least SVG version 1.1 or newer, (2) It must support Java code and (3) The "Enforce secure scripting" check must be disabled. The module has been tested against Windows and Linux platforms

And a bit more about possible SVG exploits can be read in the Exploits or other security risks with SVG upload? thread.

So, in short, it's not too safe and probably depends on your trust on the remote server(s) you'd be linking images from not to exploit that.

TildalWave
  • 10,801
  • 11
  • 45
  • 84
6

Yes, you are safe.

Of course, the page you get served when you Right click > View Image could be malicious, but no script will be executed in the context of your website.

Moreover, don't forget that the owner of the website of the image can track your visitors on all pages where the image is embedded.

copy
  • 1,939
  • 1
  • 16
  • 13
2

An IMG request is a GET request to an arbitrary server, which may be unsafe

The server response can delete or overwrite cookies which may affect the operation of your browser.

More info

Stackoverflow was once bitten by this bug, where the logout REST API was accessible by a simple GET request.

I think the scenario went like this:

  1. A spammer posted spam on a given page.
  2. On that page, they included a get for /users/logout in an IMG tag
  3. The authentication cookies for the user were removed via the HTTP headers.
  4. Any time an admin or moderator tried to remove the SPAM they were logged out.

This is part of the reason there is a Logout page when you click "log out" on SO.

Aside: Even though SO is a HTTP (no "s"/SSL) site, I think secure cookies would be vulnerable

makerofthings7
  • 50,090
  • 54
  • 250
  • 536