I have a site that has the following javascript that is being executed:

var t=location.hash.slice(1);
$("div[id="+t+"]").text("The DOM is now loaded and can be manipulated.");

I was thinking that if I appended the following to the url:

#message]");alert('test');//

That it would execute the following javascript:

$("div[id=message]");alert('test');//]").text("The DOM is now loaded and can be manipulated.");

But when it runs the console prints the error:

Syntax error, unrecognized expression: div[id=message]");alert('test');//]

Am I wrong to think that my input would generate the javascript that includes the alert? If so, is there any DOM based XSS attack in the first two lines that I posted?

  • I was thinking the same. Also I thought about that: #message]).html(<img src=xxx onerror=alert(1));// but it not seems to work. Instead, I have found that a simple #<img src=xxx onerror=alert(1)> works but I don't understand why. A $("div[id=<img srcxxx onerror=alert(1)]") is a strange jQuery element. – ibrahim87 Sep 18 '14 at 22:11
  • 1
    If you have a syntax error, start small. Does "+""+" work ok? If not what's the smallest, simplest thing you can get working without an error? Make one tiny change at a time and see when things break – atk Sep 19 '14 at 2:02
up vote 3 down vote accepted

$("div[id="+t+"]")

That's not JavaScript injection. For it to be JS injection, the attacker-supplied value would have to be written into the JavaScript code from the outside (for example in a server-side templating language or eval in JS itself). That's not happening here, there is no dynamically-generated JavaScript. There's just a plain string concatenation being done inside JavaScript.

It's not client-side HTML injection. For it to be HTML injection, there would have to be attacker markup content written to the DOM. There's not here, only the static string The DOM is now loaded and can be manipulated. which is written using the safe method text() which does not permit markup.

There is an injection problem happening here, but it's only Selector Injection. The JS string variable t is being copied into a CSS selector attribute value at JS runtime. Characters that are special here include ] (which ends the attribute value) and backslash (which introduces CSS escapes).

That's still a bad thing, but the worst you can do with a selector injection is make the application select the wrong element, for example:

http://victim.example.com/page#x],body,div[id=x

resulting in the selector

div[id=x],body,div[id=x]

which would, because of the reference to <body>, replace the whole page with the text The DOM is now loaded and can be manipulated.

Selector injections don't normally lead to DOM XSS. It's conceivable if you could target an element that the application then trusted to execute as code, such as a <script type="text/template">. But when you don't have control of the string The DOM is now loaded and can be manipulated. then there's not exploitation you can do, just annoyance.

You can fix selector injection by \xxx-escaping characters in t that are special in CSS. Better, where possible, is to avoid selector strings and their escaping problems by going straight to the element ID:

$(document.getElementById(t))  // works for any character in t

However in this case it seems hardly worth it as the attacks you can do with selector injection are by and large no worse than the deliberate functionality of letting an attack replace any named div with the text.

The string t is not being eval'd, it is a literal string. String concatenation just creates a new string, you have a similar situation to a simple var y = 'Hash: ' + location.hash.slice(1); which doesn't open an XSS vector. It just assigns the hash to a variable in Javascript.

The result works the same as:

$("div[id=#message]\");alert('test');//]").text("The DOM is now loaded and can be manipulated.");

Notice that I've escaped the ", because that translates to a literal " character in the string, not in the Javascript source. You would be able to use that as an attack if the code were:

var t=location.hash.slice(1);
eval('$("div[id="'+t+'"]").text("The DOM is now loaded and can be manipulated.");');

which is (one reason) why the use of eval is often discouraged in Javascript.

  • OP mentions a syntax error, which, if truly caused by his/her code indicates that it really is being executed, though not necessarily. in the snippet posted – atk Sep 19 '14 at 1:59
  • @atk, In most languages a SyntaxError would imply an error in the script itself, but in Javascript SyntaxError's are also thrown when parsing JSON and when calling document.querySelectorAll as well as anywhere someone might throw a SyntaxError. In the OP's case, the exact error message he is getting comes from these lines of Sizzle (included in jQuery): – Paulpro Sep 19 '14 at 14:10
  • Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); };. Sizzle calls Sizzle.error internally if it doesn't understand a selector. – Paulpro Sep 19 '14 at 14:11
  • thanks for yhe clarification! JavaScript is then a little bit crazy... – atk Sep 19 '14 at 16:50

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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