← All talks

BSidesCHS 2016: "Weaponize JS : Making the most of XSS opportunities" - Mic Whitehorn-Gillam

BSides Charleston · 201639:05183 viewsPublished 2016-11Watch on YouTube ↗
Speakers
Tags
CategoryTechnical
StyleTalk
About this talk
Title: "Weaponize JS : Making the most of XSS opportunities" Speaker: Mic Whitehorn-Gillam Mic Whitehorn-Gillam has been a security enthusiast for as long as he can remember, having started playing around with cryptography before he really knew anything about anything. Professionally, Mic comes from a background in building web applications across a diverse array of server-side technologies including asp.net, java, ruby, and node.js. After spending about a decade as a full-stack developer, Mic combined his passion for security and his experience with web applications to start penetration testing. When he's not working on client engagements or his own development projects, Mic can often been found running on nearest trails.
Show transcript [en]

um this is like the first time I'm done public speaking since I was in grade school so if you can't hear me just you know stick like a finger up so I know you can't hear me yeah for that yeah all right so making the most of your of your cross site scripting opportunities now do I have any web developers in the room people with web development experience yeah we got a few okay you might be bored all right I'm what I'm going to cover is a lot of sort of elementary javascript stuff you can use to do some cool things but you probably already know how to do a lot of it okay so quick bit about me

I'm just going to pop all those up so yeah i'm a senior security consultant at secure ideas which is based in jacksonville although i'm actually based in Rock Hill South Carolina I'm a sort of a long time software developer I professionally about 10 years and then before that upwards of 10 years as sort of a hobbyist as well and most of that was was web app development so I've always been sort of a security enthusiast found a few security flaws in the wild one of my sort of favorites was everybody knows Gawker probably so not the current platform but an older platform I discovered at one point they had a bunch of admin controls for

comments that were just hitting with CSS there was some back-end protection on most of those buttons but one of them the delete comment button did not have back-end protection so kind of quietly reported that one and went away but that was that was before I was actually doing it intentionally I just kind of picked through the site in there was and and that was really early in my in my web her career and so I kind of took off from their security as my does my main job function is a really recent move for me actually only been doing it since kind of earlier this year if you want to look at looking up on

github I've got my countdown Gilliam and also my Twitter and so if you just want to take out your phone really quick launch Twitter tweet about how awesome this talk isn't how all the people are drinking beer right now are missing out all right so just a quick why not just do an alert one why you're in the middle of a pen test that proves execution you can move on to some better findings you could do that sometimes the clients just not going to get it because the even developers I've worked with people have been doing apps for 15 years they see I show them a cross-site scripting flaw and they go so what what can you do with that

sometimes it's within scope to exploit that in order to proceed further with the test maybe to capture credentials for example so it's good to have the tools to do that and so I'm going to show you a couple of JavaScript tricks that you can probably use if you want to develop some more advanced payloads all right so here's what we're gonna hear is what I'm going to go through a little bit of Dom traversal it's elementary if you've been doing a lot of web stuff but it's sort of critical it's more critical now with stuff like angular and react amber where you've got binding with with templates because they don't have IDs as much so you can't necessarily easily get

a handle on the element you want sometimes you need to get the nearest element you can and then kind of traverse the Dom to get the one that you really want stealing HTML forms my example here is going to be actually just you find the form get a handle on it add an on submit function that gives you a copy of the contents of the form first and then submit it to their server basic rewriting the Dom fetching hosted resources you got a JavaScript file or an HTML file that you want to use in your exploit that you're hosting on your own server that you control just generally how to pull it in and use it

I'm introducing malicious objects I'm going to spend a fair bit of time on that one and that's basically without breaking their program getting your malicious code into the sort of logical flow of it probably I'm thinking we'll have more time than we need so if you have questions as we go just stick not a finger but a whole hand up and we'll try to address those as we go so a lot of this is going to build on top of itself you got questions or I haven't explained something well which is why you would have questions then let's get it out of the way right away just quickly want to mention jquery because it's it is almost everywhere but

i'm not going to use it in my examples is it not because you shouldn't use it if it's there by all means take advantage of it but I don't want you to be dependent on it so my examples don't use it certainly feel free to use in the wild though uh oh hey there's another one I he was dropping on asynchronous communication this is actually extending the idea of of introducing malicious objects but it'll be actually an example that involves listening in all basically the Ajax activity so that you can get a copy of first of all the payload their second innings second of all their response without breaking their applique again all right so

Dom traversal it's easy when you have an ID attribute like whereas my ID attribute my idea no gave some of these could have an ID attribute well those are big oversight and and so if you got one that should be unique it should be on one element and you can do document.getelementbyid grab that element do whatever you want with it that's great if it's there if it's not there you got to get more creative you have to get what you can get and then Traverse from there so you had a lot of options for getting a handle get element by ID if you if there is an element that isn't the one you want but

