Jump to content
Nytro

A practical solution of token based attributes to prevent XSS. Can you break JSLR?

Recommended Posts

Posted

A practical solution of token based attributes to prevent XSS. Can you break #JSLR?

JSLR uses randomized attributes and tags to prevent an attacker injecting malicious content. The HTML is parsed via the DOM before it's rendered and only legitimate attributes make it through. It's possible to prevent DOM based injection inside allowed script and attributes by randomizing quotes.

jslr.js:

window.JSLR=function(id, singleQuote, doubleQuote) {	
document.write('<plaintext id="JSLRElement" />');
document.addEventListener('DOMContentLoaded', function() {
var JSLRElement, JSLRContents, html, i, j, k, re, pn, len, attrNamesToRemove = [],
attrToAdd = [], allowedTag = false, script, text;
JSLRElement = document.getElementById('JSLRElement');
JSLRContents = JSLRElement.textContent?JSLRElement.textContent:JSLRElement.innerHTML;
html = document.implementation.createHTMLDocument('');
JSLRElement.parentNode.innerHTML='';
html.body.innerHTML = JSLRContents;
j = html.getElementsByTagName('*');
for (i=0;i<j.length;i++) {
tagName = j[i].tagName;
if(!tagName) {
try {j[i].removeNode(true);} catch(e){}
try {j[i].parentNode.removeChild(j[i]);}catch(e){}
}
if(/^(?:object|embed|script|textarea|button|style|svg)$/i.test(tagName) && !/^(?:canvas|form|optgroup|legend|fieldset|label|option|select|input|audio|aside|article|a|abbr|acronym|address|area|b|bdo|big|br|canvas|caption|center|cite|code|col|dd|del|dfn|dir|div|dl|dt|em|font|h[1-6]|hr|i|img|ins|kbd|li|map|ol|p|pre|q|s|samp|small|span|strike|strong|sub|sup|table|tbody|td|tfoot|th|thead|tr|tt|u|ul|blockquote|image|video|xmp)$/i.test(tagName)) {
allowedTag = false;
try {
for(k=0;k<j[i].attributes.length;k++) {
re = new RegExp('^'+id + '_$');
if(re.test(j[i].attributes[k].name)) {
allowedTag = true;
}
}
} catch(e){}

if(allowedTag) {
continue;
}
try {j[i].removeNode(true);} catch(e){}
try {j[i].parentNode.removeChild(j[i]);}catch(e){}
}

try {
attrNamesToRemove = [];
attrToAdd = [];
for(k=0;k<j[i].attributes.length;k++) {
re = new RegExp('^'+id + '_');
if(!re.test(j[i].attributes[k].name)) {
attrNamesToRemove.push(j[i].attributes[k].name);
} else {
attrToAdd.push({name:(j[i].attributes[k].name+'').replace(re, ''), value: j[i].getAttribute(j[i].attributes[k].name)+''});
attrNamesToRemove.push(j[i].attributes[k].name);
}
}
for(k=0;k<attrToAdd.length;k++) {
if(/^on/i.test(attrToAdd[k].name)) {
j[i][attrToAdd[k].name] = new Function(attrToAdd[k].value);
} else {
j[i].setAttribute(attrToAdd[k].name, attrToAdd[k].value);
}

if(j[i].protocol) {
if(!/^https?:?/i.test(j[i].protocol) && !j[i].getAttribute(id + '_javascriptprotocol')) {
j[i].setAttribute(attrToAdd[k].name,'#');
}
}

}
for(k=0;k<attrNamesToRemove.length;k++) {
j[i].removeAttribute(attrNamesToRemove[k]);
}
} catch(e){}
}
j = html.getElementsByTagName('*');
for (i=0;i<j.length;i++) {
if(/^script$/i.test(j[i].tagName)) {
script = document.createElement('script');
if(j[i].type) {
script.type = j[i].type;
}
if(j[i].src) {
script.src = j[i].src;
}
if(j[i].text) {
text = j[i].text;
text = text.replace(/['"]/g,'');
text = text.replace(new RegExp('(?:'+singleQuote+')','g'),"'");
text = text.replace(new RegExp('(?:'+doubleQuote+')','g'),"'");
script.text = text;
}
document.getElementsByTagName('head')[0].appendChild(script);
}
}
pn=document.body.parentNode;
pn.removeChild(document.body);
pn.appendChild(html.body);
html = null;
}, false);
return null;
};

Test:

http://www.businessinfo.co.uk/labs/jslr/jslr.php

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...