Solving a Hard Google CTF challenge - "Paste-tastic!"

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
during the Google CTF 2019 there was one web challenge which had zero solves and the challenge was pace tastic and the description says it's a pretty pay solution now I have no idea what that means or what it hints to seems like there's a lot of paste words but recently live overflow explained the solution to this challenge on his live stream since I was fascinated by this challenge I wanted to learn about it and also make a video on it so I thought it would be awesome to collaborate with the one and only live or a float for this video so here we go [Music] this video is sponsored by integrity a bugbear platform where you get paid for finding security vulnerabilities for more information check out the links in the description for those of you who don't know who live Overflow is I think there's not a single person but still I'm not sure there might be that one person who just stumbled upon my videos out of nowhere but anyways he's a fantastic youtuber who puts out security related content on you know pretty much everything including web Hardware low-level all kinds of stuff so go check him out now let's get back to the challenge [Music] all righty we are given a link for the challenge and upon visiting link we see what looks like a code snippets been kind of thing similar to paste bin I guess we can name the pace whatever we want and choose a language let's choose I don't know JavaScript and write code and save pretty much so for each paste you get a unique URL and the paste has some syntax highlighting going on looks exactly like the editor that we just saw a couple of other things to know is that the pastes are protected by a CAPTCHA and also there's this DMCA button which is basically for reporting you know any sort of legal issues like copyright infringement and stuff like that but reporting will send the link to the admin who can review it and maybe take it down I don't know if you play a bit of CTF so you know that this pattern of reporting to admin is quite common usually there will be some sort of an XSS vulnerability in the page and you have to use that to steal the cookie from the admin and pretty much get the flag and also if we head back to the home page we see our recently viewed pastes right so now we know how this looks like on a UI level let's dive into a bit of code [Music] let's start by looking at the source we can see in JavaScript at the top each of them have a nonce value which is related to CSP let's check out the CSP using the dev tools as we can see from the response headers there's CSP or content security policy which tells the browser rules if certain things are allowed to run on the page in our case there's the nonce which means only the script tags which have this non value as the attribute will be executed for example if you have an XSS vulnerability they inject the JavaScript won't run because it doesn't have the right nonce value scrolling down a bit we see the cookie that's being set to our session and this is also a hint that the flag is in the cookie of the admin session and we need to get our hands on it coming back to the code we see there's this config object which has some dependencies plugins and preload scripts these seem to be libraries which are used for the text editor and syntax highlighter there also seems to be the use of mark CAS which is used for markdown rendering and we will look at it later we can see that this web app uses Google reCAPTCHA but more importantly we have the app to J's let's open it up and look at some internals fjs is about 1200 lines of code and we will try to understand it but of course not everything look at the code that is relevant for us in order to solve it let's copy the code over to the text editor to have some syntax highlighting alright let's jump right in we see that there's a class and about five more functions we can start from this if statement this is a condition to check if the location path is create or view one for creating the post and other for viewing under init create function it creates an object from the viewer class and calls the init function the rest of the code here isn't that important so let's walk through the class first let's look at the constructor flow creating a few object will create a sandbox iframe with the attribute a allow same origin which allows the same origin to interact with the content of the iframe init function will be called to load the necessary scripts this pulls the preloaded scripts and dependencies and then calls load plug-in and load script the load script function is interesting because it fetches the scripts defined in the config variable and evolves the contents in this case it fetches the mark GS and prizm JS library this is certainly a point of interest after the iframe is loaded the init listener is called the init listener function uses with can elect our contact management Python to perform some stuff inside the sandbox iframe first it adds an event listener for messages and checks if the message came from a valid origin it also gets the viewport now based on type of the data which could be render or scroll it performs different set of actions we only look at the renderer because the other one isn't that important now if this is of tibor Endura it removes the few poor children and checks if the language is set to markdown if so it will use the mark J's library with sanitize set to true to convert the markdown code to HTML safely the sanitize apparently helps to mitigate XSS in markdown context it also has a sanitizer function which is basically called at the time of sanitization the output of this markdown is set as the inner HTML of the viewport now this might be a good place to look into write for like X s or something we will look into it but it doesn't help much you will see why later now if the language is not marked down it simply creates a code block and uses the prison trace to highlight the code the entire thing is wrapped inside a try/catch if there was an error then it sends a message of type error using post message to the parent window post message is an API for cross window communication and in this case it's using it to talk to the iframe and vice-versa remember the rendered code is going to be inside the sandbox iframe so hence uses post message to communicate to the parent window so that it can reload everything [Music] we saw that the viewports in our HTML we're set to some user input after converting it from markdown to HTML now can we find an XSS here spoilers yes we can but it doesn't help us that much because the iframe itself is sandboxed sadly no JavaScript but I think we can quickly go over the XSS part because it's interesting in live overflows stream he also showed a way to get the XSS working but I wanted to go over how this actually worked so I spend the next good hour reversing the library and found some different bypasses basically the sanitizer is replacing the evil words like script with an empty string the mark J's library does a heavy use of regular expressions and there are a bunch of rules to find using them the sanitizer filters them based off of the rules defined inside of it and also filtering doesn't consider the fact that the new string could also be malicious so we can do something like script inside a script tag and I would work and there's also a Nintendo flag which decides the context of the string that it's passing so you can enable that by adding another script tag right in front of it and when the replacing happens in the end you have a working payload that's what live although showed you but after looking at the code there were some interesting tags that enabled something called in raw block which basically means the markdown sanitizer sees the string as safe of course this is an interesting part of the library so I took a look at it we can enable this flag if we prefix any of these tags and after that we can place anything and the parcel would think it's safe except for other tags duh there's no bug here right hear me out there's also another flaw in how the parser matches a tag basically the regular expression for matching the tag is completely wrong and it could be easily bypassed so it forgets the fact that the forward slashes are part of the tag as well which means this is matched and this isn't but clearly both of them are tax combining these two floors together we can bypass excesses filtering very easily and the entire payload might look something like this and guess what even if the sanitizer function replaces the entire string with I don't know something like a non empty string in this case it would still work [Music] chrome chips with an XSS auditor and it's a mess the point of the exercise auditor was to find reflective exist s scenarios and prevent these attacks first they thought blocking the whole page would be fine but as you might have seen in one of my videos about the 35 C 3 CTF challenge file manager exists s auditor can be abused now they change chrome again and decided to just block the injected parts of the code instead of the entire page but guess what this can be abused too and here's how we can do that assume our website has this piece of code we have three script tags and clearly we get the message nope but we want to get the output yes but that's not possible because the Apple variable is set to true so the condition becomes false so we never see the yes message but remember what I told you earlier the exists s auditor can block certain parts of the scripts code the way the exercise auditor thinks that there is an XSS is by checking if the user input is reflected back onto the page but what if we fake the user input we can simply add a get parameter which literally has the code that we want to be blocked so in our example we don't want Apple to be true so we can copy the script tag and edit as a fake get parameter the browser things that this piece of code was the user input and also it was reflected back as the HTML text this means it could be a XSS so the auditor blocks it in the actual exploit we will be blocking the convict part of the code to make it undefined and you will see why later this is just one of these things where people try to implement security features but they give rise to other bugs this is the first concept you need to know to solve this challenge now on to the next one [Music] one of the cool things about the WEP is that you can include other websites inside yours using iframes but along with this there comes this complexity in managing security between these frames the fundamental security feature a browser office is the same origin policy which essentially means if the hostname domain the port number and the protocol match then you are allowed to interact with it else you are not so let's say we have a website love overflow calm eye framing pone function calm now now if AFRICOM cannot access the contents of point function calm because the hostname or domain is clearly different but let's say there's life over comm affirming point function calm which iframes life overflowed have come now who can access who first off life overcome is not allowed to access point function outcome and hence life all flow calm cannot access the inner life or flow calm because this frame is inside of porn function calm right wrong life overflow can actually access a list of iframes of point function calm and if one of these iframes matches life overall calm then you can read and write between this in our case the outer life overflow calm can read and write to the inner life overflow calm even if the middle frame is porn function calm a different domain [Music] we all know that we can get a handle to the HTML element using Dom API live get element by ID or get element by tag name but did you know that you could also do it without using any of these functions browsers have kept this legacy feature even to this day it's named Dom clobbering and here's how it works let's assume that we have an h1 element with the ID dog now we can get the handle to this h1 element by using the traditional document gallon and bar ID dog but instead of doing this we can simply do dog that's it for legacy reasons browsers create variables inside JavaScript that's pretty much a handle to the element with the same name as its ID or sometimes even the name attribute but if you already have this variable named dog and the browser's wouldn't override it no worries there [Music] now that you know the concepts required to solve this challenge let's get into the exploitation part just a quick refresher we have a website where we can paste code snippets and save them we can also view them later while viewing the code it's actually displayed inside a sandbox iframe where we cannot execute JavaScript because even if we have an XSS it's still sandboxed which means no JavaScript execution there's also no extreme options which is a header which means you can frame that website we also know that the flag is in the cookie of the admin session all right now for the vulnerability what is the vulnerability here is it Dom clobbering or the XSS auditor abuse or the frames thingy well it's none of those actually all of these are used in the chain for the exploit but the flaw here is the fact that there is no origin check when the error message is sent from the parent via the post message we can see that we have a check down here but when it's doing the same for errors it forgets to check the origin so that's the bug right there the thing is this error post message will also load all the dependencies in plugins and you might start to get the idea here since we can send these error messages via post message and it reloads all the plugins and dependencies but these dependencies and plugins are defined in the config variable now think about this what if we use the Exorcist auditor to block the part of the code and make it look like it never existed now the browser will look for the convict variable but it can't find it because we have undefined they're using the XSS auditor trick now what if we can redefine it ourselves but how well Dom clobbering we know that by simply creating these HTML elements with the ID or the name we can kind of create the JavaScript variables right which is great now let's try to understand the entire exploit chain basing this idea we have the attackers website porn function calm now let's go ahead and create an iframe which has the SRC set to some random paste on the page now we don't want the config variable to access so we can under fine it using the XSS or dirty trick now we know there's one iframe inside the random paste and that is the code view block but guess what there are two more iframes in the very same page that you might have overlooked I'll give you five seconds think about this where is the other two iframes did you get it don't worry if you're then I'll explain the web app uses ray captcha and this ray capture creates two more iframes in your very same page but you can see one of them right here now here's what we'll do we'll go through the iframe tree and change the location of the reCAPTCHA to our domain pone function com what are you ask because we are trying to do the similar thing what we talked about earlier we will set up our page like this where at the top and the inner iframe is the same so that we can communicate between each other even if the middle one is different if we achieve this which means we can read and write a bunch of things between these two frames because they obey the same origin policy now did you know that we can change the name of this in an iframe you might think wait a minute isn't the name of the iframe defined by the pace astok website which means if you could override it doesn't it violate same-origin policy actually no since these two iframes obey the same origin policy you are allowed to do whatever you want between these two iframes including changing the name now what happens if we change the name to config while this becomes Dom clobbering and it will affect the middle iframe which means the middle I frame or the pace astok website will have a variable called config because we undefined it using the XSS auditor but got it back by changing the name of the inner iframe just basically the Dom clobbering now the config variable is not an HTML element but instead an iframe window object apparently browsers assign different values to different kinds of elements for example if the ID of the h1 element is set to Apple that will have a JavaScript variable named Apple which has the value set to the HTML element h1 but let's say for iframe if the name instead of the ID is set to Apple then there will be an object in the JavaScript and that will be a window object of that iframe not the HTML element so in our case config variable will be the window object and not the HTML element one behavior of marked Jas is when you create a heading after converting from markdown to HTML the ID of that element will be set to the value of the element for example if we have a heading something like this test simple then after mark Jas converts the markdown to HTML it looks something like this now we have the value which is the test as the ID as well now again remember creating HTML elements with the ID will also create the JavaScript variables with the same name so we'll use this behavior to create config dependencies and config dog plugins and config dot preloads so let's see how we can specify a URL in the plugins so that we can load a URL of our choice and in the end that will be evolved in the init function we see this piece of code this styl config is set to config dot viewer with an index of index right now the config is set to the window object of our website now if we see how the pace tastic website or the middle one trice load the plugins we see that it uses this dot config and this dot config is the config dot view err of index and later down the road it also tries to load some scripts using same config variable now we have control over the config variable but we need to create the viewer so let's go ahead and do that by creating another iframe inside pone function comm why you asked because it's asking for the viewer property inside the config variable since the conflict variable is porn function comm and its parent is paste astok website it cannot access anything inside of it because of same origin policy unless we create another iframe inside porn function comm and set its name to viewer and also set its source to paste a stick markdown paste now the middle iframe should be able to access the inner paste assic iframe this checks out going down a bit we also see that there's the load plug-in function and inside of it we see this Const equals this dot config dot plugins of Lang and the very same spec variable is sent to load script to fetch the actual script via the URL and a valid this is our target and we have to somehow get our URL inside that spec variable now to set the attacker controlled URL ask the value of the spec variable we need to create an h1 element and have the ID set to plugins inside this h1 element we need to create another element and set its source to pretty much the value that we want and that will be the source to the Evo JavaScript URL because down here while fetching it does spec the SRC which means it's trying to access the SRC property inside the spec variable so we can use an image tag and set its source to our Evo javascript URL something like this now in markdown it looks something like this but how do we set the spec variable to this image time to get the SRC as you can see the spec variable is simply they stock config to plugins of Lang since the image tag is inside the plugins h1 we can do plugins of first child which will give us the first and the only child that's the image tag and the source of this image will be set to our evil website so we need to set the language to the first child value which can be done when we raise the actual error message via the post message for illustration purposes I have set up a domain pullin function in grotto I'm using n Drogba keys it's a reverse proxy and it helps me make local webservers available on the internet and it also gives me an HTTPS connection which is very much needed for this exploit to work because you'll get mixed content issues [Music] great now to summarize first we use the xs/s auditor to remove the conflict variable then we create an iframe and set it to a random paste then we change the location of the Google reCAPTCHA iframe to our domain so that we can control it from the outside then we change the inners iframes name to config doing this will create a config variable in JavaScript in the middle I frame then we create another iframe within the innermost iframe and set the source of the markdown which has some HTML elements which does the Dom clobbering and set the dependencies plugins and preload scripts the plug-in is set to h1 tag and inside of this h1 tag we have an image tag which has the source pointing to our Evo javascript file when the pace tastic page looks for this doc config dot plugins we get plugins h1 tag and doing this dot config dot plugins of first child will give us the image tag and now this image tag has the SRC value set to our evil javascript file now when the error message is sent via the post message to the first child iframe or simply the old middle pay static page it won't check the origin and that's the vulnerability it tries to reload all the plugins which will look for the config variable and now that it's done clobbered the original variable is being replaced with our newly crafted one which will get the evil javascript file and in the end this will be valid so to steal the actual cookie inside the JavaScript we can make a simple request back to the attacker control domain along with the cookie now all there's left is to report this click on the dmca use map to intercept the request and modify the report URL and pretty much wait for the flag boom we have a flag and finally this happened I guess it's time for us to say goodbye to the exorcists or attack [Music] [Music]
Info
Channel: PwnFunction
Views: 93,088
Rating: undefined out of 5
Keywords: google, ctf, xss, chrome, xssauditor, DOM, DOM clobbering, LiveOverflow, pastetastic, web, security, websecurity, hacking
Id: 2up8J9dErHI
Channel Id: undefined
Length: 26min 26sec (1586 seconds)
Published: Tue Sep 03 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.