as near it is often your preferred option because again you get one element you get the specific element it implies that it's not going to be some dynamic thing where you're working through a list of items and you want a specific one um you could get on payments by name which name property mostly you'll see that on forms a lot of the time they're only be one with that name anyway but not always that returns an array get elements by tag name it's actually the name of the tag so if it's div its div its paragraph it'll be a p hey those tend to be sequential in the order they appear in the markup you can't necessarily always count on

that but but it they tend to be by class name that's CSS classes you'll see a lot of those and query selector I'm not going to dig into that too much first of all because I would actually need to call the reference material on that to write the selector in the first place um second of all I think it's just a little bit much this late in the day but that will let you do some of the sort of flexible things that you could do with jquery as well fairly easily like when an attribute has a certain value of that tag matches your selector uh all right Dom traversal so what I've done set to green

people actually read that okay um what about like a family tree here so if I've got okay that's you so that's the element you that's the element you can get that one's got the ID and you want to get to to your cousin over here basically you got a concept of kind of one parent to to an element and as many children as you want and siblings everybody else is a sibling to it so you'd sort of be moving up a level to the parent hot so don't you jump this is the button yeah all right nice right so I go from I do get element by ID you so I get this one dot parent node to move up and then the

aunt is the sibling of the parent and then one of the children of the ant is the cousin and that's pretty much all there is to but it's up and around I'm gonna see this is gonna be interesting I'm gonna see if I can pull a code example that I have

yeah got it that's it you see that can't see back in wow that's not even on the right screen that's way way small okay let's give it a quick try anyway we'll keep that in mind now that's blurry shove that every way I so it would look like document dot get element by ID yeah kind of covered document dot get element by ID one thing you need to check with those is there's often a difference between like getting a sibling for example and an element sibling is what the actual method is to the two different things there's slightly different implications the one you want is the element one usually because the other one will get

you text nodes as well which you probably don't want to act on

so it's just rude rudimentary that you're moving up and down the tree if you're moving up you're moving up one level if you're moving down you're moving into it one of the many children when you interact with children you're dealing with an array rather than a single element stealing HTML forms

there are a few ways to do it you do some some gymnastics with cross-domain posting and redirecting i don't i don't like that approach i think it's it's more difficult and more prone to failure but if you hold the event on a non submit event then you can run an asynchronous post like an AJAX call to your own server to pass everything you want to there and then let it submit normally or resubmitted as the case may be [Music] trying to think how my examples are gonna work here i'm not sure they're big enough fit on this screen we might end up having to pull people in and kind of go over it i'm also going to throw it up on github

after as well uh but let's give to try it give it one more quick try

no no I observing

ah hey there we go that's better a little awkward from here so we could actually do that that dom's reversal really quick there's us there's a cousin that we want to get to this is exactly the same as the one that was in the slide ya know if I can get to Melanie it's hard to tell where my console is right now move that over so

alright so it's that to love you see that

yeah I call that it returns term returns that element by ID just like you'd expect

simple you can change it together parent node moves you up

elements Hitler that room that's wrong

and siblings going to get us a text now I was next siblings what it is that's what I want there we go and you can do first child our first element child but I'm gonna do children there we go we got to our cousin just sort of by chaining together those moves

so going back to it to where we'd sort of moved on to try this again yeah

by the way I like to do this I like to start of work it out in the browser when I can so I've just changed it on an exact payload button because i figured i'm doing a presentation it's probably going to go wrong so i wrote it in advance stuck on a button but there's there's my actual script again probably easier to look at it on get up after the thick but let's see if i can expand that up so we can see it is or pull it up in a code editor yeah let's do that

there we go so that's functions they're sort of simulate the payload executing [Music] just going to login message there to say that it's armed you probably don't want to do that if you're actually trying to use it for an exploit and then I access form element itself in this case I gave it an ID to make it easy tag into the on submit event handler and give this function that I created here so it's a little bit weird this Z this function gets called right away when I'm assigning the event handler and returns this function which is what will actually be the event handler kind of covered how that works a little bit more later but so I passed this fall

saying this Zed is the false which is what i use to tell whether it's been called before so that i can do what i'm going to do so I'm grabbing the elements by the tag name here in this case I just logged them it to the console again you probably want to throw them off onto your server or wherever you want to if you're capturing credentials in this case that's all I'm doing and then if that is false which means the first time it's the first time through I set it to true run a set time out this case I made it a little bit more pronounced I set it at 23 thousand milliseconds it's sort of

to simulate the the delay you would have the past off asynchronously then I return a false which will actually keep the form because I'm returning this it'll keep the form from submitting then inside this time out when it actually happens i call the submit on the phone i get the form again a call submit it'll pass through Zen will be true it will return true and it will get submitted normally now if I shorten up that delay to something you sort of need to kind of take a guess at what your latency is but I five to make that six hundred milliseconds that's going to be fine it'll be less pronounced and it'll work pass those foreign values to me

