简体   繁体   中英

Javascript XSS Prevention

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.

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.

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

var string="<script>...</script>";
string=encodeURIComponent(string); // %3Cscript%3E...%3C/script%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

You can use a function like

 function htmlEncode(str){
  return String(str).replace(/[^\w. ]/gi, function(c){
     return '&#'+c.charCodeAt(0)+';';
  });
}

You would then use this function as follows:

<script>document.body.innerHTML = htmlEncode(untrustedValue)</script>

If your input is inside a JavaScript string, you need an encoder that performs Unicode escaping. Here is a sample Unicode-encoder:

function jsEscape(str){
  return String(str).replace(/[^\w. ]/gi, function(c){
     return '\\u'+('0000'+c.charCodeAt(0).toString(16)).slice(-4);
  });

}

You would then use this function as follows:

<script>document.write('<script>x="'+jsEscape(untrustedValue)+'";<\/script>')</script> 

More info: https://portswigger.net/web-security/cross-site-scripting/preventing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM