CompTIA Pentest+ PT0-002 – Section 11: Application Vulnerabilities Part 2
102. Buffer Overflows Attacks (OBJ 3.3)
In this demonstration, I’m going to show you how a buffer overflow attack is conducted. Now I’m going to do this by using a simple program that’s written here. This program is called narnia0.c. This tells me that the program was written in the C programming language. You can see it displayed here on the screen. Now you don’t have to be an expert in the C language to understand what this program is doing though. I’m going to walk you through it step by step, and then I’m going to show you how we throw this buffer overflow attack to exploit this program. Now the first thing we can see is that there are two statements that start with the word include. This is just saying that we’re going to include these third-party libraries, the standard input/output library and the standard library itself.
After those two include statements, we get to the main part of this program. This is called main. If you see the first thing, we have a long variable, and that value is 0x41414141. Followed by that, we have a character array being set up called buffer that is 20 items long. This means that the buffer can only hold 20 pieces of information, or 20 characters in this case. Next, we have the printf statement, which basically says put everything in between the quotes onto the screen when you run this program. Then, it goes and asks you here is your chance to try it. And then it asks by scanning what the input is from the keyboard, and that input is going to be stored into the buffer.
Once you’ve inputted what you want to the buffer, it’s going to print out the two variables, what’s stored in buffer and what’s stored in value. After displaying both variables to the screen, it’s going to see what the value was. If the value = 0xdeadbeef, meaning we’ve overflowed the buffer with the characters that make up deadbeef, then the system will give you a shell prompt, which means you’re going to have access to that system to conduct any kind of programs you want. If not, it’s going to say WAY OFF, and it’s going to exit the program, and you’ll have to try again.
So now that we’ve walked through that program a bit, let’s go ahead and run it and see how it works. First we’ll type in ./narnia0, which simply tells the computer to run the program narnia0. When I hit enter, you’ll see that it brings up the correct value is from 41414141 to deadbeef. Here’s your chance, and it’s asking you to input something. So now I need to input my guess. What I’m going to do is I’m going to put in 20 A’s and four B’s. The buffer, if you remember, was only 20 characters long.
So what I’m really trying to do here is fill up that 20 character buffer using all of the A’s, and those four B’s are going to overflow into the value of the variable val. So instead of having 41414141, I’m going to have the hex value of those four B’s. And when I do that, you’ll see that the buffer is now flowing with all of those A’s and those four B’s, and the value has changed from 41414141 to 42424242, and 42 is the hex representation of the letter B. So now, at this point, I’m going to go through and try to write a short Python script that will put 20 A’s followed by some hexadecimal characters that I want. In this case, I want the hexadecimal value to show up as deadbeef, D-E-A-D-B-E-E-F. Now those are characters that make up a word in this case, but actually they’re just hexadecimal digits where the D stands for 13, the E stands for 14, the A stands for 10, et cetera. So what we’re going to do is we’re going to have to do this a little bit backwards.
And the reason is because this machine is going to use Last-In-First-Out architecture when I’m trying to attack it. So, in this case, I’m going to use \xef\xbe\xad\xde, which, when combined back together, will give me deadbeef like I want. And I’m going to pipe that output into the narnia0.c program. So when I hit enter, it’s going to run that program and feed that information from the Python script into it. In this case, the buffer is now overwritten with those 20 A’s and the four hexadecimal characters that I’ve added. And you can see that the variable val has now been overwritten with the value of 0xdeadbeef. This was the solution we wanted in the problem, but all it did was return us back to the narnia prompt. That’s because what the program did was run itself and execute a shell, but I was already in the shell environment. If I was doing a buffer overflow attack, like this, I can have it run any program I want. And so, to do that, and display that for you, I’m going to go through and actually change my Python script just a bit here. So I’m going to run my Python script again, but I’m going to add a little bit to it. So I’m going to bring it up like I had last time and I’m going to add a semicolon, which means once you finish doing that command, do this next command.
And so what I’m going to do here is echo and then the program cat, and I want you to show me the file narnia1 inside the narnia_pass directory. Ideally, this would be something like a password file, like an etc shadow file, or something like that. And then I’m going to go ahead and run that. Now let’s see what happens. In this case, we see that the deadbeef value is written to the value, but then when it goes to execute that shell command it was passed the command that I gave it, the cat /etc/narnia_pass/narnia1. And so what I get is the value that was shown in that file. In this case, that’s efeidiedae. Now this is just a very simplistic example of a buffer overflow attack. If you didn’t understand all the things that I went through in this video, that’s okay, this is way beyond the scope, but I wanted to show you what a buffer overflow attack really looks like when a hacker is doing this type of thing. This is a sample for our lab environment, but I just wanted to give you an idea of what happens. And the big takeaway here is that we overflowed the memory buffer so that whatever was put in after went and overwrote the next value in memory. In our case, the val variable. By doing that, we are able to then run other programs by getting into a command shell or other things. Whatever command that’s going to be run is going to depend on the exploit you’re using, but that initial buffer overflow is what allows you to put that into memory.
103. Authentication and References (OBJ 3.3)
In this lesson, we’re going to discuss broken authentication and insecure references. And how these vulnerabilities are exploited by threat actors. First, we have broken authentication. Broken authentication is a software vulnerability where the authentication mechanisms are insecure, and it can allow the attacker to gain entry. If the application doesn’t implement secure authentication mechanisms, then a threat actor is going to be able to exploit the system to compromise a user session or their password. This exploitation usually occurs because the passwords being used are weak or easily guessed, or because the authentication system itself was programmed insecurely, and has several coding flaws within it. For example, I’ve come across some broken authentication mechanisms in my assessments that include mechanisms that display the credentials in clear text. Or, they used weak randomization with defining their session tokens. I’ve also seen some that permit brute force login request without any kind of lockout or timeout feature. For example, if your program uses weak credentials, such as a person’s email address, and a four digit pin to identify the user, this is pretty weak as an authentication system. After all, any four digit pin can be cracked with just 1,000 attempts, because there’s only 1,000 variations of that pin. So, the attacker can quickly brute force their way through, and find the right one. Another weak authentication mechanism that could be exploited, would involve your password reset method. If your system uses a knowledge-based factor, like the person’s birthday, place of birth, or state they’re registered to vote in, all of those are considered weak factors of authentication, because they can easily be found online for most people. Now, another weakness is in terms of session identifiers that are being used after somebody authenticates to your application.
When you’re dealing with session identifiers, you need to ensure they’re truly random, and they’re not passed as part of your old parameters, because these can easily be captured by a network sniffer or an eavesdropping attacker. Now, let’s pretend you’re going to log into my website at members.diontraining.com. And let’s say we’re using improper session tracking. And this could be a vulnerability. Now, once you log in using your username and password to authenticate, you’re going to be issued a random session ID to track your movements, so we know which student is on which page or which lesson. Now, if this idea is being passed as a primer to our server through the URL, it’ll look something like members.diontraining.com/courses/id=1234. And this would be an extremely insecure way of doing things, so you really don’t want to do it. But follow me for this example. Now, if somebody copied that link, they could simply enter it into their web browser, and take over your session. Because that session ID is being shown right there as a URL parameter. For this reason, session IDs should never be passed as part of the URL parameters, because those can be seen when looking at network traffic even if the traffic was secured using a TLS tunnel. Now, broken authentication is one of the biggest vulnerabilities that are found in the Open Web Application Security Project, known as OWASP, in their annual top 10 biggest vulnerabilities. To protect against broken authentication, you should follow these seven recommendations. First, you should utilize multifactor authentication.
Second, you should never use default credentials in any application. Third, you should verify that passwords are strong and not found on published password exploitation lists. Fourth, you should use limits or delays to slow fail login attempts and brute force attacks. Fifth, you should use server side session management, as well as using long, randomized session identifiers. Sixth, you should never pass a session identifier as a URL parameter. And seventh, you should always implement session timeouts and expiring session identifications to prevent reuse of previously authenticated sessions by your users. Now, the second major vulnerability we’re going to discuss in this lesson, is known as insecure references. Also known as insecure object reference, or an insecure direct object reference. Now, an insecure direct object reference is used by a threat actor to manipulate the URL, to gain access to a resource without requiring proper authentication, because of a weak access control system that’s in place. This is commonly used to access data inside of a database through an insecure web application. Now, let me provide you with a good example of this vulnerability. Let’s pretend I started my own bank called the Bank of Dion. Now, a bunch of my students decide to sign up for my bank, and each one is going to be issued their own account number. Now, anytime a student wants to access their bank account, they’re going to log in at bankofdion.com, and then they’ll be redirected to their own personalized page. Something like bankofdion.com/account.php?acct=1234, and then their account will be displayed to the screen. Notice the URL here contains an insecure direct object reference to that student’s account. In this case, it says account=1234. Now, if I change that and went from 1234 to 4321, I’m going to get access to somebody else’s account information. This is because the account number is being passed insecurely as a URL parameter, and directly linked to a specific account and user.
This is what we’re referring to with an insecure direct object reference, and it never be used this way. So, how do you prevent insecure direct object references? Well, the first thing to do is always use secure coding practices. This is an area that can be completely eliminated to the proper design of your web applications, and building improper authentication and reference techniques. Second, you should always implement proper access control techniques in your applications to verify a user is authorized to access a specific object, even if you’re using direct references. For example, if I was logged in as Jason in the Bank of Dion example, and I tried to change my account from 1234 to 4321, it should give me an error, because that account is owned by Tamara and not Jason. But again, it is much better to ensure you don’t use direct object references in the first place. So, this again goes back to using proper secure coding techniques and best practices to prevent this type of exploitation.
104. Improper Error Handling (OBJ 3.3)
In this lesson, we are going to talk about improper error handling. Now, if you’ve used a computer for any length of time, you’ve probably gotten an error. Now, that error can be really detailed or not so detailed. It really depends on how it was coded. And what we’re going to talk about is how a programmer should really create a well written application and to be able to handle errors and exceptions more gracefully. I’m not going to bother to define an error here because we all know what errors are, but what causes an error? Well, errors could be caused by invalid user input, a loss of network connectivity, or another service or process failing. Essentially something went wrong and so we’re going to generate some kind of a message. Now, when we talk about an error handler, this is some kind of coding method that’s being used to anticipate and deal with exceptions that are thrown during the execution of a process. Now, error handling is critically important for us because error handling can prevent the application from failing in a way that allows the attacker to execute code or perform some sort of injection attack. And so if we don’t do proper error handling, for instance, checking for a buffer to make sure it has enough room before putting something in it, you can have something like a buffer overflow. That would allow some kind of an injection attack or a code execution to occur and so we want to make sure we’re doing proper error handling. Let me give you a really silly example here using some pseudo code. Here is a program I wrote. Now, this isn’t a real program or any real programming language. It’s just something that looks kind of like code, so we call it pseudo code. Now here, I’m initializing four variables. I’m initializing X, Y, Z, and total. Then, I’m going to take in as input X, Y, and Z from my user.
Then I have this program and the first thing I’m going to do is I’m going to test is Z equal to zero. Now, if Z is equal to zero, then I’m going to print to the screen an error message, Z cannot be zero. Otherwise, I’m going to do some calculations. I’m going to set the value of total to X plus Y divided by Z, essentially add together X and Y, divide by Z to give me some sort of a number. Now, once I have that, I’m going to print the averages and then the variable total that I just calculated. This is a really simple program, right? But it does show you the concept of error handling. Now let’s go through this and see what happens if I give some values to X, Y, and Z. First, let’s say that I have X = 5, Y = 10 and Z = 5. What’s going to happen? Well, we’re going to go through, we’re going to see that Z is five, it’s not equal to zero, so we’re going to skip the error and do the L statement, which in this case means we’re going to set the total equal to X plus Y divided by Z, or 5 plus 10 divided by 5, which in this case will be 15 divided by 5 which gives me three. And then I’m going to print that to the screen and say the average is three. That works perfectly fine. All right, so let’s take a look at another example. This time, I’m going to use the same program but I’m going to give X, Y and Z the values of five, 10, and zero. Now, when I go to run that program, the first thing I’m going to test is is Z equal to zero. Well, it is, so I’m going to print the error to the screen. Z cannot be zero.
Now, why do I do this? Well, if I didn’t have that if-then statement and I just said let’s just use total and print, what would happen? I would try to divide by zero and if you know anything about math, you know that you cannot divide by zero. It’ll give you an error. And so if I tried to just divide by zero, the program would crash. I can divide by any other number in the whole world but I cannot divide by zero. And so therefore, I put in a little bit of error handling to prevent the system from crashing. Now, let me give you another warning here when it comes to error messages. Noticed in this, I actually used my own error message. I said, “Z cannot be zero.” That was the error message I wanted to present. But the warning I want to give you is this. Sometimes default error messages could leak sensitive information. Now, what I mean by this is sometimes your programs will just give out the error messages by default and not something you told them to give. So if you’re using something that’s going to be calling a database function and you have an error on the SQL statement, it might actually print out the full SQL statement, including the file pass and stack traces and other information that could really be used by an attacker to hack your system.
So, when you’re creating error messages and you’re doing error handling, you want to make sure that you’re creative and think about using custom error handlers to be able to prevent accidental leakage, just like I did in my little program because if I didn’t have that error message and I tried to divide by zero, it could have actually done a brain dump of the memory onto the screen and that could have had sensitive information in it. So by me catching that error before running the application, I’m handling that error and giving you a message that makes more sense. Now, one more area that I like to think about this when we talk about errors, let’s talk about your login system. Oftentimes, people will create their website and they’ll have a login with username and password.
Well, what if you have a message that looks like this? Error, incorrect password. So, I go to your website, I type in my username, I type in my password, I hit login, and I get a message that says, “Error, incorrect password.” What does this tell me? Well, if I’m an attacker, this is actually valuable information because this tells me the username I submitted was correct but the password was wrong. So now I can keep using that username and then I can keep guessing passwords. So what would I want to use instead of this? Maybe I would use error, incorrect username/password, incorrect username or password, something like that, because then they don’t know which one is incorrect and now that makes it harder for them to continue to game your system and try to hack into it.
Interesting posts
The Growing Demand for IT Certifications in the Fintech Industry
The fintech industry is experiencing an unprecedented boom, driven by the relentless pace of technological innovation and the increasing integration of financial services with digital platforms. As the lines between finance and technology blur, the need for highly skilled professionals who can navigate both worlds is greater than ever. One of the most effective ways… Read More »
CompTIA Security+ vs. CEH: Entry-Level Cybersecurity Certifications Compared
In today’s digital world, cybersecurity is no longer just a technical concern; it’s a critical business priority. With cyber threats evolving rapidly, organizations of all sizes are seeking skilled professionals to protect their digital assets. For those looking to break into the cybersecurity field, earning a certification is a great way to validate your skills… Read More »
The Evolving Role of ITIL: What’s New in ITIL 4 Managing Professional Transition Exam?
If you’ve been in the IT service management (ITSM) world for a while, you’ve probably heard of ITIL – the framework that’s been guiding IT professionals in delivering high-quality services for decades. The Information Technology Infrastructure Library (ITIL) has evolved significantly over the years, and its latest iteration, ITIL 4, marks a substantial shift in… Read More »
SASE and Zero Trust: How New Security Architectures are Shaping Cisco’s CyberOps Certification
As cybersecurity threats become increasingly sophisticated and pervasive, traditional security models are proving inadequate for today’s complex digital environments. To address these challenges, modern security frameworks such as SASE (Secure Access Service Edge) and Zero Trust are revolutionizing how organizations protect their networks and data. Recognizing the shift towards these advanced security architectures, Cisco has… Read More »
CompTIA’s CASP+ (CAS-004) Gets Tougher: What’s New in Advanced Security Practitioner Certification?
The cybersecurity landscape is constantly evolving, and with it, the certifications that validate the expertise of security professionals must adapt to address new challenges and technologies. CompTIA’s CASP+ (CompTIA Advanced Security Practitioner) certification has long been a hallmark of advanced knowledge in cybersecurity, distinguishing those who are capable of designing, implementing, and managing enterprise-level security… Read More »
Azure DevOps Engineer Expert Certification: What’s Changed in the New AZ-400 Exam Blueprint?
The cloud landscape is evolving at a breakneck pace, and with it, the certifications that validate an IT professional’s skills. One such certification is the Microsoft Certified: DevOps Engineer Expert, which is validated through the AZ-400 exam. This exam has undergone significant changes to reflect the latest trends, tools, and methodologies in the DevOps world.… Read More »