Ctrl-F template strings... yep, there they are.<p>So if you didn't know, ES6 added template strings, which are these really awesome things because they have multiline and string interpolation capabilities (and they're safely far away from JSON, which in my opinion shouldn't have such capabilities). They are very pretty and incredibly handy; you write<p><pre><code> console.log(`
I'm so ${scared} in case ${ I.fall.off() } my chair
And I'm wonderin' how I'll get down the stair
`);
</code></pre>
and this gets converted into<p><pre><code> console.log("\nI'm so " + scared + " in case " + I.fall.off() +
" my chair\nAnd I'm wonderin' how I'll get down the stair\n");
</code></pre>
Except for one thing: they're called "template strings" because actually this is a sort of "default behavior" which can be metaprogrammed. There is a default interpreter which could be written:<p><pre><code> function interpret(text_segments, ...split_segments) {
var out = "";
for (var i = 0; i < split_segments.length; i++) {
out += text_segments[i] + split_segments[i];
}
return out + text_segments[i];
}
</code></pre>
but... you can write one of your own, if you want, and put it on the beginning. Therefore:<p><pre><code> > console.log(`abc ${[1,2,3]} def`)
abc 1,2,3 def
undefined
> console.log `abc ${[1,2,3]} def`
[ 'abc ', ' def' ] [ 1, 2, 3 ]
undefined
</code></pre>
Notice that the side effect of console.log has happened with the arguments given to it, allowing for code execution.<p>As for mitigation... add detection of backticks to whatever code was detecting parentheses. It's not a very widely used symbol in any context other than shell scripting and LaTeX anyways, so you're probably good to go if you just outlaw that character before calling eval() on the whole.
Spent a couple minutes figuring out how to spell "butts":<p>[[]+{}][+[]][++[[]][+[]]+[++[[]][+[]]][+[]]]+[!![]+[]][+[]][++[[]][+[]]+[++[[]][+[]]][+[]]]+[!![]+[]][+[]][+[]]+[!![]+[]][+[]][+[]]+[![]+[]][+[]][++[[]][+[]]+[++[[]][+[]]][+[]]+[++[[]][+[]]][+[]]]
I've done something similar with PHP, by casting an array to a string (The string "Array") and using "variable variables". If only there was a way to call functions in PHP without using letters in the code... <a href="https://gist.github.com/nubs/5849633#file-nodigitsorquoteseither-php" rel="nofollow">https://gist.github.com/nubs/5849633#file-nodigitsorquotesei...</a>
I found this article had more depth: <a href="http://patriciopalladino.com/blog/2012/08/09/non-alphanumeric-javascript.html" rel="nofollow">http://patriciopalladino.com/blog/2012/08/09/non-alphanumeri...</a>
This article did give me the <i>out-loud-at-the-office</i> chuckle and a whispered "what the f°°°" that only awe-inspiring hacks far above my programming intelligence level can provoke. :)
Reminds me of Church encoding or even iota reductions, where you reduce a set of higher level symbols to primitive symbols that in combination have provably the same meaning.