first then the form will get submitted normally user won't even know that anything is wrong and all have a copy of the credentials that were on that form

how are we doing so far good

losing my cursor yep oh I'm looking at two different screens that are mirroring the exact same thing looking for it there we go I know sort of explains exactly what I was just talking about so I hold the the on submit event while I wait for the new synchronous post it to happen and then execute it changing the Dom you're not going to spend a lot of time on this is most of the time you're going to use you going to get a hold of your element you're going to do a dot in turn HTML and throw in the market that you want usually that's going to be the easiest way to do it it's also a good thing to

look for if you're looking for a cross-site scripting vulnerability by the way this tends to be taking a value and throwing it in some place that it will render the other one that you might want to do if you want to hide an element show it again later it's just style that display none CSS hides it takes out of the flow and you can rerender it later when you need to buy doing a display you can actually pass it an empty string and it'll it'll show up again usually you might have to do in line depending on what you're changing if it has a display property said already that can be useful if you're doing something like

hiding a form showing something that's saying hey you time don't need to login again and then showing that form again when they do

that one second the other thing this sort of thing is good for changing the dump place where I found it valuable before you find a vulnerability but it's not on a page that you wanted on find another registration page I'm going to use that effectively in like a social engineering attack you got to get somebody who what you get somebody to register a little bit silly or you going to somehow convince an existing user that they need to register again neither that was really practical you would like it to be a login page so make it a login page on their domain and then direct them there and I think I've got another quick example for that

so

this is sort of a normal login page very simple one that I threw together sort of like my reference implementation or login page and I'll show you the rendered version in a second and my registration page follows the same kind of design concepts it's on the same site it usually does in fact a lot of people use something like a master page from dotnet or use a partial template to include the exact same JavaScript resources so even if they're not using them yell aloft and have all the same JavaScript resources on every page

ah

so there's the registration page in this case again I took a shortcut figuring its presentation things are going to definitely go wrong and I created a variable already on the page that has the mark up from the login page normally I would just go to the login page and grab a copy of that but in this case put a div at the top level i'm going to use that as my handle

there we go I know I've got a handle oh my did in fact that's a collection and I want the individual element there's my template

let's see if it worked it uh and it's great it's already on the domain that the registration page was on even less likely to look at a place probably using the same valid ssl certificate and if you point the forearm action at the same place they'll actually login successfully but you can rig it up so that you can capture credentials with it at the same time

yeah what about fetching HTML for another another host yep and I i hope i have a working example of that I think I do but that's absolutely a possibility you can set it up on a different host if you can't pass in the whole payload it's always nice if you can just kind of edit it in line through the vulnerability that you already have but if you can't do that then it's always a positive thing if you can ok you can fetch it from someplace else you can write a minimal payload to go and get it and just shove it in where you want it anyway I think probably will do the JavaScript version of that first

set a little small as a little small let's zoom in a little

so this has a little bit of sort of extra going on that's not entirely necessary but the idea is still there xmlhttprequest everybody know what that is okay anybody not know what that is people use that for Ajax this is the object native object that underpins everybody's Ajax implementation doesn't matter jquery's is backed by this yet the mini jQuery version in angular is backed by this whatever implementation you're using with reacts is backed by the same thing if you've got an easier one to use like the jQuery one is available and more concise definitely use it in this case I didn't but I'm just right I got my URL I'm fetching it when it comes back I throw it into an

eval just plain old JavaScript eval and it'll execute the script file it's the same reason why you don't want to see evals on the client site walk maybe as a pen tester maybe you do depends it's always sort of difficult to reconcile wanting to find things with wanting the client to be secure but it's a bad thing to see normally because it's it's the sort of thing where if you can get something into it you can get script to execute in this case we're using it for exactly that purpose now and the same thing essentially can be done for HTML from another source the only thing is instead of using eval and here i would do document ID enter HTML whatever

the object is the Dom Dom object the element is dot enter HTML and shove the response text into that instead you could reference style sheets that are available on that page it reference other JavaScript that's available on that page you just shove it in there and it will get rendered which can be really effective delivery mechanism if you've got a big pelo a big big chunk of HTML and you can't stick it in through your initial attack vector

okay this gets a little bit scripty so we've got to kind of build it up with a little bit of the time try to bear with me it's so injecting malicious objects into the end of the flow it's hard to not make it sound complicated but it's not complicated really so it's going to go through some really basic stuff but we'll build up to some advanced stuff within like three or four slides don't worry we got a function we're going to add function takes two parameters a and B add them together and returns that that value right next to hello world it's one of the most basic examples of anything ever next one down is

