Abusing noscript
-
Someone found a <script> inside of a <noscript> tag.
<!-- Page is at: http://squarespace.com --> ... ... <noscript id="inline-deps"> <link rel="stylesheet" type="text/css" href="//cloud.typography.com/7811972/758964/css/fonts.css" /> <script type="text/javascript" src="https://static.squarespace.com/static/ta/5134cbefe4b0c6fb04df8065/7400/assets/logomark/logomark.min.js?37"></script> <link rel="stylesheet" href="https://static.squarespace.com/static/ta/5134cbefe4b0c6fb04df8065/7400/assets/logomark/logomark.min.css?37" type="text/css" /> </noscript> ... ...
So now you're probably thinking: "WTF! That script tag will never execute. Nice find Zacy, you're the best. Also we don't mind that you keep copying WTFs from StackExchange sites." But it gets worse.
Here's the top answer: (TL;DR comment below it.)
I did some searching through their code and found this snippet:
var DepLoader = function() {
function init() {
var a = document.getElementById("inline-deps");
if (!a || JS.hasClass(document.body, "deps--loaded"))
webfontsReady();
else {
var b = a.innerText || a.textContent;
JS.addClass(document.body, "deps--loaded"), processRaw(b)
}
}
function isListed(a, b) {
for (var c = !1, d = 0; d < b.length; d++)
if (-1 !== a.indexOf(b[d])) {
c = !0;
break
}
return c
}
function webfontsReady() {
JS.fireCustom("webfontsReady")
}
function processRaw(html) {
var el = document.createElement("div");
el.innerHTML = html;
for (var scripts = el.querySelectorAll("script"), styles = el.querySelectorAll("link"), common, signup, dialog, systemPage, commerce, others = [], inline = [], styleWhiteList = ["site.css", "dialog-", "signup-", "logomark"], scriptBlackList = ["management-", "ckeditor-"], style, l = 0; l < styles.length; l++)
style = styles[l], -1 !== style.href.indexOf("fonts.css") && load(style, webfontsReady), isListed(style.href, styleWhiteList) && load(style);
for (var script, src, s = 0; s < scripts.length; s++)
script = scripts[s], src = script.src, src || "dynamic-assets-loader" == script.getAttribute("data-sqs-type") || -1 === script.innerHTML.indexOf("SQUARESPACE_ROLLUPS") || eval(script.innerHTML);
if (window.SQUARESPACE_ROLLUPS)
for (var key in SQUARESPACE_ROLLUPS) {
var rollup = SQUARESPACE_ROLLUPS[key], js = rollup.js, css = rollup.css;
-1 !== key.indexOf("common") ? common = js : -1 !== key.indexOf("commerce") ? commerce = js : -1 !== key.indexOf("signup") ? signup = js : -1 !== key.indexOf("dialog") ? dialog = js : -1 !== key.indexOf("system-page") ? systemPage = js : key ? others = others.concat(js) : inline = inline.concat(js)
}
for (var s = 0; s < scripts.length; s++)
script = scripts[s], src = script.src, isListed(src, scriptBlackList) || (-1 !== src.indexOf("common-") ? common = script : -1 !== src.indexOf("commerce-") ? commerce = script : -1 !== src.indexOf("signup-") ? signup = script : -1 !== src.indexOf("dialog-") ? dialog = script : -1 !== src.indexOf("system-page-") ? systemPage = script : src ? others.push(script) : inline.push(script));
var loadOthers = function() {
for (var a = 0; a < inline.length; a++)
"dynamic-assets-loader" != inline[a].getAttribute("data-sqs-type") && load(inline[a]);
for (var b = 0; b < others.length; b++)
load(others[b]);
JS.fireCustom("dependenciesLoaded")
}, loadSystemPage = load.bind(this, systemPage, loadOthers, "system page"), loadSignup = load.bind(this, signup, loadSystemPage, "signup"), loadCommerce = load.bind(this, commerce, loadSignup, "commerce"), loadDialog = load.bind(this, dialog, loadCommerce, "dialog"), loadCommon = load.bind(this, common, loadDialog, "common");
loadCommon()
}
function load(tag, callback, label) {
var head = document.head;
if (Array.isArray(tag) && (tag = {nodeName: "SCRIPT",src: tag[0]}), !tag)
return void (callback && callback());
if (tag && (tag.src || tag.href)) {
var child;
"SCRIPT" === tag.nodeName ? (child = document.createElement("script"), child.src = tag.src, -1 !== child.src.indexOf("combo") && (callback = function() {
Y.Squarespace.FrontSite.Core.domReady(!0)
})) : "LINK" === tag.nodeName && "stylesheet" === tag.rel && (child = document.createElement("link"), child.href = tag.href, child.rel = "stylesheet", child.tyle = "text/css"), child && (child.onload = callback, head.appendChild(child))
} else
try {
eval(tag.innerHTML)
} catch (e) {
}
}
return {init: init,webfontsReady: webfontsReady}
}()As you can see, the <noscript> tag has the ID #inline-deps, which is referenced in the code (line 3) to load dependencies asynchronously and on-demand. > > They probably use a <noscript> element as it allows them to directly access DOM elements, instead of having to place it in a string or a comment (which I consider particularly bad, as comments are not meant for actual information) and then parse it. It also prevents the execution of scripts and CSS styles until specifically loaded. > I personally find this an abuse of the <noscript> tag. I'm not even sure if it's valid HTML5 code. Using other methods such as declaring dependencies in a JavaScript object with a script loader should be used where practicable. TL;DR comment: > the whole thing is a bit complicated but basically it checks that it needs to load scripts and/or stylesheets, then gets them from the <noscript> element to be executed. …Wow. That processRaw function… I'm going to list the WTFs I spotted, but first the obligatory javascript "expert" who has just added this to his bag of job security tricks. > That's a pretty nifty trick using `<noscript>` to store DOM elements, I must say. And a +1 and an accepted answer to you for diving into their minified JS before me and figuring it out! – Agent.Logic_ Agent.Logic_ is the guy who asked the question. Also, cartman82: @cartman82 <a href="/t/via-quote/2640/6">said</a>:<blockquote>Nice find. Not sure it's a WTF, though. I'm not entirely clear on why do they have to load everything dynamically, but if they do, this seems like a clever way to do it.</blockquote> And now the WTFs: - Creating a long list of variables in the for statement. - Not using most of those variables in that for loop. (They're used later in the function.) - Abusing the `,` and `&&` operators instead of just using braces. (I didn't know javascript could do that too.) - Abusing the [conditional operator](http://thedailywtf.com/Articles/One-Bad-Ternary-Operator-Deserves-Another.aspx). Edit: Dammit! Posted it early by accident.
-
Nice. Wait, that makes no sense. I though this XSS hole was already fixed. Or maybe it only works for <noscript>? That would be TRWTF...
-
<img src="/uploads/default/5967/07da38cb653ffe6e.png" width="197" height="97">
Nice.
Wait, that makes no sense. I though this XSS hole was already fixed. Or maybe it only works for <noscript>? That would be TRWTF...Oh cool. Let's see what I can do. Any suggestions?
-
-
Oh cool. Let's see what I can do. Any suggestions?
http://what.thedailywtf.com/t/how-about-this-sidebar-audio-src-http-soundjax-com-reddo-64951-5ecddyhorn-mp3-controls-autoplay-audio/889That’s what caused the XSS to be fixed the first time...
-
Nice find. Not sure it's a WTF, though. I'm not entirely clear on why do they have to load everything dynamically, but if they do, this seems like a clever way to do it.
-
Nice find. Not sure it's a WTF, though. I'm not entirely clear on why do they have to load everything dynamically, but if they do, this seems like a clever way to do it.
Maybe, maybe not. However, this comment:
Those devious code hackers ;) . I hope they documented it well, before some smart guy deleted it 'since it has no use'. – Patrick Hofman
Points out a real problem with it.
I think a better way to handle it would be to put it in a javascript variable.Beisdes, the
processRaw
function was what I was focusing on.
-
Beisdes, the processRaw function was what I was focusing on.
Ah. That's what I call "hipsterscript". A version of javascript written by hipster who'd rather work in ruby or functional languages. Ignore it.
-
Changing the image to this:
-
Wow. Just... wow.
Edit: added an HTML comment to the title, but it didn't go through.
-
I think that bubble should probably have the word sexy in it somewhere.
someone make it happen.
-
I think that bubble should probably have the word sexy in it somewhere.
someone make it happen.
What should I change the text to? "I agree with whatever the sexy morbs just said"?
-
yes, that appears to be appropriate.
make it so number one!
-
Abusing my Leader-Powers to protect Frontpage (seriously guys, this has been out for so long. Stop hogging onto that XSS ;D)
Filed Under: Leave the Frontpagers alone! They live their lives without Discourse and thats good for them!
-
I wonder if blink and marquee would work, too!
-
Here's the result:
-
yeah, The frontpage is not being sanitized at all.. Discourse Team couldnt fix it because they dont have access to TDWTF-files
Filed Under: This one falls on Alex
-
Aaawwwww.
No one got to see my masterpiece.
Well. It was fun while it lasted.
-
works for me still
-
Hmm, they don't!
-
the marquee worked but now its gone and replaced with & l t ; again (i dont know what escaping prevents that becoming the character) so it will probably break on the next cache...
shame!
-
Oh right, caching.
I forgot about that.
-
Seems like Discourse does something similar:
https://meta.discourse.org/t/how-to-add-advertisements-to-your-discourse-forum/11105/3
but now its gone and replaced with & l t ; again
I know I shouldn't say that but I didn't lose my ability to edit titles and mobile (the only thing I had available) didn't update the title before I clicked on the pencil. Hence it's back.
Just... please don't abuse that XSS-vunerability. I don't really know who could fix it besides @apapadimoulis and while it starts small it can get really annoying really fast
(meaning: breaking layout -> inserting content that should not be on a frontpage-site, etc). And yeah, just because YOU (the reader of this post) wouldn't do it, doesn't mean somebody else who is getting the idea won't do it.Filed Under: Thats how the world works | Also mentioning @aliceif so the title-thing gets sorted out :D
-
please don't abuse that XSS-vunerability.
Are you new here?
I'm surprised that the front page isn't spinning around.
-
Last time it was audio playing on the front page courtesy of Discourse.
-
Yes, I remember that little gem.
-
Are you new here?
I'm surprised that the front page isn't spinning around.Well, we already SEXYfied the main page. There's not much more we can do before it counts as malicious.
Edit: Also, I love that there are only 4 on topic posts here and no one cares.
-
I've just been awarded the <kbd>XSS Award</kdb> badge for this topic, and I want to point out that VinDuv should also get this badge. But I'm not sure who to contact.
-
@PJH is the person to ask about such things. Or flag the message in question for moderators.
-
@PJH (@dhromed is MIA)
-
Ok, @PJH, VinDuv deserves the <kbd>XSS Award</kbd> badge as well.
-
Sorted.
-
the marquee worked but now its gone and replaced with & l t ; again (i dont know what escaping prevents that becoming the character) so it will probably break on the next cache...
shame!
&
So <