HackTheBox - Bookworm

IppSec · Beginner ·🔧 Backend Engineering ·2y ago

Key Takeaways

The video demonstrates a cybersecurity attack on the Bookworm box, utilizing tools such as nmap, burp, and Python to exploit vulnerabilities including cross-site scripting (XSS) and insecure direct object reference (IDOR), and ultimately gaining access to the system.

Full Transcript

what's going on YouTube this is IPC I'm doing Bookworm from hack the box which starts off with a insane cross state scripting payload but don't let that like scare you away from this video I think by the end of um that portion you'll appreciate JavaScript a lot more and learn a lot of things because when I did cross a scripting in the past I always used XML HTTP request in a quote unquote incorrect way because it made sense to me in this one I had trouble using that just because my code was a mess so I tried to use fetch my code became a mess so I tried to use fetch with await statements in async and I couldn't keep track of my variable names so I started creating helpful functions and by the end of the day like I became pretty good at doing this type of exploitation and I think you will be too if you watch it after that the Box does get a little bit easier the next step is abusing a Sim link to exploit something but really let's just get into it because this is going to be a fun one as always we're going to start off with an end map so- SC for default scripts SV enumerate versions OA output all formats in the nmap directory and call it Bookworm then the IP address of 1010 111215 this can take some time to run so I've already ran it looking at the results we have just two ports open the first one being SSH on Port 22 and its Banner tells us it's in auntu server we also have HTTP on Port 80 its Banner tells us its engine X also running on Ubuntu and also redirecting everything to Bookworm htb so let's go ahead and add this to our host file so V ety host and then we can add 10 10 11 to 15 Bookworm htb and check out the page so let's go HTTP Bookworm htb uh we probably want to turn burp Su intercept off uh let's go over here proxy intercept there we go and it looks like we have a online bookstore so I'm going to check check out the shop and looking at this it looks like there are a bunch of books we can try to view a book and if we add it to our basket which I guess is the same as a cart uh it wants us to log in and at this point I'm going to turn intercept back on and I just want to um intercept the response to something so I'm going to try admin first so we'll do admin admin but the main thing I'm looking for is the headers so we can see X by Express so we know this is nodejs let's just for this request and it just says invalid username or a password so let's go ahead and add an account and since this is Express I would probably try for like no SQL injection as well on the login form just because the mean stack is so common um I want to say mean stands for um Express angular and node but I could be wrong there um so let's just put a bunch of junk I'm doing um username and name as IPC password as password and then 1 two three in every other field so it let us create the account we can log in with IPC and password and now we're going to be able to test our cart and we can also see this recent update thing it does work we can see Joe bubbler added the yawning party to their basket so if we add this we can see we also added something to the basket so since we have a thing right here I definitely want to check for like cross- site scripting so I'm going to do a u so this is going to underline my name if it exists right I was going to do bold but it looked like my name was already bolded in that so there we go I put a uipsc and we see the um actual HTML so this is not going to be any cross- site script if we attempt to view the book uh let's add it to the basket go over to a basket and see what else there is there is a note here saying as a result we're no longer offering free ebook downloads of purchased books don't fret all previous orders that were made during a moving period will still be downloadable we hope you enjoy the new 4our guarantee so what this tells me is we have have users we know there's some type of simulation going because we see a user adding stuff to the basket we also see there is a download functionality however it's only on Old orders so this is telling me somehow we have to get to a existing users profile examine the previous orders and see if we can find out how to download ebooks because when there's a file download maybe there's a file disclosure vulnerability that is just a super good guess at this point right so let's try editing a note of this so the note um let's intercept and we add this let's just do test so it just gets added there and if I looked at that I should have tooken a more second we can see it adds to basket the basket ID which is 359 in this case I'm guessing this is just an incremental number and then edit and it adds quantity and then the note so now if I click this again we have the note here so let's try doing some JavaScript here so we'll do script um alert one SL script and then we can update the note I think my burp site okay it is no longer on intercept so we now have JavaScript it doesn't look like it's loading on this page even if I refresh um let's press f2 or was it F12 and it did not load but there is a warning here it says this page of settings or blocked the loading of a resource in line script source so it means we can't load any JavaScript off the existing page we see it again it's blocked so I think that means our JavaScript did run however well it did exist but because it content security policy was blocking it on itself it did not run if I go to The Source Let's see we can see it is here and there is no like HTML ndn coding around the special characters so this definitely is somewhat vulnerable we just can't execute it on itself so what that means is we have to find a way to create like xss somewhere else we could probably try it on our own box let's see uh let's look at it we have content security policy here let's let's try that so I'm going to do nvn p 8000 and let's just see if we can make it called back to us so I'm going to redo this whole process of adding a book to a basket then we're going to do a new cross-site scripting payload so we can edit note we can say script source is equal to http 10 1048 Port 8,000 uh it I guess we'll do pone doesn't really matter what the file name is and then we can do SL script update the Note complete the checkout and let's see it does not look like it loaded off a um different website it says loading failed script with Source http 101048 slone so I'm not sure exactly what is stopping this it's probably some type of browser type security so we can't load it off an external resource let's just keep poking at the website so I'm going to go to uh let's shop see if there's anything else we can edit does not look like it we can click his book and it just brings us to the book we do have a avatar so let's try updating our Avatar and see if we can put a file there so I'm going to locate every file that be ends in JPEG and then we're just going to copy a random one here actually we probably don't need to do that um let's just touch or Echo please subscribe to T t. jpeg whoops T test. jpeg so let's browse htb then we want Bookworm test go over to browser I am going to intercept this request so we can see the MIM type is image JPEG so it is uploading has it I'm going to try just uploading this it's redirected us which I think is good um let's see let's turn intercept off and then we got to figure out how to load a profile we have a broken link where the profile was so if I open image a new tab it goes to download so let's just curl this and and we can see we can write a file the whole reason I'm not trying to um use like a PHP webshell is because this is an Express website right it's very hard to just get code execution there if this was in um debug mode it would be potential to be like overwrite a JS file and get it to reload so we can also test for directory traversal so let's see if we uploaded something to image we did not so I don't think it is vulnerable to directory traversal the other reason I'm not trying that that much is because we don't have control over the file name we uploaded test. JPEG and it uploaded as 14 so either that's our user ID or maybe that's just the 14th Avatar that could be an incremental number so that's why I'm not trying a bunch of just directory traversal type of attacks because again we also don't control the file name but we could insert JavaScript here so we can do script we don't want to do that we just want to do alert one okay so now when I go here we have alert one so what I want to do is edit my basket to have that JavaScript to load that so let's go back to the shop go to view book we have a different user there go to add basket add this and then what I want to do is say script source is equal to and I'm going to grab the SL static up image uploads 14 and then we can end the script update the Note oh I clicked edit again didn't I update it and then when I click complete checkout we have a JavaScript or alert box so we know this is going to be cross-site scriptable the thing we have to figure out is there an idore vulnerability in the basket itself because this doesn't really do us any good if we can't poison other people's items so the easiest way to test this is just to create another account and have another browser so I'm going to go back to book one. htb on a different browser we can log in we're going to create a new user I'm just going to say this is the victim same password of password and junk everywhere else so we can do victim password then I want [Music] to uh let's see I'm going to go to view book we can add it to the basket if I go to shop here we can see the victim added it but the issue right now is we don't have the basket ID we could try adding one to ourself and then we'd see like when we edit it and just know we go up one but I'm going to look in the source to see if there is any indication maybe like the link is added but we do have a comment here so 369 um this probably means basket ID 369 because we have 367 down here I'm guessing I was 368 I don't know what 368 is but I'm guessing that was me and then I checked out and it dis appeared from this list that's the best I can guess right now so we have 369 so let's go add something to our basket it'll probably be basket 370 right and we want to edit the note go over to burp intercept and then we're going to do the same thing script source is equal to our JavaScript payload we are in intercepting so click Update note we're going to send this to repeater and what basket ID was it uh I think we said 369 because this is 370 so let's just try 36 whoops okay num lock was not on I started hitting 369 and it did not do what I expected to so I'm going to edit this and we can um drop this packet I guess so if I go to my basket here click edit note we do have the JavaScript if I go to um whoops cannot get if we go here we have it as well I thought I dropped this request but I guess maybe I did not oh okay I just had to do a control shifter to refresh it so we don't have the basket here because we never sent it to 37 so there is an idor vulnerability so if we completed this checkout we have the JavaScript so we have a way to now infect other users baskets the issue is we're going to have to build a pretty complex cross-site scripting payload to do this because we want to um hit probably the profile page then look at the order history and then grab all these links and click through them because we want to get each of these Pages the reason why we want to get each of these pages is we want to see if there's a download link on any of them because that would give us a new endpoint to hit on this web application so I'm trying to think what we want to do do we want to start with cross-age scripting or start with uh python application to poison uh baskets I think a python application would be the best place to start right now so I'm going to do touch um we'll call it basket poison. py I guess and we're going to um want to have a script that essentially will crawl or hit this shop URL and it will look for any new basket it finds and it knows the basket ID because there is a comment uh there we go we have 371 so we want to look for this text and when we have a new number then we know we can poison this um basket so let's start this python script so let's go to visual studio go to basket poison and the first thing we're going to want to do is import request because of course we have to make a python request and I'm going to do something a little bit odd because um in Python I don't really know how to pass point ERS and like there's a bu of just magic go on with variables to me um I want to explain it Qui and hopefully this makes sense so what I want to do is have a python session so we can say session is equal to request. session and I want to do this so I can log in so we can say um session dot was it probably post and let's just pretend this is a login it's not going to work because uh maybe that would no Local Host 5,000 definitely not we'd have to put like uh Bookworm htb I'm guessing the endpoint is that and probably username of IPC and password of password I'm guessing that works so then I'd want to create different functions to do things so I'd want to do like uh Define get uh latest bucket and have like pass in the session but I don't like returning session every time right if I was in um C or goang or probably a lot of other languages I would pass in the session as a pointer and then when we call the function we do it so we just pass the pointer in so it updates we don't have to worry about a return um so whenever I want to do something like that where I just want to update a variable without returning the variable exactly I always use classes in Python um maybe my whole explanation just confused you more um let's not call this exploit let's call this um basket poisoner so we can create variables on this object so we're going to say self um we can give it a base URL and then we set it up like that so now we can just create this um object so I'm trying to think of what I want to call this um I know this is probably a bad name I'm going to call it sess for session but it probably shouldn't be that and I'm going to put the URL up here so we have it as a variable just say this okay and then we want to create a function here let's call it login self username password and that looks good okay so we can say ss. login ipac password uh there we go and now if I do cess dot uh session git URL plus shop and we can say R is equal to this then print r. text so let's just see if this works um yeah that should be fine so I'm going to do Python 3 and we called it basket poisoner we have this I want to make sure IPC is on this page uh let's just search up for IPC okay so SL profile is pointing us to ipac so we know we logged in so we have a working um thing instead of sash I'll call this BP or we'll call it yeah we'll do BP for basket poisoner that s stop session is confusing me so there we go um now what we want to do is be able to get the latest bucket so I'm going to call another function we can say get latest bucket and we're going to Loop this because there's a chance when we hit the page there are no um request in the shop right so when we don't have that I'm just going to have it sleep and retry so we'll say session get that looks fine and we don't want to go in the cookies that is co-pilot doing things we don't want to we're going to use a regular expression so I'm going to call I keep saying bucket it's basket right there we go so we can say basket is equal to regular expression find all and we want to import our e okay and we want to create a regular expression to find this so that was a common so we'll do this and then we want to grab all digits so we can do that like this we'll put this in a parentheses and I think think that should be fine oh we have to say r. text the actual HTML and then we can say if the length of basket is greater than zero we can return basket Z so return the first match and otherwise we can say basket not found sleeping 5 seconds and we can do time. sleep and then we also have to say import time okay so let's say basket is equal to this and then print basket so if I run the script now let's see what happens we get 377 that is awesome so we all already have it grabbing the um latest basket if I just refresh this page if we'll probably have 377 right at the top so it looks like this is working the next thing we have to do is Poison the basket so I'm going to do um it's almost like it heard me so I'm going to call poison basket and let's see the code it's giving me is not good here so we want to say um the URL is going to be the base URL and then what was it it was like edit right so let's go back to burp Suite intercept we have basket 369 edit so I'll just make this a F string and we can say basket basket ID edit there we go the data we want to poison with is going to be this so we can copy this and let's see we'll just paste you can say Quantity one note I'll do this in a single quote because we already have a double quote in our xss payload right so we have the URL and data that looks good and let's see that should be fine so what we have to do here is identify if we have a um new basket so I'm going to do another infinite Loop so we'll do while true and then we're going to say new basket is equal to this and then we'll say if new basket does not equal basket then we found a new basket we will want to poison it and oh I already hardcoded the payload that would be fine so we will poison it and then set new basket equal to or set basket equal to new basket and it'll go back through this Loop so if it attempts to run again and it's um not a new basket then we won't poison it because we won't hit this okay uh we probably want to say poison basket and then we can say which basket we poisoned that should be fine I'm just going to do new basket so we stay good or maybe we should put that in here we probably should do some type of like try catch statement around um this so like to do try catch to verify it's poisoned um but I'm not going to do any of that type of error handling in the script so let's see what else do we have we did this so I guess the next thing we just want to do is sleep so we'll do time sleep for 2 seconds so let's see what happens when we run this so when we run it we don't have anything it's sleeping how long do we sleep 5 seconds so I'm guessing it did not have anything I bet if we refresh this page look for this payload we have 380 so I guess if we added a another thing to this when it gets to 381 that's when we see output right so I'm just going to do it myself we view book uh book add to basket we go here go back to our payload and we have a error U missing schema invalid URL uh let's check this out which line is this it's probably the poisoner right uh let's see line 40 poison basket poison URL oh we need to do um self. Bas URL there we go rerun this and let's see let's add something else to a basket you book oh that's going to be the same thing because we already have that in our basket we'll do the little mixer this time add to basket okay we go here we poison basket through 383 I'm going to guess that is this if we edit the note here we already have the payload so if I completed the checkout we have the um cross a scripting thing so now we have to build the um xss payload because we have the poisoner working so I'm going to create a new file we'll call this payload JS and this part is not going to be fun but at least it's going to be epic and we're going to spend a little bit more time showing like a payload evolve instead of just going straight away to do it the way I think is elegant and it should be mentioned I think this box was blooded in like an hour this piece of the Box took me probably the better part of a day and I'm saying like six to seven hours mainly because I hate JavaScript but I started learning a lot about JavaScript doing this box um we want to use the Fetch and this is going to download a page and we're going to do it a somewhat bad way but the way I see most guides doing it online so we want to fetch profile and then we'll say the mode is going to be we want to disable cores we want to um whoops include credentials so if we do include credentials it's going to um include or session cookie with this request um the actual like um cookie is um HTTP only so we can't steal the cookie so we have to like use JavaScript to control their browser so we'll do cach is equal to no store and we want to close that so if we do this we have to create all these nasty um then and because it's like async in this fetch module we have to like grab the text like this and then we do another then we can um grab the response text and then we can um do something else so what we want to do is I'll just print it now we'll do console log um response text and we'll get to make several requests so if we did that this payload is just going to get massive uh is it like that there we go let's try this this so if you want to test it the best way is just your um console window right developer tools so this does work but again I think this if you imagine we're going to have to probably get three URLs by the end of the day so you can to have so many thens like it's just going to get crazy and unmanageable right so I evolved or I started using async with my fetch so we could do like a const we'll say profile is equal to a weight Fetch and what a weight does when you call something that's async it's going to wait for it to finish that's why we have to use these thens because we don't have it in a wait call so we have to wait for this to finish then we can get response text then we go here then we can do something if we didn't do that then like all the ordering would go out of whack and um it just would not work it's hard to explain other than it won't work or it didn't work for me so we can do that then we also have to grab the text for it so we can do await profile. text and then we can just do console log so this also works right so if I do this we can do it and we get the profile this gets a little bit messy because I hate having to do two variables every time I want to pull a page so because of that I used uh a function so we can then um create a async function then get page and we pass it the URL and let's see I'm just going to copy this okay so we can fetch URL I'm going to call this request reest we'll call this response and we can return response so I can just do now um profile we'll just call it profile is equal to um await get page SL profile and we do this and we can copy this entire function over here and body has already let's refresh it we get our JavaScript uh profile is not defined oh we have to call cons profile there we go we could probably also use letter something but whoops let's copy and we have to specify the URL uh HTP let's put put that in this we'll say um HTTP Bookworm htb plus URL there we go uh we'll call this page you can replace URL with page there we go I'm just going to go to the shop page so I don't trigger my xss again we send them uh profile is undefined oh it's request redirect oh my God this is going to be more painful than I thought okay um it was just because I did not refresh so I had a variable but now we can get this so what we want to do is grab all the orders on a profile because we want to get those pages so what we can do here is um instead of just logging the profile we can say um const we'll call this I'll just do re for reg X so re orders is equal to um what is it we want to get order then a digit plus we want to get all of them and I'm going to put it in in parentheses so now what we want to do is test if it is a on this page in regular expressions in JavaScript is weird or maybe I do it a bad way so we're going to test profile okay and let's see we want to say while and we're going to call this um order IDs is equal to re e orders. exam profile null like that what are you ering on okay it's not so let's just do console.log order IDs and if we do zero it's going to show us the full string if we do one it's going to show us just the order ID so let's prove this real quick B this get page is not defined because I did not copy everything paste this uh did not work let's see what's profile we have that okay paste this oh we have order ID 139 okay so we have order ID 139 we only have one I'm going to complete another order so we have multiple orders I want to make sure that's working add to basket complete checkout yeah we have that xss oh we did have multiple order IDs we have 130 131 13 three so we're screwing something up here let's see go here paste this we have it undefined I don't know why it's undefined we waited there we have that we test I think I have an error somewhere okay it's a pulling everything thing so I think things are working it's weird that I have to call this separately which leads me to believe we have some type of async IO bug because I think it's testing the profile before this finishes which doesn't make sense because we did await it so do I have to put a semicolon here I doubt that I didn't do a semicolon there is this the problem do we have to do maybe that's it undefined weird um rype profile it definitely exists so we'll continue and debug it if it doesn't work at the end so we have all the order so what we want to do is get the page here so oh we could also show let's see so if we just copy this we have all the order IDs we could say order IDs one and if we do the same while loop it's only going to print the numbers so let's see we can say order URL is equal to um order IDs zero and then let order ID is equal to one console log I just want to make sure the let is working here Order URL order ID okay so that works so now let's download all those pages so we're going to say const order equals await get page slash order and then we want the order ID I believe right is that where it's linking us to if we go to our profile view order order 130 so that's what we want so we have this and what we want to do with this is eventually um send it to us so let's do a new function and I'm going to say uh we'll call it P data I guess try and be it's really xfill I guess we'll say XL data or now we'll just do post post data and this will be URL to make it easy on replacing who we send it to if like my IP ever changed so we do this request we have a fetch this is going to us this is going to go to our IP so we don't need to send credentials we will have to change the method to a post and then we want to say the body is going to be the data okay so we do a weight fetch uh I guess we can we don't need the response we can just return I think that'll be fine okay so let's now say await post data HTTP 1010 148 P 8,000 and we're going to give it the order and I'm going to say um order ID okay so I think we're going to send data now so if I copy this and we listen on Port 8,000 then we go back to our browser uh F12 we have to copy everything I really don't like that I'm having to do this separate uh a weight is only async generate what line is that we did a wait get page a wait post data is do I not a wait there uncaught syntax eval code 622 we get rid of this 22 it's going at the end of this I honestly don't know how to debug this we have a profile we do we can test the profile with a regular expression true so we go into this Loop um order ID is not defined let's see while n async do we have to return request let's just do what we did here we'll do response and return like that oh wait I'm really curious why because we have asnc function post data I may pause the video and play with this because I am getting confused so if we don't do that does this now error is it this code that doesn't look right it is that const order await get page we called get page here nothing hit us if I put this in my Loop we just going to get our profile constantly which is fine because we're redeclaring it let's do order huh doesn't like us using a weight in this Loop let's move this I guess async function um we'll call it poison and we'll move this entire thing into this and then we can call poison we'll uncomment this we'll just paste everything here get page is not defined because I did not copy it prom is pending we did not hit something really odd is going on we only use order ID once so I didn't reuse that this isn't go so just because I declared this and didn't use it that still should be fine I'm going to put these as constants I really don't think that's it but maybe it is promise pending so one URL is not coming back but we're not getting a hit here so it's not getting to my post we don't even have that proxy is off but let's turn it on poison I should see something in burp Suite I do we got the profile then we're going to get a order ID get another order ID another order ID and done fulfilled okay so I think it's working when we put in the function I'm stupidly not doing a log and we're not sending the data um so const uh we will say we'll just do await post data we'll try this again 10 10 148 8,000 then plus order ID order spell a weit correctly I can just do contr a intercept is off promise is pending oh pending because we sent it awesome so now it's working um I think moving this to a function somehow helped I'm not positive but we're just going to go with that explanation so now we have the post data so we get um a response to us so the next step is we want to download everything so I'm going to create we'll call it server.py and I'm going to do from flask import flask request and we can say app is equal to flask name app route and we're going to create a order then we'll say um ID like that wonder if I does it want me to do it this way we can try this that's probably more secure so it gets defined as a integer right so we can do methods is equal to post like that I'm missing something no I'm not so we can do Def and what we want to do is save this file so I'll do with open F orders then ID dot we'll call it HTML and we'll write it as a file we'll write the request it's not a form we'll just do request. dat. dcode and then return okay okay and we can say app. run host is equal to all IPS p is equal to 8,000 okay go into code let's do Python 3 server.py and then I'm going to copy my payload uh it's this one go back to a browser paste we're sending it and we're getting 404s because we just add um the order ID after the URL so what I want to do is edit my payload and say order slash internal server error because we don't have a directory orders run it and we have saved a few request right least I assume we saved let's go CD code orders and then we last 131 HTML we can see this is our order so what we want to do now is update the um our Avatar which is where we're poisoning buckets to to be this payload so let's copy this entire thing go back to burp Suite go to repeater this is our profile Avatar where we just have the alert one I'm going to put this entire JavaScript so we're going to send this so now if I went to one of my pages so let's save this I'm going to let's clear the screen let's just go to my profile I'm going to go to an order I'm assuming I poison this order and our browser sent us all this data so what I want to do is just wait probably 5 minutes because we're going to have users that we assume because of the activity feed here or shopping we can see we poisoned two baskets um that's probably these two um if I control U like this uh let's see uploads for so this is that user um if it was us then we'd see was it 14 was that our bucket ID uh profile Avatar I'm pretty sure we were 14 I don't think I have it here but I think we were 14 so we know we poison this guy's bucket so we want to do is wait for him to check out which it'll probably take about 5 minutes um we have 409 there let's see I think I want to put the time stamp here because I'm going to pause the video and speed up right so I want you to see how long this can take because this is one of the more painful Parts is waiting here so let's see um where do we print I'm going to disable this so I don't it doesn't flood the screen and then let's see get current time now okay let's do we'll make this an F string now poisoned basket new basket there we go rerun this so hopefully it is a bit more verbose when we do times so we'll add this added uh that is not what I want um let's see oh we sent a bunch of orders so maybe I don't have to pause the video Let's just look at the orders we have so I'm going to go to orders or it was code orders uh we can either less it if we less 11. HTML we can see at the very bottom we have two links and this is going to be one of the hard Parts there is a uh file disclosure vulnerability but it's when send multiple book IDs it's only in the download everything and I'll go over it in a couple minutes on why this is but instead of just blindly trying this one and failing I figured I'm just going to go quickly and we'll only do um this one so we want to be able to download everything I'm going to put a file in the second book IDs so typically whenever you can download something I always try um putting a file so we're going to try that but first we have to grab this URL so we're going to go back to our payload or before I do that I'm going to um GP book IDs on 11. HTML and it looks like if I make a regx that just grabs digit question mark book IDs and then this and it'll only grab the download everything link and then I'm going to fill out the second book IDs with the Etsy passwd um that makes most sense and if you wanted to you could also Firefox 11 HTML and open it up to see kind of what it looks like so let's go back to our payload and what we want to do we can um send the data but after we send the data we want to do a second regular expression so I'm going to do const Reg X or we'll do re and what is it I want um we'll call this download everything is equal to and then we want to what start with a digit so we'll do back SL D plus and then we want to escape a slash uh do we do this in Quotes no um so we escape the Slash then we can do wait we did 11 but we escape a question mark That's what I want to do we can say book IDs is equal to another digit and then we want to do camper sand like that what did this say this is a bit of heck but it works how did it know that's a good comment for this line that was one of the better things I've seen co-pilot do I'm going to leave that that is fun uh so we want to test if this regular expression works and then if download everything is there we will want to um get the data so we can say download everything is equal to r e download everything exec on the order and we want to grab the first item so the order this is going to be the HTML page um so that is 11. HTML right that's this so we're looking for to download everything so we have that link so we want to download it so we can say const download is equal to await get page and then we say download plus download everything plus and if we go back here we start at this and so I'm going to do book IDs is equal and we're going to do a bunch of do do slashes at pass WD I think that is good I'm hoping it is um and I'm going to do one slight thing I'm going to call this get page binary and we're going to create a new function called get page binary which is going to be the same thing except instead of returning text we return blob because we're deal dealing with the file not asky text I want to make sure we treat it the correct way um if you don't I think like your Zip's going to die in the middle or it will have extra data because it encoded something it shouldn't have and just all like hell will break loose so make sure when you download things you use the blob and then we want to post data to 10 10 14 8 8,000 and then I'll do xville plus order ID download uh we are missing something I did not end a quote probably here there we go and I think that is going to do it I don't know what it's complaining about this semicolon uh we missing a bracket there we go so what I'm going to do is paste this into our payload because again this can take five minutes and if I see a 404 on this I know it works um but let's now go back to server.py and we want to create a route for xfill so we can say app route we'll do X method post we got to change this so we do xville ID we'll make the directory [Music] xville I don't know the type of data it is we'll just call it dot we won't even do that we'll just do order ID and then we are decoding the data um again we're probably dealing with binary data so we're going to write binary and we're just going to do um request. dat and I think that should work if I make dur uh we go up one so we makeer xfill we run this server and I think we are good um it's kind of hard for us to test this though right let's see CD orders so the best way I think to test it let's do python 3-m HTTP server 801 and I think it's going to work but we're waiting on time right and you can't hack time so while we wait we might as well be productive and I'm going to test out her actual payload so if we go back to this payload JS we really want to just get this page AG we want to probably oh man I hate that I defined um this let's see I'm just going to copy paste rename debug get page 10 10 148 8,000 okay so let's put this in in my terminal so now that get page is defined to point towards us we can now get 11. HTML on 80001 and I called it 8000 it's really 80001 there we go okay go back here we can edit that I'm not using those now so what we want is to redo order so we'll do const order is equal to 11. HTML we have to do slash uh let's see read. because we made it constant um I'll call it debug I guess if I do debug we nothing we got it is debug a protected value uh ipac no we still just posting orders there and so we see 23 151 I'm guessing we have something broken because we did not get the post request on xfill so something is broke I don't know what though I wonder if this is some type of course thing if I do 10 10 14 8 or 80001 if we start off on this page F12 get page we defined it we on this tab there we go so now we have it we have a downloads everything link uh what do we call it debug so we want to Define this regular expression I see the error we have four it's D that's probably it I really should not be in the habit of calling everything constant everythingin will be with the slash D then we can test this test on debug it is true so we matched it that is good we got to change this back to everything thin and it's no longer order it is [Music] debug we have 11 question mark books ID that looks good so the next thing I want to do is print this line console.log and that looks good so I think once we fix that it's all good let's go back to our payload let's put a d there copy everything we have to go to burp Suite rep poison it go back here and I'm just going to let's see python print human timestamp I forget how to format that import time date time maybe that'll be good POS x g try this real quick this is not how I remember doing in the past but it may work so we can say time stamp is equal to this now import date time there we go do this Bookworm view book add the basket there we go we have somewhat of a good time stamp um so with that being said I'm going to pause the video and we're going to wait probably about 5 minutes so let's see sleep 300 I'll come back when this sleep is done and we'll see how many requests have been made and um if we have any actual xfill data we have not hit the five minutes yet it was probably I would say one to two and we see some X fills right we have xfill 11 so I'm going to check that out so if we go into our code directory go into xville do a file on 11 it is a zip archive so we can do 7zl 11 and we see it's got two files we got the pirate woman and unkknown so let's extract 11 and look at unknown. PDF and we have the past WD off the server so I'm going to move unknown to be called past WD um we going to remove star.pdf we don't need that one and let's see makeer um we'll go up to directories and say xfill I don't know what to call this so there we go I want to save every file we download and we're going to delete that and we want now to get a different file um and this also is going to be a bit like Nostradamus of me just knowing the file I want to grab it is a node thing right so there only like a few files we'd really want we could go um well the files we probably want our um let's see index.js database. JS app.js or something like that right we want to go into um those so I'm going to try proc self current workking directory and I'll do database. JS I would probably start with index and app but I don't want to wait all that time right so we'll start with those files and I think all we have to do is add that so if I now come up paste the payload okay we shouldn't even have to update anything it all should just automatically work because um we didn't change the basket poisoner that just sends them the Avatar URL this part didn't change the only part that changed was the Avatar URL and we just uploaded that right so I think that's going to work I'm trying to remember exactly how I did it um I saw this box yesterday and I'm just like recreating all the steps I took but I want to say that's how I did it so let's just leap for five minutes and hopefully I have some type of data in xfill so I'm going to pause the video now probably be back before 5 minutes but if not then that's why I know I need to start debugging because in reality it should not take longer than 5 minutes to get the data it's been probably about 30 seconds since I stopped recording and we did get an xill I probably should fix this condition where we just do it multiple times um there's no reason for us to send the file three times or do this three times I don't know where that bug is but I don't know if I want to fix it CU it seems to be working now right so we xill 14 if we do a file on 14 it's a zip so let's unzip 14 we could have also done 7zl there's really not much different right uh let's look at unknown. PDF and we got a file right we have the user Bookworm database Bookworm password Frank the job Giver so if we SSH Bookworm at Bookworm htb put in Frank the job Giver we don't log in right but we do have um the passwd file so I'm just going to move this over to xfi and we can call this um what was it database. piy .js so let's look at P WD and there is a Frank user if we wanted to we could just grab everything that ends in sh so we have root Frank Neil James since Frank is in the password I'm going to try to SSH as Frank and I may also like do crack map exact with a bunch of usernames and spray it if I had more than four I would probably go that route but um I like just taking a guess first and we log in as Frank and user. text is right there what's going on this is it from the future and before we go enumerating the box as Frank I want to take a step back and talk about something that I found interesting if we look at the orders and go to like order 11 I had mentioned that only this one was vulnerable the download everything that has two book IDs if you tried the one with just one book ID it wasn't vulnerable and the reason why I found is pretty interesting it's one of the things that node does pretty well on standard things and when you do multiple books you're doing a zip so I wouldn't really call that exactly standard how that works but um let's look at the code I'm already there we're defining book IDs we're just saying it's going to be request. query and then we say if the book IDs is a string we go down here so this is the single path all right we're going to do a res. download book IDs file name going to give it the path right well if you look at the zip it's very simple similar right we have this ZIP we have the book IDs um we're getting the file name and we need the file name here mainly because it's a zip file what do we put in it and then we have like the path. jooin command here that looks very similar to this path. join but it's extremely different because this one has root um this res. download supports this which kind of like jails it to that directory or makes a CH route I don't know a good way to explain it but you can't go outside of the directory so this is what's preventing the lfi on the single book ID is this makes it so we can't go out of the working directory SL books it is pretty cool so let's take a look at it I had created a simple application and by created I asked chat gbt give me a boiler plate and I finished it off right so we have two post parameters we have no root and with root and and on the no root I'm just doing file is equal to rec. body. file name and then we're going to download the file um with root what we're going to do is assign the file name just like we did before but this time we jail it to the dur name right so let's go play with this if I do python or not Python 3 wow um node index.js we're going to stand up our web server and then I'm going to do a curl Local Host Port 3000 uh let's start with no root and we'll specify the um post file uh post parameter file name and I'm going to give it please subscribe because I do have um please subscribe if we go in app web there is a Please Subscribe in this directory we have it right here and I part one up One Directory right right so with the no rout we should be able to read both of them so if we do please subscribe. text uh no such file or directory does it help if I can type correctly I'm guessing that was the problem because it's just please sub we get no really please subscribe to me right so let's try doing the directory traversal again there is um no root specified in this so I'm hoping it works right yeah it says thank you for subscribing awesome so what happens if we specify the root parameter right so this is the one that specifies we shouldn't be able to leave this directory so if we do please sub. text um cannot post to oh we called it with rot we get that message and then if we go dot dot slash we get an error message and this is a 500 message I want to say it's 500 let's do a-v so we can see uh 43 forbidden not 500 but it's just giving us the error that um we can't get out of that right I don't know exactly what that says I wonder if we can decode this quickly um let's go copy burp sweet decoder paste smart decode o we're getting there fimm test.html Firefox test.html it's probably not the best way to read this eror but hey it worked right you get the Forbidden you can see what that stack looks like but um I hope you guys kind of enjoyed that Beyond rout I really did enjoy um like this feature of nodejs I don't know I'm sure a lot of other languages have it but I normally see it in this this isn't the first time I had a a file disclosure vulnerability and a node application and couldn't do much with it just because they like locking you to directories which is a cool thing so um let's get back to enumerating the boxes for Inc so the very first thing I would do is check out my SQL right because we had the credentials for it and there could be um passwords in this so let's try going in I'm going to log in with the username Bookworm to The Bookworm database paste in the password which was Frank the job giver and then we're going to show tables and we can select star from users and let's see we got the name and password so I'm going to do select um name we'll do username as well and password from users and it looks like it's just hashed right um this is going to be password I bet if I Google this it'll come right up let's see it is md5 so these are all just MDS we could see if we could get any other um user and we'd also probably want to um let's see hold on let me look at this page first md5 hold on okay it says it up here um what was I going to say um we could go hashcat route but I don't feel like doing that um just send it all here I know none of these actually reverse so it's not going to be that beneficial maybe we can look at what the password is at the end of the day because the password's probably going to be in the like automation that's running but we don't have access to automation so we probably just want to save all these passwords store them because if they ever did crack or we got hits um it may be that user's password um who else was on this system if you do grap sh on Etsy pass WD uh is there a James I don't see James we have Frank there's no Neil so none of the users even line up maybe one of these is the root password but who knows right so the next thing I would look at is um listening ports to see what's on this box we have 300 and 3001 so I'm going to see what 3000 is it's probably going to be the website we have right um so why wait join now and start your reading Journey so this is probably just what we're accessing um I would guess if we do what is it Etsy is it engine X running this um sites enabled default let's see 3,000 I was assuming it would do like a proxy pass let's see I don't actually know how this is working CD Etsy engine X grap 300- R here uh it's in engine x.com they didn't do it in then s's enabled that is odd but we can find on Port 80 it's going to forward everything to Local Host 3000 so that is the main site let's check out 3001 so I'm going to curl Local Host 3001 and we get something different so what I'm going to do is set up a tunnel so to get into this SSH prompt if the first thing you do on a line is the squiggly C it drops you in that SSH prompt so I'm going to do - L uh 3001 1271 31 so once I hit enter we can go to Local Host 3001 on our box and it will for us through that ss8 session so we have this Bookworm converter demo we have a file to convert and output file type I want to see if I can find this so let's see um I'm going to find. GP convert I don't know if this is going to be a good one thing to do or not uh we see a bunch of things

