CompTIA CYSA+ CS0-002 – Mitigate Software Vulnerabilities and Attacks Part 3
3. Race Conditions (OBJ 1.7)
Race conditions. In this lesson we’re going to talk about race conditions and the vulnerabilities associated with them. Now, what exactly is a race condition? Well, a race condition is a software vulnerability that occurs when the resulting outcome from execution processes is directly dependent on the order and timing of certain events and those events fail to execute in the order and timing intended by the developer. Now, that’s a really funky way way of saying that basically the computer is trying to race itself. So if you’re trying to do something legitimately and the attacker is trying to do something at the same time and they can get in before you, they have now taken advantage of this race condition to be able to run their thing before you can run yours. And this is a very specific case when we start talking about a race condition vulnerability.
This is found when there are multiple threads attempting to write a variable or object at the same memory location at the same time. Now, one of the ways this can happen is by a dereference or a null pointer dereference exploit that’s being exploited that can trigger this race condition. Now, when we talk about dereferencing, this is a software vulnerability that occurs when the code attempts to remove the relationship between a pointer and the thing that that pointer is pointing to in memory. This is why it’s called dereferencing because we’re dereferencing or breaking apart the pointer and the thing it’s pointing to. Now, race conditions are difficult to detect and mitigate. In fact, this is one of the things that actually is used by attackers to try to evade antivirus because if you can race in and get there before the antivirus can take hold, it doesn’t realize you’re doing something wrong.
And so there is a lot of examples in the past of this happening. One of the most common ones was actually in 2016 and it’s known as Dirty Cow. Now, Dirty Cow is a great example of a race condition that was used to exploit a computer vulnerability. Now, when I talk about cow, I’m not really talking about a cow like you see here on the screen. The cow actually stands for Copy on Right. Now this exploit affected Linux operating systems in 2016, including some Android versions. Because it’s based on Linux, the exploit would cause a local privilege escalation bug that could be exploited through this race condition vulnerability because of the implementation of the programming for Copy on Right that was used in the kernel’s memory management system.
Now, because of this race condition exists with the right timing a local attacker could exploit the Copy on right mechanism to turn the read only mapping of a file into a writing mapping and therefore they now had privilege escalation because they could write to a file where they only were supposed to have read access. Now, because this was a race condition it was hard to detect because it didn’t even leave anything inside the system’s log to let you know what happened. And so this again is why race conditions are so dangerous. Now race conditions can also be used against databases and file systems. They don’t have to just be used against some kind of an operating system kernel or memory. Now when race conditions are used to exploit a database or a file system generally they’re going to take the form of a time of check to time of use vulnerability.
Now we talk about a time of check to time of use. This is a potential vulnerability that occurs when there’s a change between when the app checked a resource and when the app actually is going to use the resource. So essentially this vulnerability will make the change and validate the check that was already made. Think about it this way. If the attacker can identify the time the check happened and then do something before it was used that’s a race condition. They can then manipulate the data after it’s been checked but before it was used by the application and therefore cause some kind of an issue. For example, let’s say I had an e commerce store and I had a shopping cart and you go on to Amazon for instance. Let’s say they program this horribly. You go to Amazon, you put a bunch of stuff in your cart but you never bothered to check out.
You put down your phone, you come back the next day, you pick up the phone and see you still have all these things in your cart. So you go there’s there and you finish your purchase. Well if Amazon didn’t go back and actually check that those things were still in stock and that the price hasn’t changed, then this would be a time of check to time of use issue because they checked it when you put it into the cart but then you’re using it when you check out of the cart. And so that time difference is an issue. So what you’ll see is most things, especially with e commerce they’re going to do a final check when you try to pay and they’re going to say do we still have it in stock? And it’s is it still the same price. This can help prevent this time of check to time of use issue. Now how else can you prevent race conditions in time of check to time of use issues? Well the first thing you could do is develop applications to not process things sequentially if possible.
So if I have to do something and it takes a certain amount of sequences, do I have to do them all going from 12345 and take those steps or can I do things in parallel? Anytime I can do things in parallel that’s going to decrease the amount of time that things are in sequence and that’s going to limit the ability for a race condition to occur. The second thing we can think about is implementing a locking mechanism within the app to provide exclusive access to that resource. And a lot of ecommerce stores will do this. For instance, if you go into Amazon and you put something in your cart they will give you exclusive access to that maybe for five minutes. If you don’t buy it within five minutes they’re going to take it out of your cart or they’re going allow it to be open in the store so somebody else can buy it.
But during that five minutes they put a lock on that product and say this one is reserved for Jason, he has it in his cart and if he checks out within five minutes he can have it. You’ll see us a lot with movie theater tickets or concert tickets because there’s a limited supply. They will give you a certain time to check out and during that time you hold on to that ticket. Now that’s an example for physical products. But even inside your database there can be things like that. For instance, if you’ve ever used SharePoint to work on files across an organization, they use this type of a locking system for their database. If you take a file you will check out that file, you make those changes, then you check the file back in. That removes the lock. Now other people can have access to it to make those changes. During that time people can read the file, they just can’t write to the file because you have exclusive lock access on it. And that’s a good way to prevent a race condition.
4. Improper Error Handling (OBJ 1.7)
Improper error handling. In this lesson, we’re 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 be able to handle errors and exceptions more gracefully. I’m not going to bother to define an error here because as 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 pseudocode. 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 pseudocode. Now, here I am, initializing four variables. I’m initializing X-Y-Z and total.
Then I’m going to take in his 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 divided 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 equals five, y equals ten and Z equals five. 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 else statement, which in this case means we’re going to set the total equal to x plus Y divided by z or five plus ten divided by five, which in this case would be 15 divided by five, 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 510 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 green, 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.
If you know anything about math, you know that you cannot divide by zero, it will 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 want 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 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 log in, 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 »