0

I store some data in firebase (which can be retrieved in the client), and then, I add it to the HTML using JQuery. This is easy - I just prepend the data to the DOM element. However, the issue is, this raw code will be vulnerable to attacks, so I need to properly escape the data taken from the database before adding it to the HTML. I thought the following code would do the job:

function escapeHTML(text) {
  var map = {
    '&': '&',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;'
  };
  return text.replace(/[&<>"']/g, function(m) { return map[m]; });
}

$('#element').prepend('<h1>Heading</h1><p>' + escapeHTML(data) + '</p>');

When I test this code, by making the value of data something like <script>alert('This should not work');</script>, I thought that it would just add this text to the <p></p> tags, without executing the JS, but it actually ran the code.

I understand that using $('#element').text() will escape the text for me, but I don't want everything to get escaped - I still want to add the <h1></h1> and <p></p> tags, I just need the variable "data" to be escaped. I saw a couple of StackOverflow posts on similar topics, but none of them seem to address this issue - post 1, post 2, post 3.

9
  • XSS is more than just <script> tags Commented Jun 15, 2018 at 17:42
  • @epascarello what do you mean? Isn't that the only way to run inserted JS code? Commented Jun 15, 2018 at 17:46
  • no, there are more ways to do it. Commented Jun 15, 2018 at 17:47
  • @epascarello ook. Could you please give me an example or some links? Commented Jun 15, 2018 at 17:48
  • owasp.org/index.php/Cross-site_Scripting_(XSS) Commented Jun 15, 2018 at 17:50

1 Answer 1

0

The reason the code in your question didn't work is because all the entities like &amp; in the Javascript are parsed as the characters they represent when the JS in the HTML is parsed. It would work if you put the code in an external .js file, since that's not parsed as HTML. Or you could double-encode them:

  var map = {
    '&': '&amp;amp;',
    '<': '&amp;lt;',
    '>': '&amp;gt;',
    '"': '&amp;quot;',
    "'": '&amp;#039;'
  };

But a better way is to create the <h1> and <p> elements separately, and put the escaped text in the paragraph using a jQuery method.

const data = '<scr' + 'ipt>alert("foo");</scr' + 'ipt>';

$("#element").prepend("<h1>Heading</h1>", $("<p>", {text: data}));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="element"></div>

If you want to fill in data attributes, you can do it similarly:

$("#element").prepend($("<div>", {
    data: {
        attr: data,
        another: someMoreData
    },
    text: "hello world"
}));
Sign up to request clarification or add additional context in comments.

4 Comments

doubt this would meet the OPs needs if the content contains tags like bold and such. Maybe it is plain text and would be fine....
Why do you say that?
@Barmar I am actually adding the data from firebase like this: $('#element').prepend('<div data-attr="'+data+'" data-another="'+someMoreData+'">hello world</div>'). So, I don't know how to use your JQuery method... Also, this is already in an external JS file, and even if it wasn't, I don't think it would get parsed as HTML - it's in a string. But this is probably not the cause of my issue. However, your double escaping method worked like a charm! Thanks a lot! I can't upvote you yet though, as my rep is too low
I've added code that shows how to fill in the data attributes using the object method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.