Original Description

00:00 - Introduction 00:50 - Start of nmap 04:30 - Discovering a potential XSS in the Notes field of an order. Content Security Policy (CSP) blocks us, because JS cannot be on the same page. Looking for a file upload functionality. 08:29 - Finding out we can upload anything we want to the avatar. This should allow us to bypass the CSP in the book edit field 11:55 - Confirmed XSS on the page, checking if there's an IDOR Vulnerability that allows us to add notes to other people's items by creating a second account 16:00 - Creating a Python Script that will automatically poison items in peoples basket (cart) 28:00 - Backet Poisoner script is completed 28:50 - Creating a JavaScript payload, explaining why I'm doing await, fetch, and helper functions. 40:15 - Having the XSS Payload fetch profile, look for orders, then perform a get on all orders to examine the order page. Then send us the HTML of that page 49:55 - Creating a Python Flask Server that will save all of the orders the XSS Payload sends us 56:00 - Examining orders, discovering there is a "Download Everything" URL. Didn't show it but there is no IDOR Vulnerability here, need to have the XSS Trigger it. Exfilling /etc/passwd 01:12:00 - Extracting database.js, which contains the database information. The password lets us onto the system as Frank 01:15:52 - EDIT: Examining the source code to show why downloading a single book was not vulnerable. Talking about setting ROOT on res.download of express 01:21:04 - Enumerating the box as Frank discovering a second web application listening on 3001 01:30:00 - Looking at the source code to the book converter. 01:36:20 - Exploiting a SSRF/File Disclosure vulnerability in the Book Converter, but it doesn't get us anything 01:42:18 - Finding Arbitrary File Write vulnerability in the Book Converter by abusing SymLinks to bypass an File Extension Check. 01:51:50 - Shell as Neil who can run the GenLabel binary with Sudo, examining it to discover a SQL + PostScript Injection
Watch on YouTube ↗ (saves to browser)
Sign in to unlock AI tutor explanation · ⚡30

