In this lecture, we're going to talk about how we test for security. Before we can do that, first we have to talk about what security is. So, security is really sets of processes and technologies that allow owners of resources in a computer system to reliably control who can perform actions on particular resources. So, we can think about the people who have rights to do things as principles. That's what we tend to call them in security, and the things that they have rights on are systems, tasks and information. So, a system is usually some physical system. You can think of like a chemical plant, and the activities that a computer may perform on that system are things like opening valves or flipping switches, that caused the system to react in a certain way. Another thing that we have rights to are tasks. So, we have hardware resources, and we can use those in different ways. We can run processes and run threads, and who has the access rights to do that and on which hardware resources is something that we care about in terms of security. Finally, there's information. And when we tend to think about security, this is what we tend to think about. So, when we read about credit card breach of a company where they steal a million credit cards, what happened was a hacker got in and took information that didn't belong to them. So, these are the different activities that we can perform on these resources, and what we do is we create what's called a security policy, and this says who should have access rights to these different resources. Then we're going to have attackers that are going to try and gain access to these resources in such a way that they don't follow the policy. So, we're going to call these threats. Finally, we have things that we can build into our applications to prevent the threats from getting in, like this shield, and these are called mechanisms, mechanisms to enforce security. What we're going to do really when we do security testing is we're going to test the mechanisms. We're going to pretend to be a threat, and we're going to look to see how well the system responds to these threats. One of the important things to remember is that security is all about risk management. Every software system is insecure in some way, unless it's not running at all. So, the thing we have to look at is how likely it is for an attacker to break in, and what can we do to make it very, very difficult for an attacker to break in without it being extraordinarily expensive. So, let's look further at security threats. A security threat describes a possible way that an attacker may breach the security constraints, so the mechanisms that we have. It may also document a rationale as to why. So, when we think about the security threats that we have for our application, usually we want to think about why this is a threat. So, what we want to do when we think about security is to identify as many as possible threats to the security policy. So, things like password cracking, what requirements do we have on users? Network attacks, denial of service by sending too many requests, exploitation as software bugs like buffer overflows, social engineering. What happens if an attacker befriends someone who has legitimate rights to this system? What happens then? Or what happens if we have a malicious insider? So, someone who has some legitimate rights but decides that they want to misuse those rights in some way. When we do security testing, what we're trying to do is reveal flaws in these mechanisms that we're using to protect against the threats. The goal of security testing, because we can never really be sure, is to determine a level of competence that we have that the software is resilient to attack. When we do security testing on modern systems, usually it involves a bit of manual testing but an awful lot of automated test generation, and this is going to be the focus actually of course 4 within the sequence, but we're going to touch on it here just to demonstrate how you can do security testing in the web. One thing to note is without proof, even if we do lots and lots of testing, it's very difficult to make strong statements of security, and in part, this is why we talk about proof in the next course. But security testing has become an integral part of modern software development. If you think about it, there are very few applications that we build these days that aren't connected to a network and once you're connected to a network, someone will try and attack you. So, we look at testing for security. Most of the news is bad, if I'm honest. Security is really asymmetric. So, the defender, the tester has to identify all the possible security errors. So, let's suppose you're the tester for Windows. You have 20 million lines of code that you know is going to get attacked all the time. So, the sources of attack are outside of your control. There may be entry points to the network through browsers, through you name it, different kinds of devices that are attached to the computer, and usually the attacker only has to find one flaw in order to break in, and you have to fix all the flaws. But the good news is that many of the attacks that attackers use are predictable. So, there are certain kinds of weaknesses in modern software systems that get exploited over and over again, things like buffer overflows. Now, in Java, there's actually protection for arrays. So, you can't overflow a buffer, so this particular attack goes away when you use a higher level language. But all the other attacks are actually possible to perform in Java, and since a lot of system software is written in C or lower level languages, these buffer overflows are still very important. So, things like replay attacks. So, a legitimate user asks for a resource and the attacker just records that request then later on plays it back. Another thing that happens is that people forget to use encryption. So, within a data center, you might think two computers communicating are safe, but you're likely wrong because if there's some other computer within the data center anywhere that has been compromised, it might be able to listen in on that communication. Incorrect use of a database is another way to do this, too many privileges, so you have an application that needs to be able to do a few things but you've given it rights to do a lot of things. Then there are, in particular, text strings that we make, escape character attacks. So, if you send database commands across the wire, sometimes you can inject specific characters that cause the database requests to misbehave. So, what are we going to do? We're going to check programs for well-formedness. We're going to use a technique called fuzz testing that I'll explain in more detail in the next lecture. That's a little bit like million monkeys tests, where it tries random stuff right around the border of what would be considered correct input. We're also going to, in course 4, look at more aggressive techniques using static analysis which can provide stronger guarantees about correctness. We're also going to check connections and protocols. So, when we do security testing, it's not all about the functional behavior of the program, it's also about how things are configured. So, is this web request configured to only work with HTTPS? Which is encrypted, or can I make it with HTTP? Which may allow an attacker to look in, and we're going to look at the configurations that we use to manage our processes. So, is this thing running at a high-privilege level or is running at a user-privilege level? Then finally, I'm going to check the requirements. So, if we have a requirement that only this action can occur after authentication, then by golly, when we're using the application, I shouldn't be able to do this without getting authenticated.