Do you know this feeling when you see a technical
tweet by some cool hackers you look up to, but you don’t understand what they are saying? And then you are also too scared to ask what
it means? Well… I know how you feel. I have been there. But that’s why I’m here for you now. I want to explain to you in as much detail
as I can, what this tweet by Mathias Karlsson is about. Especially, what’s up with this “name”
here, that’s a really cool trick if you don’t know. So, welcome to Tweets explained! Or maybe Xplained. Heh. I don’t know. In this format I explain to you tweets by
hackers. <intro> So, before we can understand this tweet, we
obviously should go to the original tweet which was quoted here, and that one is by
Justin Gardner. He is also a very experienced bug hunter who
also is co-host of an awesome “bug bounty” podcast called “Critical Thinking”. They are talking a lot about appsec and web
security related topics. So if you are looking for a technical podcast,
go check it out. But back to his tweet. Apparently yesterday he exploited a tricky
XSS. There was an injection into the JS context
and he couldn’t use any parentheses, backticks or single quotes. And his solution “made use of the fact that
any function in javascript can take any numbers of parameters”. The function looked like this, x with two
parameters. And apparently, through his injection, this
is how he triggered the XSS. Alright. When trying to understand XSS payloads, especially
a little bit more complex payloads, it can make sense to setup a quick XSS testbed where
you can play around with it. And php is actually a super useful tool for
that. So let’s create a quick .php file for testing. We don’t necessarily need HTML code here,
but I just use some basic boilerplate. And I create a form with a text input where
we can submit the XSS payload. The important part is of course the javascript
script tag, where we can then define our test function x. With the two parameters. And I guess, let’s just call console.log
to print the parameters passed into the function. Now we need to call this function, and we
can do x(“a”,”b”) for testing. We haven’t added any .php code just yet,
but let’s quickly test it. If you have php locally installed you can
now simply execute php -S IP:port in the same folder, and a small php development server
is launched. Now let’s take our browser and go to 127.0.0.1:8888,
and we have here our test page. If we open the developer tools and refresh
the page, we can also now see the result of the function call to x, the two console logs. Cool. Now let’s simulate the XSS. Justin gardner said the injection happened
inside the 2nd parameter as a string. So let’s replace the second string here
with a PHP variable output. This is just how php works. Basically whatever $xss evaluates to, it will
replace this php snippet with that value. Now we just have to set this value, and for
that let’s write some more php up here. This is just some basic .php. Just copy & paste it from somewhere. We set the variable $xss to empty string,
but if we have the GET parameter xss set, we then set xss to that. And that will work nicely with our HTML form,
because when submitting that form it will addd the xss parameter to the url. Also justin mentioned that there was a XSS
filter that didn’t allow the use of parentheses, backticks and single quotes. So let’s add a preg_replace that replaces
these characters with nothing. Basically removing them. Alright! Now we can go back to the browser, and we
can use the XSS GET parameter to simulate the injection. XSS=123,
And we can see in the developer tools, in the HTML code, we are now calling x with 123,
and in the console we can see the console logs. From the function call to x. Now before we look again at how Justin got
XSS here, let’s play a little bit ourselves. So our goal is XSS. Cross-site scripting. By the way I made a short series about where
the name comes from. If you are interested in some hacker history,
definitely go watch that. Also… if you watch that, then you might
also understand that a better name for XSS might be “Javascript injection”. So our goal is to somehow inject and execute
arbitrary javascript that we want. And in this case, we know the attacker can
control the string of the second parameter. But inside a string, we cannot execute any
javascript, it’s just a string… but what about when we break out of the string? Double quotes should be allowed. Let’s see? That works! See how our injection now lead to the function
x being called with three parameters? While the function doesn’t expect a third
parameter, this is not an error in JavaScript. So you can see our javascript code executes
just fine. And this is what Justin meant when he said
“My solution made use of the fact that any func in JS can take any number of parameters.” Cool. So where do we go from here? How can we execute arbitrary javascript code? Typically in such a case you could now simply
close the function call. Add our own code like alert document.domain. And place a js comment at the end, just to
avoid any js syntax errors. BUT the problem is, parentheses are not allowed! They get replaced. So we can inject quite some stuff, but without
parentheses, how can we call arbitrary functions? There are a few tricks with for example backticks. Alert backtick 1 backtick, that would work. BUT backticks are also not allowed. mhhh… Well, let’s go on a short detour. Let’s look at another typical XSS case that
can happen in client-side redirection. So sometimes code uses window.location to
redirect the user to another page. Assing window.location = “/asd”, would
for example redirect to /asd. But you can also use full URLs, and redirect
to https://hextree.io. BUT, besides relative or absolute URLs, you
can also use javascript URIs. These allow you to execute javascript code
in the current origin. So window.location="javascript:alert(1)",
will execute alert(1). Now.. we are almost at the full explanation
of this code. Just one small thing. What’s important to know here is that with
JavaScript in the browser, the window object is very special. ALERT is actually a variable or function registered
on the window object. So the full function path would be window.alert(1). We just use the shorthand alert(1) all the
time, because the objects in the window object are globally accessible. Fun fact, our x function is the same way,
it exists here as windows.x! But we can just call it with x. This also works with HTML IDs. if we have a div with id=”test”. This html element will become easily accessible
from Javascript via windows.test, or just test. So let’s come back to the injection. What Justin is actually doing here, he is
assigning a string to location, or rather window.location - it might just look confusing
without the window. But it’s just that. So, if in the injection we assign https://hextree.io,
we get a redirect. But…. uhm… mhh? It definitely works, but it might look a bit
weird just seeing it like this. This is an assignment, and it’s like a parameter
to this function? This looks like bad code. But this is just how lots of programming languages
work. In the case of javascript, and many other
languages, a variable assignment, when it gets evaluated, actually returns a value! If you assign a=1 in the console, you see
here the return value! 1
If you place it in parentheses it is maybe a bit clearer. Or here as a parameter to console.log, a=1
returns 1, so console.log prints 1. So yeah, this variable = string inside a parameter
looks like invalid javascript, but it’s totally legal! And now we can put everything together. We inject location=”javascript:alert(1). AND! Doesn’t work. Well. of course it doesn’t work, because
parentheses are not allowed. But because we assign here a string, we can
simply use hex encoding to encode the parentheses. So \x28 and \x29 should work. Let’s try it again. And there we go. We get the alert box. Cool! Now we understood this tweet and we can move
deeper. let’s move on to the quoted tweet by Mathias
Karlsson. Here we see another variation of somehwat
the same thing, but there are some differences that are worth exploring. So first of all. The cool thing here is that it doesn’t need
any commas. So in case you cannot add another parameter
via the injection, this would still work. The trick here is to use arithmetics instead. Or rather string concatenation. string + string. And in order to concatenate one string to
another, this part of the addition needs to be evaluated. BUT if we go back to the XSS from justin,
and try + with assignment, that wouldn’t work. Because now there is a syntax error. Javascript doesn’t know in what order to
execute this. First the assignment or first the subtraction. So you get an invalid left-hand side exception. If you could inject parentheses, then that
wouldn’t be a problem. This way you can force Javascript to first
evaluate the assignment, and the result is then used for the string concatenation. But because you cannot inject parentheses,
Mathias’s solution is pretty neat. He defines here a Javascript object. And this object contains a key “a”, and
the value of a is set to…. Of course the result of the assignment to
window.location. So basically by using a Javascript object
you can again make sure the javascript syntax is valid to be able to perform the location
assignment. Pretty neat. But there is more. the second example is another variation of
this idea. Here a new class b is created. And this class overwrites the toString method
with an arrow function. So when executed it will execute this part,
which is again the assignment to window.location. And toString is executed, when you attempt
to use plus for string concatenation. Javascript wants to append a string. And to figure out how this object or class
is represented as a string, it calls toString - triggering the assignment. Anyway. This is just very condensed javascript and
can look very scary. So both of them are pretty neat. BUT there is one more trick hidden in here
which you might have not noticed. And that is the name. Unlike justin’s example directly assigning
a string, mathias assigns the variable “name” to it. And maybe you have guessed it already. What is this variable “name”? Of course it’s another global variable that
exists on window. Window.name. Right now it’s an empty string. But this one is ultra weird if you haven’t
seen it before. BECAUSE. You can actually set this from another website. When you dynamically open a new window in
javascript with window.open, you can actually define a window name. So let’s call this window “test”. We execute it, the new window opens. And if we now, on the opened page, look at
window.name, we can see it’s “test”! This allows us to optimize the XSS from before. We don’t even need to care about the string
encoding for the parentheses. We just place all our javascript payload into
the name. And in our xss GET parameter we now assign
name to location!. If we execute this window.open, we now trigger
the XSS. pretty neat. You see, the name variable trick is incredibly
useful for XSS in situations where you don’t have a lot of space for your payload, or there
is some annoying character filtering happening. So if you didn’t know this trick, well now
you know. And it was hiding here in plain sight in mathias’s
tweet. Cool. That’s kinda it. Now I hope you understand these two tweets
and what you can learn from them. But, I have one small addition to this as
well. Justin didn’t say whether pointy brackets
were not allowed. And how exactly the context looked like. But in our test case here, we could also inject
a closing script tag. And then we can inject for example svg onload,
to trigger a XSS. of course we can still not use parentheses directly, but we can use the
name trick again to get our payload in there. So that might have been another solution as
well. Please let me know in the comments what you
think about this format. Is this fun? Is this useful? Also, if you come across a any tweets, or
toots or posts that you don’t understand. Send them to me on Twitter or Instagram. My DMs are open. And maybe I can explain your tweet next. And f you are interested in more hacking tutorials,
check out my channel, it’s full of free content. But we are also currently building hextree.io. This is an online training platform built
by me and stacksmashing and it’s currently in a close beta. But I hope soon we are opening it up further. We still need to produce lots of content for
it, but eventually we will get there. So checkout hextree.io, go follow us on twitter
and join our discord. Also if you want to support my free videos
on Youtube, checkout my patreon or shop.liveoverflow.com. By purchasing my shitty handwriting as a font
you can support this channel, and you get something useful out of it. Maybe if you had read the tweet in my font,
it would have been easier to understand!? Right?! Anyway. See you soon.