almost identical as a variable add receives a function assigns it to that variable you call it exactly the same way afterwards it's just taking an anonymous upon function in assigning a reference to it in the form of a variable think that would be different there is that I could assign something else to add I can do it in either case actually but I can assign something else to add a different function and that function would get called instead from all the functions that already reference it by name now that's just sort of an artifact of of being an interpreted language really so let's modify it a little bit here i have a function that returns a function

that does the adding thing it's my ADD factory function it's anybody has worked around you has certainly seen the factory method before is it's sometimes an overused design pattern in this case this is just sort of a step on the way to to where we're going for us but so it's a function returning a function and I'm assigning a variable assignment at a reference to that function to this variable add one I could call add one and it would be calling that function essentially that that returned one which is the same ad one that we saw before but it would be called add one here I made it more generic so we've got this math factory

same idea function returning a function but in this case I'm passing in and value and treating that value as a function so it doesn't make a lot of sense to actually do this if you want to write an add and subtract function but it illustrates the example while I think I passing the logic as a parameter in form of a function and then I use it and this function does enter one that I'm returning which is what it's going to get assigned to add or subtract respectively maintains a reference to this value even though this is essentially gone out of scope and there's a reason we're doing this and we're right about to get there

I did this yeah ah so the main thing to look at this changed here that I've done so I've wrapped it in a set of brackets is that same thing that looked weird before that false that was passed in I brought to set of brackets around my function and then another set of brackets afterward that have the parameter and when you see this is this JavaScript closure syntax this outer function will be immediately invoked and this will be returned right away and assigned to the variable and for the practical purposes of what we're about to do that's really good so this is what we're going to do we're going to modify this fetch stuff from

the server set as an existing function on your client site this is what we're going to hijack on them so what do we do we reference reassign the reference to it so that anything that's calling it cause our function instead but we still need the original functions that it can work normally so they don't detect that there's anything wrong to the page so when we created we pass it in ok so that we have the only reference to it and everything but there anywhere that they are referencing it is now repointed our function in this case all I've done is logged the payload when it comes in and then I call their function normally anyway and again

even though I use log in this case I can do this as an asynchronous post off to my site 22 grand values and then probably in the call back or promise if using promises call the normal function let it perceive as it normally does but what I'm missing at this stage is what response they're actually getting from the server which I might be interested in so that's where we're going to go next and that's what I right here I've created an evil success function recall that that grabs the response and then cause their success callback with that same response passed to it same thing for the fail this would be of course inside of that

previous one rape where this dot dot dot is so that when there's is called when when the original function is called we use those callbacks my evil once there's still get called normally but we grab a copy of their responses first and that it's really pretty much it for stealing Ajax which if you're using it for intelligence rather than credential capture or if they're using page hex to do authentication it's a really good thing to to steal maybe you can steal sensitive information that way because you're on a page that's using Ajax to do with the infinite scroll thing and you just want to grab records as they scroll it was more I didn't know there's more

um right and yeah okay so this is if instead of is just a made-up function by it this is an example I'm using I'm using an asynchronous function and daisy changing in the on response rather than kind of doing it in line like I was fundamentals of it are really very different it just means that you're calling their function in like a call back or promise rather than calling it in line in a synchronous call and that's like hmm well I started early I started two minutes early so we're almost at 40 minutes a couple of useful resources if you've been doing anything on the web you probably already know about them but we're going to point them

out anyway mdn you want to figure out how any kind of objects in JavaScript working that's w3schools is worth a mention it was used to be my first stop now mdn is my preferred result either one of those though kind of they've got a listing of all the methods that have that are there look at document for example we're doing a lot of things that were document I get element by ID you don't know how something works look at document itself or look up element and find the generic stuff that every element has because that sort of stuff is useful for interacting with it but really once you got JavaScript execution your imagination is sort of the biggest

limit you can do a lot more than just pop up an alert box you kind of do whatever you want as long as its client side and maybe a few things server side as well anybody any questions yes

yeah I any sort of cross-site scripting vulnerability and there it's hard to do a generic kind of thing to use every time because everyone is different so a lot of those well I did showed you a couple of ways to pull it in through through your own Ajax call and use it that way you might be able to use that to also use a payload that is that obeys the filter I didn't cover getting the excellent actual execution didn't think I'd have time I guess I did but one really good reference you know wasp there's a good filter evasion cheat sheet they're usually the best telltale be the easiest telltale that you've probably got something you throw a

regular double quote into a into a field and it gets reflected and escapes the field then you've got something probably that you can work with that answer the question yes how do you guys edge like your ex the end is sort of a case by case scenario i haven't really had to do a lot of it and i've done testing and chrome i think part of is just that those filters don't seem to be all that effective if the site is vulnerable but i can't say that i've tested it in enough depth to really know what the limits are there any else all right beers right [Applause]