Playlist

Uploads from IppSec · IppSec · 0 of 60

← Previous Next →
1 HHC2016 - Analytics
HHC2016 - Analytics
IppSec
2 HackTheBox - October
HackTheBox - October
IppSec
3 HackTheBox - Arctic
HackTheBox - Arctic
IppSec
4 HackTheBox - Brainfuck
HackTheBox - Brainfuck
IppSec
5 HackTheBox - Bank
HackTheBox - Bank
IppSec
6 HackTheBox - Joker
HackTheBox - Joker
IppSec
7 HackTheBox - Lazy
HackTheBox - Lazy
IppSec
8 Camp CTF 2015 - Bitterman
Camp CTF 2015 - Bitterman
IppSec
9 HackTheBox - Devel
HackTheBox - Devel
IppSec
10 Reversing Malicious Office Document (Macro) Emotet(?)
Reversing Malicious Office Document (Macro) Emotet(?)
IppSec
11 HackTheBox - Granny and Grandpa
HackTheBox - Granny and Grandpa
IppSec
12 HackTheBox - Pivoting Update: Granny and Grandpa
HackTheBox - Pivoting Update: Granny and Grandpa
IppSec
13 HackTheBox - Optimum
HackTheBox - Optimum
IppSec
14 HackTheBox - Charon
HackTheBox - Charon
IppSec
15 HackTheBox - Sneaky
HackTheBox - Sneaky
IppSec
16 HackTheBox - Holiday
HackTheBox - Holiday
IppSec
17 HackTheBox - Europa
HackTheBox - Europa
IppSec
18 Introduction to tmux
Introduction to tmux
IppSec
19 HackTheBox - Blocky
HackTheBox - Blocky
IppSec
20 HackTheBox - Nineveh
HackTheBox - Nineveh
IppSec
21 HackTheBox - Jail
HackTheBox - Jail
IppSec
22 HackTheBox - Blue
HackTheBox - Blue
IppSec
23 HackTheBox - Calamity
HackTheBox - Calamity
IppSec
24 HackTheBox - Shrek
HackTheBox - Shrek
IppSec
25 HackTheBox - Mirai
HackTheBox - Mirai
IppSec
26 HackTheBox - Shocker
HackTheBox - Shocker
IppSec
27 HackTheBox - Mantis
HackTheBox - Mantis
IppSec
28 HackTheBox - Node
HackTheBox - Node
IppSec
29 HackTheBox - Kotarak
HackTheBox - Kotarak
IppSec
30 HackTheBox - Enterprise
HackTheBox - Enterprise
IppSec
31 HackTheBox - Sense
HackTheBox - Sense
IppSec
32 HackTheBox - Minion
HackTheBox - Minion
IppSec
33 VulnHub - Sokar
VulnHub - Sokar
IppSec
34 VulnHub - Pinkys Palace v2
VulnHub - Pinkys Palace v2
IppSec
35 HackTheBox - Inception
HackTheBox - Inception
IppSec
36 Vulnhub - Trollcave 1.2
Vulnhub - Trollcave 1.2
IppSec
37 HackTheBox - Ariekei
HackTheBox - Ariekei
IppSec
38 HackTheBox - Flux Capacitor
HackTheBox - Flux Capacitor
IppSec
39 HackTheBox - Jeeves
HackTheBox - Jeeves
IppSec
40 HackTheBox - Tally
HackTheBox - Tally
IppSec
41 HackTheBox - CrimeStoppers
HackTheBox - CrimeStoppers
IppSec
42 HackTheBox - Fulcrum
HackTheBox - Fulcrum
IppSec
43 HackTheBox - Chatterbox
HackTheBox - Chatterbox
IppSec
44 HackTheBox - Falafel
HackTheBox - Falafel
IppSec
45 How To Create Empire Modules
How To Create Empire Modules
IppSec
46 HackTheBox - Nightmare
HackTheBox - Nightmare
IppSec
47 HackTheBox - Nightmarev2  - Speed Run/Unintended Solutions
HackTheBox - Nightmarev2 - Speed Run/Unintended Solutions
IppSec
48 HackTheBox - Bart
HackTheBox - Bart
IppSec
49 HackTheBox -  Aragog
HackTheBox - Aragog
IppSec
50 HackTheBox - Valentine
HackTheBox - Valentine
IppSec
51 HackTheBox - Silo
HackTheBox - Silo
IppSec
52 HackTheBox - Rabbit
HackTheBox - Rabbit
IppSec
53 HackTheBox - Celestial
HackTheBox - Celestial
IppSec
54 HackTheBox - Stratosphere
HackTheBox - Stratosphere
IppSec
55 HackTheBox - Poison
HackTheBox - Poison
IppSec
56 HackTheBox - Canape
HackTheBox - Canape
IppSec
57 HackTheBox - Olympus
HackTheBox - Olympus
IppSec
58 HackTheBox - Sunday
HackTheBox - Sunday
IppSec
59 HackTheBox - Fighter
HackTheBox - Fighter
IppSec
60 HackTheBox - Bounty
HackTheBox - Bounty
IppSec

