Angstrom CTF 2021 - Web Challenge Walkthroughs

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to take a look at some of the web challenges on the angstrom 2021 ctf not too sure how many of these challenges we'll get through this is the last day of the ctf so i was hoping to get through some more challenges and and get into like the crypto in this category but oh well we'll see how many challenges you can get through here and any scripts that are created will be uploaded onto github you can jump between the chapters at the bottom of the video or in the description and if you like the video drop it a like and subscribe thanks the first challenge is called jar and the description says my other pickle challenges seem to be giving you all a hard time so here's a simple one to get you warmed up so we're giving a link to the web website we need to go and test out we have a picture of a pickle jar here and then we have some files to download as well so we have a python file the pickle image and a docker file as well so i've already got these downloaded let's go and let's go and have a look at the website first of all though let's go and get burp suite running as well and we might want to enable burp to only capture this traffic as well so let's just enter in a test here into this add item box and we can now go and have a look at our http history so if we wanted to we could say that we want to add this to the scope and then we could also say here that we only want to show in scope items and that will refrain from showing other items we could also if we have intercept on that will capture all requests but we could go in and say that we only want to intercept client requests if the target is in scope so i'll do that as well and this means that if we were to do that again we can see that we have our hello there let's say test as well add another item and you'll see it's intercepted that request but if we go and have a look at say google or go it won't intercept that request so with that request intercepted we can go and have a look at it we can see we've got a cookie here with a base64 encoded value so we could grab that and go over to hackverter and if we want to decode it okay that's gonna base64 encoder okay let's go to decode base64 we'll do basics for url and paste that in and we can see that we have some funny looking characters and then we have our hello string there as well okay so let's go back to our proxy so it's passing in this it's making a post request to the ad uri and it's passing in the item which is equal to test so we could play around with that and put in some different values and see what happens but we know from the description this is going to be related to pickles and pickling so um that's what we're going to want to focus on so each time as well this page loads let's let me turn off the intercept each time the page loads we get our text in a different location and we could go and have a look at the source code let's go to view source and there doesn't appear to be too much for us to look at here so let's go back and let's go and have a look at the locals source code and see what's going on so we can open up jar.py so the first thing you'll notice is we have the flag variable declared at the top which is calling os environment.get and it's either going to grab the flag environment variable or if that doesn't exist it will use this default value instead we then have the app root for pickle.jpg which is simply going to return the pickle image we have our home directory which will assign contents the value of our cookies so if we go back to our cookies let's hit f12 and we'll see that we have this contents variable with the base64 encoded value so it's going to grab that it's going to base64 decode it like we did in hackverter and found the hello string and then it's going to load it with pickle.loads then this this is what will happen if there's a contents inside the contents variable so if there was a cookie otherwise it'll create a new list and for each item in the items list it's then going to randomly print it somewhere on the screen the final route is the add route so if we make a post request to add which we did do already if we go and have a look at our http history then this was the add post and it takes in a parameter of items so it'll assign contents equal to our cookie value again and if that cookie value already existed it's going to load the it's going to do the same thing as here so it's going to base64 decode the cookie and then it's going to load it using pickle loads otherwise it'll create a new list so exactly the same as we have here and then it's going to append the new item so whatever item we provide here in this case we've provided the string test it's going to append that to the list and then it's going to base64 encoder and pickle dumps so the opposite of pickle loads and set that to the cookie so essentially just to clarify that each time we add a new item here it's going to deserialize it's going to basically decode and deserialize all of the items that we already added so the test and hello and then it's going to add our new item to it it's going to basically encode it and then it's going to serialize it so what we want to do is have a look and see what is the issue with the pickle serialization so we'll go and have a look at the python documentation and see what the potential vulnerability is and how we might be able to exploit it so let's go and have a look first of all python pickle and we'll just go and have a look at the official documentation and the first thing we'll see is a big red warning box saying the pickle module is not secure only on pickled data you trust it's possible to construct malicious pickle data which will execute arbitrary code during unpickling never unpickled data that could have come from an untrusted source or could have been tampered with now obviously in this case uh the the data which is being unpickled is this cookie variable which we do have control of we can edit it either here or in burp suite whenever we're sending the request we can modify it here so let's go and have a look as well if we look for pickle exploit this is a really good article describing how to actually exploit the vulnerability i used this and referred to it throughout the hack the box challenge i think it was baby interdimensional internet whichever one had the pickle in anyway and this gives us an idea how we can create an exploit for it so i'll not cover this article in too much detail but if we scroll back up here we'll see that there's this reduce method um and by using reduce in a class which instances we're going to pickle we can give the pickling process a callable plus some arguments to run so this means in the example is given here they have created a class using this reduce function and it passes in a command to the os system call so any command that they enter here will be executed and then they're just doing the same thing that's happening in the code here in our in our python code which is base64 encoding the dumped pickle item so in the case of the hi the box challenge we weren't able to simply inject our own pickled cookie we had to modify the value that was already there so let's just go back over what was a little bit what was done in that challenge we can use python dash m pickle tools and you can see here that we can pass in a file so let me actually just go and grab the cookie that we have at the moment i'm gonna close that down for now i'm gonna grab this contents cookie and i'm going to i'll echo this to file and then we'll base64 decode the file and then if we run python dash m pickle tools and pass in that file then it's gonna unpickle so instead of just simply getting let's actually cut out new too so with base64 decoded the pickled object here and we can see the hello and the test string but the rest of it doesn't make much sense but if we actually use the pickle tools we can actually disassemble that whole structure and see um see what's going on behind the scenes i don't really understand too much about the structure of the pickles pickled objects but um in cases where you might need to go and modify some values or inject something into a pickled object then this this would be a useful way to do it as was the case in the hack the box challenge in this case we're just going to try and overwrite the cookie with a new pickled object whereby we can use something like we saw on in that article there to create a rce class which calls the reduce function and makes some kind of system call so let's get this test out locally as well we have a docker file which was given to us so we can run docker dash or docker build dash file docker file in this current directory and let it run through the steps to install whatever it needs to you can see that setting up our environment variable and then if we go and have a look at docker images docker image ls we have this new docker image let's do docker run i'm gonna pass in dash dash net host and then the image id that we want to run you can see that's launched that as a local server so let's go and try and open that up and see yep it's taken us to our pickle so if we go and try and add a new item here just say hello add item i mean go back to our terminal and actually see that any requests that are made here we'll be able to view as well which means we could also go to our source code and make some modifications if we were trying to debug this locally that could be that could be quite handy but let's try and get this tested out locally and then we'll test it on the remote server so i've already got a script created created to do this exploit.py so let's take a look at it it's essentially just what we saw on that on that site we have our class which is called rce but it doesn't doesn't matter we have our reduce function which will call this callable object and it'll pass in then the parameters so in this case we're using os.get environment to get this environment variable a flag and then we're simply returning that and then right here we're pickling it with base64 encoding it in a url safe manner and then printing it out so if i go back here and run python exploit.py it's going to give us a cookie value so let's go and have a look on our local server first of all if we replace the cookie and then hit f5 do we get a flag and it looks like we do so if we go back to the server and test the same thing out let's replace the cookie and refresh the page and we also get a flag although notice that each time we refresh the page the ordering of this flag is different so it would be quite a difficult task to try and work out what order these characters should actually go in luckily we don't need to so if we go to f12 and go to our inspector let's go and have a look at the contents here and we'll see that actually it's in the right order if we have a look at our divs here so we could go through and we could we could grab each of these values or we could do that with some javascript so if we save for divs is equal to document dots gets elements by tag name we want to grab there was no name specified we want to grab all divs and now if we let's set up a flag variable as well i'll just set this to be to be empty and then we'll say for for i equals zero i less than divs dot length i plus plus i'm going to loop through and we're gonna say flag is plus equals divs eyes whichever element we're looping through the inner text and there we have our flag so we could also print that out we could use alert as well and there you can see we have our flag we can go and submit that so that's a pickle challenge done let's have a look at the sea of quills the second challenge is called sea of quills and the description says come check out our finest selection of quills and then we have a ruby file as well to download so let's open up the link to the site we've already got the ruby file downloaded as well i'll open that up let's just go and test the site out first of all though so we have a list of different quills available here we could have a quick look at the source it's interesting to notice this comment here sometimes a car runs away and does not come back ever i i thought maybe this had something to do with the challenge so if we google this this is the this is the site that it brings back hi there i'm kevin the mastermind java html and css technician behind the scenes of this project this website was fully developed created in less than 48 hours um yeah this is the only reference i could find to this which i thought was kind of funny it's not loading properly on on here but it loaded it loaded okay outside my vm but anyway um it's not related to the challenge so let's move on we this is our homepage not really too much there for us let's go to explore and we go to this quills uri where we can enter in an amount and starting from so amount let's just say one starting from one we search that and it brings back one quill so now if we would say two starting from one it's gonna bring back two quills if we say two starting from two i guess it's just bringing back some different quills okay so we could play around with some of these parameters see if we're able to enter something and notice that whenever we put in an apostrophe that says bad no quills for you and we could also go and have a look in burp suite as well and see what's being sent and received so whenever this post is going off send in our limit our offset and then columns as well so if we want to url decode some of this we can do ctrl shift and u just to make it a bit clearer to read so we have our offset which we've just passed in there as the apostrophe we've done the same with the amounts i guess and then columns is passing in the url at the moment so actually let's go back and change this let's change this from urls to something else let me first of all just go and put in here we'll well we'll say i'll just put in a thousand starting from one we search that allows us to search it okay let's go and [Music] send this to the repeater and if we send this to the repeater let me just send that off we get our results here but because this is set to url and it's it's assigning these urls here what happens if we go back here and say bring back name and notice now that instead of the image source pointing to a url it points to what was what we were seeing here is the description previously so presumably if we put in a column here which doesn't exist let's try flag we get back an internal server error so we could go through and try and find out exactly what some of these columns are can we just we can just return them all there but as soon as we have access to the source code we don't need to blindly test this let's go and take a look at the code and the first thing we see here is that whenever the home page is loaded it's going to open the quills database it's going to select all from quills so let's go back to the home page and so it's selecting all of the items from quills and then it's printing them to the screen if we post to quills which was the explore option then it's sending off it grabs the columns it grabs the limit and it grabs the offset and these are the post parameters which it takes them from and then it has a black list here of certain characters and it's going to go through each one of these characters in the columns so the columns field was where we changed the url and the name let's go back there to burp suite so the columns is right here so if we go and say put in a apostrophe you'll see that we get beep boop sqli detected so we could look for some ways to bypass this there might be characters which are allowed which have been missed or you can use unicode sometimes to um to bypass these filters so for example actually let me go to url and a url encoder and we'll try and decode if i paste in this value here decode this is the unicode url encoded unicode value for an apostrophe so if we go back and minimize this we send that off again instead of sending an apostrophe we send in that url encoded unicode value we get internal server error so it didn't trip off this this blacklist but we still had some problems there it still returned an error so we could look at the other parameters notice that the columns was being checked for these blacklisted characters but the limit and the offset aren't being tested so this is the actual sql statement which has been executed select and then whatever we passed in as the columns will be entered here so say url select url from quills limits and then we could say limit a thousand offset one and the limit and the offset there are also some checks here notice that whenever we tried to put in an apostrophe to begin with we've got that bad no quills for you so this looks to be secure as far as i can tell it's it's ensuring that it starts with zero to nine and it ends with zero to nine and that's all that's allowed in between so anything else we enter is going to return that bad no quills for you so i spent quite a while actually longer than i should have spent um trying to play around with the encoding to try and get some union statements and things working here without properly focusing on what the actual sql statement is doing i also tried i figured if we could um encode the comment so we could encode the dash character a hyphen character and then we could say select all from the sqlite master table to try and find out what table names exist and then just comment out the rest of the code i also tried then commenting out the rest but also in certain these percentage s to deal with these other parameters none of that seemed to work for me so the solution that i eventually came to was to insert a union statement without any characters or we don't actually need any characters so in this example we're taking in this select and then the string well what we could do is just insert as our string select let's say name from sqlite master but then we have the rest of this code which i was initially trying to comment out but instead we could just say well we'll also then union select name from quills so we're selecting name from sqlitemaster and we're union we're doing a union query with the name from quills and then the limit in the offset can just go ahead as normal so i'll take this out here i was just putting that in just to demonstrate what we're aiming to do and let's go back to our burp suite and in here we'll just go back to what we had so in columns instead of just saying we want to select name from quills we're going to say we want to select name from sqlites master and then we want to union with select name and it's just then going to take do the rest of the statement select a name from quills so we can url encode that let's just do control and u there and send that off and we get an internal server error let me see if i just take this out and that seems to have run okay this time so we can go and have a look and we'll see that we have some of our descriptions here in stock in stock as well the first thing we see is flag table so there's another table called flag table if we wanted to we could also show response in browser just grab a copy of this url and then open it up okay that didn't give us any better so we have this flag table because it's shown as the image source we still can't see it here but that's fine so let's close that so we know that we've got this flag table so now we want to do what we want to do is see if we can select from the flag table so let's select name from flag table and if we try to send that off we get a server error let's try and select all from flag table oh we want to change our offset probably as well there we go okay so offset was set one so it was trying to grab whatever was in the flag table after the first element and the first element was our flag so we changed that now if we change that back to name that should be fine as well oh no okay it still needs to be we could have a look at what the actual column names are maybe it's just flag yeah okay so it's the flag column of the flag table and that gets our flag back so we can go and just take a copy of it and take that to submit and that's the save quills challenge solved so next challenge is nom nom nom but considering that spoofy has the most solves i'm going to deal with that one next because the competition is ending soon but hopefully we'll get chance to at least have a look at the next sea of quills challenge after that which will step up the sql injection so if we open the spoofy challenge says clam decided to switch from rebel.it to an actual host and service like heroku in a typical clan fashion he left the back door in unfortunately for him he should have stayed with replied it so we're going to have a look at this back door we also had some source code that we could download there but i already have that downloaded so let's open that up app.py so just before we dig into the source code let's go back to the site so it loaded up said i don't trust you we could have a look to see if there are any cookies or anything which doesn't seem like there are so if we have a look in burp suite we can see the get request that was made and nothing notable here we get a 401 unauthorized i don't trust you so we'll send this to the repeater because we might want to play around with it later but for now let's go and have a look at the code and see what's going on so we can see them whenever the main page loads it's looking for the x forwarded for header in the request headers and we have a comment here as well saying some people say first ip in the list some people say last i don't know who to believe so just believe both and then we have a link to a stack overflow question so we can go and take a look at that let's have a look through the rest of the code though so it's gonna create an ips list based on the parameter that we provide in for the x4 header uh it'll be split in that on comma space and if there aren't any ips in that list it's going to just say how is it possible not to have any ips if otherwise it will check to see if the zero earth element equals the element at minus one and if it doesn't it'll say the first and last ips disagree so i'm not going to serve this request and finally if we get past those checks then it'll check to see if the ip is equal to 1.3.3.7 and if it is we'll get our flag here which is defined as an environment variable if not then it'll say i don't trust you so if it's not if it's not equal to 1.3.3.7 it's gonna say i don't trust you that's the message that we we're currently getting but whenever we go and try to assign this to 1.3.3.7 we have to be aware that it's comparing to make sure the this zeroth element is equal to the minus one element now obviously lists start at zero in python so this doesn't really make any sense we need to go and see how we can potentially trick this into comparing the right ips so let's go and have a look at the article first of all and it's quite a it's quite a long article actually a quite a long question and answer section but essentially somebody is asking whether they can use the x4 4 header and take the ip but they're saying that it's not safe because uh if it contains more than one value they could take the first but then somebody could manipulate the value so um you have some responses here people explaining how it works and how this i'm giving some examples here of providing multiple ips in the exported four header but essentially in in this part of the question which is explaining it quite well it explains that if this gets if a request gets forwarded say to between a couple of proxies and ips get added on then the final destination for example in this case google won't know which of those ips are real and which are forged um so some good explanations here there's no point me sitting and reading through reading that out to you on screen we want to get this challenge solved so let's go and play around with it we'll go back to the burp repeater and let's add in the exported four header so i'll add it in here x forwarded four let's try and put in one point three point three point seven we send that off and we get the first and the last eyepiece disagree so i'm just not gonna serve this request so we can try that again 1.3 1.3.3.7 so now we're passing in a list we know that this is going to split based on the comma space so this is going to give it two ips so we'll hit send again and we get the disagree so in this kind of case we might want to go and set this up locally and test this out and see exactly you know use some login see what's going on behind the scenes where's my burp sweet gun but i did already solve this challenge so let me just go ahead and without taking up too much time see how we can solve it so in this case it's checking if ip0 is equal to ip minus 1. so in this case we have ip0 whenever the split occurs it's going to be ip0 and then it's going to be ip1 so that comparison isn't going to match but if we go ahead and set up another x4 to 4 header let's try and set that up and send that you see we still get the ips disagree not going to serve this request what if we add this another 1.3.37 so now both of these exported headers both equal the same values so if it receives two of those then we get our flag back hello elite hacksaw here's the flag spoofing is quite spiffy so we can go take that and submit it and we solve that challenge the final web challenge we'll be taking a look at is sea of quills 2 so the competition is actually over already but these files are still available to download and actually the servers still seem to be up and running to test remotely as well now i'm assuming the servers will go down but hopefully the files will stay up because i can see that looking at previous years we go and have a look at the 2019 ctf and have a look in the challenges section although the services are down we can still go and download binaries so for example right here we can download that i like it and we can still do the reverse engineering challenges even some of the web challenges sometimes they have docker files or source code available so you might be able to do some of the previous challenges locally as well but for now the services still seem to be up and running so let's go and solve the sea of quills 2 challenge so the description here says a little bird told me my original quill store was vulnerable to illegal hacking i fixed my store now though and it should be now impossible to hack so we can go and open up the site we've also got the source code available to us and let's go and let's go and take a look at the site first of all so it looks very similar to the first site that we dealt with let's go to the explore section and everything's looking quite similar so we can put in here an amount let's put in a thousand starting from i'll put in zero this was the offset on the last example that we went through and then if we go into burp suite and have a look at our post request we'll send this to the repeater and yeah this is very similar to so in our last example let's actually let's open up the code and try and compare this to the sea of quills one challenge so in sea of quills one we had a blacklist and we had all of these characters blacklist as well but we didn't have flag blacklisted and also we had this regex around the limit and the offset parameters but we didn't have this column's length uh greater than 24 so essentially whatever we enter in our columns field here needs to be less than 25 characters long and it can't contain the word flag either so in our last example we were able to inject in here so instead of saying select say all star from quills we were able to say select name from sqlite master union select name from quills so let me just give an example of that again actually i'll copy this over from our previous example let me just create a new row here to visualize this so this is our original sql statement but if we without even needing to inject any quotes or anything like that we could simply ensure that this string in a string placeholder we can enter select name from sqlitemaster union select name from quills limit offset and that worked fine for us on the last example so let's go and test that out first of all on the remote server and see what's different so if we replace our columns field instead of saying we want to retrieve the url we're going to say we want to retrieve name from sqlite mastered union select name we'll do control and u to url encoder and send that off and we get back bad no quills for you so it hasn't got to the beat boop sqli detected because we haven't entered any of these characters we haven't entered flag but it's got down here to the bad no quills for you because it's greater than 25 characters so we know from the first challenge that we were grabbing a flag so selecting flag from flag table and then we would would that's how we eventually got the flag we we grabbed the table names from the sqlite master table and then we found out the the name that we needed to look for so if we if we send that off we're now going to get boop sqli detected but we know that sqlite doesn't um have case sensitive table names and column names so we could just go and change these flag strings to capitals and send that off and that works out fine but we're still over the character limit so i spent a little bit of time trying to solve this by injecting comments to the ends so rather than having our union there if we were able to just uh insert our comments but obviously the this is this is blocked so we're not gonna be able to send that off so i was trying to do various types of encoding unicode and hex encoding things to try and get that working and i didn't actually get it working but it's quite annoying because in the first challenge while trying to solve that i tested out using a null byte and then i never actually tested it out when i got to the second challenge but if we send that off with a null byte at the end you'll see that we get back our flag right here we can open this up if we want to in the browser if we copy that it won't actually show because it's the image source but if we inspect the element here and see the image and it's tried to load the image from and then that's our flag so that was the sea of quills challenge two anyway and that'll wrap it up for this video i might go through and solve some of the some more of the challenges maybe have a look at crypto and miss categories and some more of the reverse engineering and binary exploitation challenges so yeah if people want to see more of these um video walkthroughs then let me know what you're interested in seeing in the description uh sorry in the comments and uh i'll try and and take act on some feedback anyway i hope you've enjoyed the video if you have then drop a like and any questions comments leave them down below thanks
Info
Channel: CryptoCat
Views: 2,749
Rating: undefined out of 5
Keywords: ångstrom, angstrom, ångstromCTF, ctf, capture the flag, hacking, wargames, web, sqli, sql injection, pickle, cpickle, deserialization, serialization, vulnerability, exploit, burp suite, devtools, pentesting, pen-test, oscp, web proxy, web security, http header injection, http headers, x-forwarded-for, header spoofing, spoofy, sea of quills, jar, pickletools, sqlmap, cyber-security, infosec, challenges, owasp, owasp top 10, vulns, tutorial, sanitize inputs, bug bounty, bughunting, websec, python, ruby, javascript, sql
Id: c147fBCppb8
Channel Id: undefined
Length: 36min 4sec (2164 seconds)
Published: Sat Apr 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.