Search code examples
javascriptphpajaxxssinnerhtml

Security using AJAX and set innerHTML?


Consider the following circumstances:

  • I send an AJAX request (no user input) to PHP which starts a function.
  • The function returns a string of raw HTML. Could be anything - a list of links, a bunch of empty divs, SVGs to insert inline, most of a page... No user input data is used in its creation.
  • I receive the string as a response and insert it into a div.
  • I'm (currently and would ideally like to continue) using pure JS - no libraries.

Accepting that some level of insecurity is inherent in JS, how insecure is what I've just done?

The OWASP XSS Cheat Sheet says to escape all 'untrusted data'. Is the result of my AJAX request untrusted given the above circumstances? Is the result of any AJAX request regarded as 'untrusted'?

Is inserting HTML this way bad practice? If so what should I be doing instead?

Edit to clarify a couple of things:

  • URL variables in the AJAX request are only used to start a PHP function on the server. No variables are passed to that function at all (specifically, I'm using Joomla's com_ajax component).
  • All of the returned code is static and written by me.

Solution

  • As long as the response is truly static and does not involve user input of any kind, this is fine. AJAX itself (as you hinted) does not make it vulnerable to XSS (as long as transport is secure, which practically means https).

    One caveat (not necessarily in your case, but in general) could be what you consider user input and what not. Your application always receives input from the user, or it may use parameters received previously, or even by another application. Even if you don't pass parameters, there are request headers, cookies (if any), and user input can also be read from a database. Even if it looks like static data in the database, at some point it may have originated from some kind of a user, probably a legitimate (but rogue) one, or an external attacker, or it could have come from another application that writes to the same database (not a good practice anyway).

    So in short, if the data you send back is really just static data (as in hard coded), that's not vulnerable, but there are many ways it can become dynamic, and from there it's your (ideally risk based) decision, what you protect against and what you trust.

    The best practice is to encode everything by default to avoid mistakes. If you are sure that you trust the source of data that you want to insert into the DOM as HTML, that's fine. Threat modeling may help to discover what you should and should not trust, but in some cases it may also be obvious.