Nytro Posted October 31, 2011 Report Posted October 31, 2011 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 Quote