Javascript XSS Prevention

27,738

Solution 1

Here is a general encode procedure:

var lt = /</g, 
    gt = />/g, 
    ap = /'/g, 
    ic = /"/g;
value = value.toString().replace(lt, "&lt;").replace(gt, "&gt;").replace(ap, "&#39;").replace(ic, "&#34;");

If your user doesn't submit anything to your server you don't even need the above. If the user submits and you are using the user input then the above should be safe. As long as the '<' and '>' are globally sanitized and the parenthesis also are you are good to go.

Solution 2

why not use encodeURIComponent before sending the data to the client?

var string="<script>...</script>";
string=encodeURIComponent(string); // %3Cscript%3E...%3C/script%3

Solution 3

Considering https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html

Here is an implementation of their recommendations :

function escapeOutput(toOutput){
    return toOutput.replace(/\&/g, '&amp;')
        .replace(/\</g, '&lt;')
        .replace(/\>/g, '&gt;')
        .replace(/\"/g, '&quot;')
        .replace(/\'/g, '&#x27')
        .replace(/\//g, '&#x2F');
}

Also make sure you use this function only when necessary or you might break some stuff.

But I suggest you to take a look at already made libraries for sanatizing output :

https://github.com/ecto/bleach

Share:
27,738
onlineracoon
Author by

onlineracoon

Dutch developer, interested in Javascript, Node.js, Backend and Frontend development of webapps and mobile apps.

Updated on July 09, 2022

Comments

  • onlineracoon
    onlineracoon almost 2 years

    There is a Node.js project that sanitizes data and there is an OWASP library for JavaScript that handles sanitization to prevent XSS.

    I have been benchmarking these libraries, and they are pretty intensive and maybe an overkill, my application does not need any dynamic HTML (submitted by users, bbtags or what ever, not required at all) so why not do it like this:

    1. Disable "<" and ">" characters, don't replace them or anything, just disable them, if the user submits these, give them a warning that these are disabled (client- and server-side validation)
    2. & => &amp;
    3. " => &quot;
    4. ' => &#x27;
    5. / => /
    6. Encode submitted URLs (GET parameters etc.)
    7. DOM based XSS is covered since my application uses HTML5 PushState and the backend is fully separated from the frontend.

    Would this be enough to protect myself, as I said, my application does not require any HTML submitted by users, so I don't need the < and > tags at all.

    Thanks for all the feedback, this is what I use right now:

    var pattern = /<(.*)>/;
    
    function hasHtmlTags(string) {
        return pattern.test(string);
    };
    
    if (hasHtmlTags(userData)) {
        // Do something?
    } else {
        // Create entity.
    }
    

    So users can still use their emoticons :< and such, and the function only gets triggered if a combination of < and > is found. So no expensive regular expressions and such, just disable < and > in combination and we should be fine.

    • onlineracoon
      onlineracoon over 11 years
      I see, but users don't use it that offen, and if they do they are not essential. So I figured, why not spare the overkill and disable them.
    • user2428118
      user2428118 over 11 years
  • Quentin
    Quentin over 11 years
  • onlineracoon
    onlineracoon over 11 years
    The user does submit stuff to the server, just no '<' and '>' characters. If sanitizing them would be the solution, why is there a whole OWASP cheatsheet? owasp.org/index.php/…
  • Quentin
    Quentin over 11 years
    @onlineracoon — See this section of the cheatsheet
  • Konstantin Dinev
    Konstantin Dinev over 11 years
    The owasp cheatsheet covers all possible scenarios for XSS. If you are not outputting data within tags' definitions (not content) or within script tags, then you can omit a whole lot of it.
  • RASG
    RASG over 11 years
    +1 to set things straight. if the answer is not wrong, there is no reason to downvote. if there are better answers, they will be upvoted.
  • Quentin
    Quentin over 11 years
    The answer is wrong. If someone enters <script>...</script>, they do not expect it to be rendered as %3Cscript%3E...%3C/script%3. It mangles special characters into line noise. You could prevent XSS by discarding absolutely all input, that doesn't make it a solution to the problem.
  • japrescott
    japrescott over 11 years
    Thanks @RASG! @Quentin; Yes, if you have an inline editor, that will be the case. But thats not onlineracoon's question. Its about XSS. Therefor he wants to prevent userA writing scripts that execute on userB. If he uses encodeURI when sending HTML to userB it will be "ugly" yes, but UserB will see it as <script>...</script>. Same as if you'd replace them with html entities as the accepted answer proposes. And good joke about "discarding all input". He also could shutdown his website to prevent XSS ;)
  • onlineracoon
    onlineracoon over 11 years
    @KonstantinD-Infragistics I updated my answer, please review it.
  • Konstantin Dinev
    Konstantin Dinev over 11 years
    @onlineracoon You should be fine with what you have.
  • rahil471
    rahil471 about 5 years
    This method also encodes "space" " " which is harmless and not required. eg: monday 10 becomes monday%2010
  • japrescott
    japrescott about 5 years
    @rahil471 that is besides the point as the user will see it as monday 10 even when the data itself looks weird.