1

Say I've got this HTML page:

<html>
  <head>
    <script type="text/javascript">
      function echoValue(){
        var e = document.getElementById("/path/&#x24;whatever");
        if(e) {
          alert(e.innerHTML);
        }
        else {
          alert("not found\n");
        }
      }
    </script>
  </head>
  <body>
    <p id="/path/&#x24;whatever">The Value</p>
    <button onclick="echoValue()">Tell me</button>
  </body>
</html>

I would assume that the browser treats the ID-string /path/&#x24;whatever as simple string. Actually, it converts the &#x24; to it's rendered representation ($).

The javascript code however uses the literal string &#x24; to search for the element. So, the call document.getElementById fails and I never get hands on the value of the paragraph.

Is there a way to force the browser into using the given ID string literally?


Edit:
Of course I know that I don't have to escape the $. But the web page gets generated and the generator does the escaping. So, I have to cope with what I've got.

eckes
  • 64,417
  • 29
  • 168
  • 201
  • You could just use `$` - it does not need to be escaped as an entity. – Bergi Jan 25 '13 at 09:55
  • Or, if you do need to escape the entity, double escape the HTML version - `/path/&#x24;whatever` – Gareth Cornish Jan 25 '13 at 09:56
  • However, I would be interested in why the entity gets treated different in the script node and the id attribute. – Bergi Jan 25 '13 at 09:57
  • You really shouldn't be using `$` character in the `id` attribute as it is not allowed and therefore will result in invalid HTML. – jasso Jan 25 '13 at 10:44

3 Answers3

5

In the <p id="...">, the &#x24; sequence is interpreted as $, because it appears in an attribute and is treated as an HTML entity. Same goes for all other element attributes.

In the <script> element, HTML entities are not interpreted at all, so it shows up literally.

2

You could try decoding the javascript text without jQuery:

<html>
  <head>
    <script type="text/javascript">
      function decodeEntity(text){
        text = text.replace(/<(.*?)>/g,''); // strip out all HTML tags, to prevent possible XSS
        var div = document.createElement('div');
        div.innerHTML = text;
        return div.textContent?div.textContent:div.innerText;
      }
      function echoValue(){
        var e = document.getElementById(decodeEntity("/path/&#x24;whatever"));
        if(e) {
          alert(e.innerHTML);
        }
        else {
          alert("not found\n");
        }
      }
    </script>
  </head>
  <body>
    <p id="/path/&#x24;whatever">The Value</p>
    <button onclick="echoValue()">Tell me</button>
  </body>
</html>

JSFiddle: http://jsfiddle.net/phTkC/

Gareth Cornish
  • 4,357
  • 1
  • 19
  • 22
  • That depends on where the values you're decoding come from. I've added a line to strip out all HTML tags, to help protect the results. Also note the resulting `DIV` element is never added to the DOM, so any malicious code may not be run, but I wouldn't trust that entirely. – Gareth Cornish Jan 25 '13 at 11:22
  • The values I'm decoding are dynamic content. They are intentionally escaped to avoid XSS issues. Don't want to get vulnerable again by decoding them. – eckes Jan 25 '13 at 11:58
  • Your only XSS danger is if the text added to the DIV actually contains dangerous HTML code which might be run. But, we strip out HTML tags to prevent that, and your text is pre-encoded anyway, so we probably won't even get any HTML tags. The decoded value is treated by Javascript as a string, and will never be processed, so it doesn't matter whether the decoded text is malicious code or not - it can never be run (unless you use it somewhere else as well, and you must handle that case separately). – Gareth Cornish Jan 25 '13 at 13:13
  • thanks for that hint. Please contribute the answer to the question I opened regarding the XSS question arising from this question: http://stackoverflow.com/questions/14521534/is-this-code-vulnerable-to-xss-attacks – eckes Jan 25 '13 at 13:24
0

I'd suggest you to decode the HTML entity in your javascript code:

<html>
  <head>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    <script type="text/javascript">
      function echoValue(){
        var decoded_string = $('<div />').html("/path/&#x24;whatever").text();
        var e = document.getElementById(decoded_string);
        if(e) {
          alert(e.innerHTML);
        }
        else {
          alert("not found\n");
        }
      }
    </script>
  </head>
  <body>
    <p id="/path/&#x24;whatever">The Value</p>
    <button onclick="echoValue()">Tell me</button>
  </body>
</html>
César García Tapia
  • 3,326
  • 4
  • 27
  • 51