This video teaches how to exploit vulnerabilities in a web application using various tools and techniques, including XSS and IDOR attacks, and how to use Python for web scraping and automation. The lesson covers the importance of cybersecurity and the need to identify and address security vulnerabilities.

Key Takeaways
  1. Run nmap to enumerate versions and output all formats
  2. Use burp to intercept and modify requests
  3. Create a Python script to crawl and poison baskets
  4. Exploit a file disclosure vulnerability to read files from the server
  5. Use Flask to create a server and handle POST requests
  6. Extract download link from HTML page using regular expression
💡 The video highlights the importance of cybersecurity and the need to identify and address security vulnerabilities in web applications, and demonstrates how to use various tools and techniques to exploit these vulnerabilities.

Related AI Lessons

Chapters (18)

Introduction
0:50 Start of nmap
4:30 Discovering a potential XSS in the Notes field of an order. Content Security P
8:29 Finding out we can upload anything we want to the avatar. This should allow us
11:55 Confirmed XSS on the page, checking if there's an IDOR Vulnerability that allo
16:00 Creating a Python Script that will automatically poison items in peoples baske
28:00 Backet Poisoner script is completed
28:50 Creating a JavaScript payload, explaining why I'm doing await, fetch, and help
40:15 Having the XSS Payload fetch profile, look for orders, then perform a get on a
49:55 Creating a Python Flask Server that will save all of the orders the XSS Payloa
56:00 Examining orders, discovering there is a "Download Everything" URL. Didn't sho
1:12:00 Extracting database.js, which contains the database information. The password
1:15:52 EDIT: Examining the source code to show why downloading a single book was not
1:21:04 Enumerating the box as Frank discovering a second web application listening on
1:30:00 Looking at the source code to the book converter.
1:36:20 Exploiting a SSRF/File Disclosure vulnerability in the Book Converter, but it
1:42:18 Finding Arbitrary File Write vulnerability in the Book Converter by abusing Sy
1:51:50 Shell as Neil who can run the GenLabel binary with Sudo, examining it to disco
Up next
Machine Learning Project for Final Year Students | ML Project Idea @FameWorldEducationalHub
FAME WORLD EDUCATIONAL HUB
Watch →