-: 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 failed to execute in the order
and timing intended by the developer.
Now, that's a really funky 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 no-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 any virus,
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 Write.
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 Write
that was using the kernel's memory management system.
Now, because this race condition exists,
with the right timing, a local attacker could exploit
the copy on write 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, when 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
invalidate 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 ecommerce store,
and I had a shopping cart, and you go onto 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 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 ecommerce,
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 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 one, two,
three, four, five, 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 four or 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 to 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 this 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 onto 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 ever use 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.