 Hello, everybody. My name is John Hammond. Welcome back to the YouTube video. We're still looking at some more all-army cyberstakes and ACI CTF. I want to showcase this challenge. It's called The SQL Always Sucks. It's for 150 points in the Web Security Challenge. It says, if we discovered an application in our environment that's apparently under development, please identify the risk it poses. It says solutions to this problem are known to be sensitive to common latency. If your solution is working very slowly, you may be able to speed the process by running it from the competition's shell server. Okay, whatever. So let's fire this up. It's a web page and it says, the SQL Always Sucks. It says, SQL Retriever version 0.2, Dev Info Storage, first name. John, submit. Welcome, John. Thank you. Fantastic. That is apparently all that the web page does. If I view the source here, I'm going to zoom in. It says, the SQL Always Sucks is a title. Debug has display of none. That's interesting. Okay, I see that debug line down here. Last SQLite query, select name from users where first name equals John way down here. It says, Dev is only using SQLite. Bobby needs to fix this. Okay, so we know the backend database is SQLite. And seemingly, it shows us the query that's being ran. I don't know what more we could do with this, right? So we could tinker with it. If we go back or modify this first name, we could try a little or one equals one, and then some comments out there. It says, welcome or one equals one and Brantley. Hello, Brantley. I don't know if that lets us get more. Union select one, comma, comma. Union select no, what does that say? No unions. Is it not letting me use unions? Is that the page trolling me? It looks like it is. Okay. So truth be told, if you go take a look at the hints here, it says, Hey, sometimes it's useful to know what database is behind a web application. In this case, we know, okay, it's SQL SQLite. SQL injection doesn't always result in giving you raw database content sent directly back to you. Sometimes it's all about patience and timing. Ah, a timing attack. Okay, if we can't use union, maybe we could do some Boolean stuff with timing. Some attacks are just not practical to do by hand because they require precision and lots of repetition. Thankfully, tools like SQL map can automate much of this for you. Okay, so we could do this with SQL map potentially. Many tools like use unique user agent strings by default. Oh, so curl and SQL map don't appear to be working properly. You might look into whether you configure them to impersonate something else. Odd, maybe that page just does not respond to curl. If I were to simply curl, slap that guy in it says help I'm being hacked slash dead. Okay, so we probably need to grab what is my user agent. Thank you, Google. There's our user agent. We could do this with SQL map. And admittedly, I didn't. So maybe we could fire it up like let's let's just try that. Let's hop into a directory here. Let's make that the SQL always sucks folder. Wow, typing. I don't need to W get anything. I just need to start to write a script. So I can save this in here. User bin environment Python. Let's just say user agent can equal this guy. And I should clear out some of the stuff from the leftover videos. But let's try to get SQL map going on this. First name seemed to be the argument that needs to be supplied. Yeah, so first name should be what we should use so we could use SQL map. tack you on this guy. Is he an opt? Yeah, he's an opt. Okay, SQL map dot pi tack you on that URL. It probably needs an HTTP reference, but I guess it figured it out. First name does not appear and the SQL map is just steaming right through it. Okay. We could tell it that it's SQL light because we know that. Let's actually specify that if you check out the help for SQL light, it should tell you that excuse me for for SQL map, it should tell you that you can specify tack tack dbms. Yep, to specify, this is what the back end database management system is. So let's try that with tack tack dbms SQL light. Maybe it'll try some stuff now first. Okay, it's recommended perform only basic union tests. Do you want to reduce the number requests? Yeah, that's fine. Oh, we don't get the user agent that we specified, right? Because we need to actually supply that. So let's use that user agent. We save that as a string here earlier just to take note of it. Pass it in. Maybe now we'll behave a little bit better. Yep. Well, you won't bother with the union tests. Okay, we can try like level five. Is that how it goes? Like level goes up to five and risk goes up to three, I think, right? So I let this run for a little bit of time. Whenever it would be connecting and it would be trying some attack, it would tell me just kind of as the description of the challenge said, it's getting some issues connecting back and forth. So it's doing some latency stuff. Given the kind of foresight from the hints that this is a timing attack, we could determine how can we do a timing attack within SQL light? And that might be able to give us some useful information if we were to try and do this by hand without using SQL map, I'd like to do something by hand and not try to bother with these SQL with SQL map. And I think there's a little bit more learning in that as well. So if you simply google SQL light timing attack, or like SQL light injection payloads or cheat sheets, there's some good stuff in here. Here's a SQL light SQL injection cheat sheet. One of those results here. And this has some good stuff. You could determine things for a concatenation. If you're trying to do things for comments, it gives you a basic syntax. And there is a time based data extraction. They have a condition set in here and they're saying and one equals this random blob, that will cause a time delay if the condition is true. So maybe we could do that. Let's keep track of this. And let's let our SQL map run in the background until it dies, which it may very well, but we can go ahead and get started with our own script. So let's import requests. Let's do r equals requests dot get if I could type my goodness, I've been doing this for too long, I've been recording too many videos. Let's grab the URL for this challenge, because I don't have that just yet. We can get the URL to equal this guy. We should specify headers to get our user agent in there. That can be simply user hyphen agent, and the user agent variable that we just created. So we could say URL, and headers equals headers. And params should be our database or dictionary, sorry, of what we want to actually try and inject. So params can equal that first name value with our SQL injection. So if I were to try that or one equals one trick with the hyphen hyphen little comment there, we could print out a r dot text. And let's see how that page looks. It needs HTTP colon slash slash as part of the schema in the URL. And there we go. Now we get our page back. I'll split this one more time, drag that output over there. And let's make that syntax in that page HTML. I'll zoom out a little bit so you can see that hopefully you can still kind of read the source code. But the sun is like coming down on me. I don't know if you can see that in the video. But Alrighty, now that we have our SQL injection, it says hey, welcome or one equals one. Oh, I forgot my equals. So that's why that didn't return to me. The little Bentley or that just hung. What happened there? That didn't return anything. A lot of white space. What does that say? There we go. Or one equals one Brantley, and then a lot of white space, for some reason, seemingly. So we know that that clearly works. We know that our Python script as a simple proof of concept will work for us. But let's play with that timing attack. We have a condition that we might need to specify and one equals one random blob, maybe that random blob is what will trigger the time difference for us and we can perform our timing attack. So if I did or one equals one, if I were to use an or zero equals one, that will obviously not retrieve much, seemingly. But we could use that or as a condition. And we can do a one equals one and our random blob. So we know that should work because our or will trigger this condition to work. This first condition one equals one is true. And our and will return from running this. So if I were to press Ctrl B on this, you can see that this window is taking a little bit of time to actually get the response back. So we know, okay, our random blob is actually working. That took a lot of time. So I'm actually going to remove one of the zeros in there and turn that down. That still had a little bit of delay, it wasn't as an instantaneous response as before. So we could kind of toggle this, right? Our or condition is letting us apply another SQL statement in there, and to get our timing attack in place. So that one equals one, we know it will take that long for it to return. And how about a false condition where that random blob does not trigger and we don't have that timing attack? Let's try that. That's a quick immediate response just about. So let's try and determine how quickly that's actually taking let's import time. What I'll do is I'll say a start can equal time dot time. And then I'll do an end equals time dot time. So I'm taking a snapshot of the current time like starting the stopwatch right before I send the request and right after I send the request to see how long it takes for the request to come through. Now what I can do is I can determine like the delta, I can say, okay, how long did it take the difference from when we stopped recording to when we started recording the time? Let's print out how long it took after we get a response. So with a false condition with something that does not start this random blob timing trigger, it takes about half a second or two tenths of a second that might jitter a little bit because we won't know for certain. That one took some time. That was an oddball. We could also just very well switch that trigger now to our one equals one. So we will pause just after our little random blob timing attack. So what we can determine is if it takes longer than maybe a half a second, we know we have a true condition, we know that we were able to actually trigger our timing. If it was a false condition, it will take less than half a second, usually pretty much, right? If we if our connection is good, and nothing's tweaking out on us. So with that, we could kind of start the structure to build a timing attack or some boolean attacks to potentially read out what we actually are looking for in the database. So let's try and determine that with some of our other payloads here. If we want to get the table name enumeration, we can select name from SQLite master where type equals table. And we want to be able to get the first string of that, don't we? Because we if we're doing some boolean stuff, it would be good to get like the very very first character one at a time. And they're actually going to end up using do they showcase it in here? They don't I don't think they do cast one as text I want to get a hex. I think hex is what it should be. I'll look at the payload all the things response and see what it can tell me here. Oh, they do some good stuff they do integer string base extract table name extract column name and boolean stuff count the number of tables enumerate the table name, they select the length here, extract info of the day they use they use hex and substring on the table name from SQLite master, or table name is not SQLite. That looks good. That looks like a condition we can use, because it's going to extract out the first character or whatever character we specify, based off of some hex character as well. So let's get that in place. I will use this condition. And I'll say if it's equal to the hex of some character. So table name is what we're returning from SQLite master to get the table name out of this, it's going to start at position one and go for a length of one. So we'll get the very very first letter out of this. And we'll determine if it is equal to one specific character, which we could kind of specify I'll use percent s and then like a letter C. Now we should really go ahead and start to brute force and determine, okay, what is the actual character that we could leak out with this technique. With that, I'll go ahead and import string. So I can do a for C in string dot printable. Let's include our parameter with testing the hexadecimal character of that character we're looking at. And we'll use our delta to determine if it was a true or false request. So if delta was less than 0.5, that's kind of our threshold, then we know, okay, that is a false condition, and we can continue to test and loop through it. If it is greater than 0.5, then we like, okay, no, now we have a true statement. Now we have a true condition where we've actually found the first character of that table name. So we got a hit, right, or whatever we want, and we can print out our letter or C. We can print trying C. And we can print out our delta with that. In the case we got a hit, let's break and just have a simple proof of concept to see if we can leak out the very, very first character that we're looking at. So let me move our build output back over here. And let's try and run our script. That seemed to fail unsupported format character hex 27. Why is that percent s? Can I just use a format? Maybe it doesn't like that sequel light one that's referring to us. Let's use format C run that guy. There we go. So now we're trying all of the different potential characters that could be returned to us. We could leak this out. It's going through numbers. It's going through letters, and we'll see if it ever gets a hit. Oh, there we go. Looks like we got a hit. Me knowing this challenge, I can tell you that's wrong. So that might be just our network connectivity fumbling. Again, as they say that it's probably a good idea to do this from the shell server. We could SSH and connect into that if we wanted to. But let me just rerun this so I can get our correct thing. And that's going to keep doing that. So let's pivot. And let's go to our shell server. Maybe we can go ahead and run these things just as easily. It does give us a shell over here, right? I can just SSH into this. Does that work? Can I do that? Did sequel map ever get anything? No, I just gave up. So I need a John Hammond as that is my account. Yep, that's totally fine. Enter your platform password. I will copy my password from last pass, slap it in there. Now we should be logged in. Fantastic. Okay. I wonder if it will let me do this with SCP or SFTP. Let me create a new window where I can SFTP over to that. And that's apparently my password. Thank you. Let's grab that cyber challenge link. Will that work? Trying to connect? Maybe not. Okay, that's fine. We'll just copy things in as needed then. Let's make our Python script vim ape dot pi slap that in there. And now let's Python three ape dot pi. There we go. Now he's going super duper quick. And even way too quick that our timing doesn't matter. But that tells us, okay, we have a condition where it is certainly true. And ones that aren't are maybe less than a second. So we can change our threshold to 0.1. How about that? We will need to now modify our script. Let's do an echo nothing into ape dot pi and then edit so I can slap that in really quickly and run it. There we go. So our hit is s. And now we could add that to our list of known characters. And we could slowly start to build out the flag or what we might be reading from that data. So let's do that. Let's do a while one. So we keep looping this. And let's keep track of our known data. I'll make that a list. And we'll start with s because we already know what that is. So we need to adjust what we're actually looking for in the index of our SQL statement, because it's starting from the very, very first position. But we want to be getting just it after the length of our known data. So we'll have to modify this to a formatted variable as well. So that will be supplied. And our hex character will also be supplied. So let's do length of our format or known data. And we'll add one to it because it is one base rather than zero based. And in the condition that we got a correct key, we'll go ahead and add that we'll simply say known data dot append C. And we'll start to actually display what we're seeing thus far. We'll say our join known data. And then trying that all out. Now let's try and run that code. So we're seeing everything that we're building thus far. We're adding to what we build once we know that we have a hit, and we break out of our for loop. So we start again now iterating to add and look for the next character. Let's try to Vim edit our script, slap that in there and run it. And now it's leaking out super secret data. And that's what's going to end up being that table name, which will have the potentially useful and worthwhile information that we might need. So we could go ahead and determine that let's say, table name is super secret data. Let's clear out our known data list. And let's go see how we could determine what might be in that schema. Select SQL from SQLite master where type equals table. So we want to search this guy and table name. Well, we could potentially group concat that could we not? Can we do a group concat? How did they do that? Previously, they just had a from where in there. So we don't need the select that we just SQL is what we're actually looking for. So SQL from SQLite master where type equals table limit one, that guy, maybe that will work for us. Let's try that way we can determine what columns are actually in that super secret data table. Run that guy. There we go. And this will leak out the actual SQLite database schema, how it's represented inside the database. So we'll be able to see this is the column name, this is the type that it's using, this is the data length that we would expect, etc. Thankfully, because we're on the shell server, this is cruising along pretty quickly. It looks like it's adding even new lines. So we're working for but we can see it growing and displaying out as we're working on. So we can tell there's an ID column. And there also seems to be a flag column. Great. That should be text. So let's start to leak out that flag. And now that we've determined the actual schema and what is in that database in that table name. Just paste that in here. So we want to select the substring of flag from super secret data. We don't need to do any where statements, but we're still going to limit one and offset zero. So we get all this good stuff. Let's go ahead and modify our script on the shell server and run that. So there we go. Now we are leaking out the flag using that timing attack and being able to actually determine what is in the database using some Boolean blind SQL injection technique, which is kind of cool. I hope you guys are kind of like that. I don't know if that was presented extremely well. But the resources that I think you guys should actually take away from that are of course payload all the things and absolutely some of that a SQL cheat sheet that we saw up here the unicorn as fuel SQLite SQLite cheat sheet. That gave me kind of the tools and what I needed in my arsenal to be able to go ahead and determine and do this timing attack with that random blob that seems to at least cause a delay and trigger and SQLite that I know I can use to actually leak out more information and that will help me build out this attack. So cool. That is it, everybody. That is all that I wanted to cover. I hope you guys learned something in this video. I know it was a little bit of a whirlwind, but some Python stuff in there, some SQL injection SQLite timing attack and some neat threshold determination between finding out when we're actually having a correct data value, a true condition and a false condition. So thank you guys so much for watching. I hope you guys enjoyed this video. If you did, please do press that like button. Love to see you guys maybe leave a comment, do some YouTube algorithm stuff, hit that subscribe button. I'm so so grateful. If you guys would like to support the channel or me or anything that I'm doing, there is a link to Patreon in the description, link to PayPal, link to Discord if you want to come hang out with everybody. And I'm honestly just so thankful for everything that you guys do. So I wouldn't be able to do these videos if you guys weren't out there watching. All right, that's it. That's the end. Good night. Take care. I love you, etc.