MIT course "Computer Systems Security". Lecture 4: "Separation of privileges", part 1
Massachusetts Institute of Technology. Lecture course # 6.858. "Security of computer systems". Nikolai Zeldovich, James Mykens. year 2014
Computer Systems Security is a course on the development and implementation of secure computer systems. Lectures cover threat models, attacks that compromise security, and security methods based on the latest scientific work. Topics include operating system (OS) security, capabilities, information flow control, language security, network protocols, hardware protection and security in web applications.
Today, we’ll talk about privilege sharing, since we’ve ended up with a buffer overflow at a certain level, but we’ll still go back to it. We will not talk about the details of how to use a buffer overflow, but switch to reducing this problem and talk about how to develop a system in which buffer overflow will not be a big problem for you, like other vulnerabilities. ')
So today we will talk about privilege sharing as a method to create a more secure system, and in the lecture materials we mention a web server called OKWS . This is not the most telling example of separation of rights, but the system is described there well enough to understand how all its parts work. But this does not mean that you should go right now, download OKWS and launch your website.
So, before we get into the details of OKWS and Unix permissions, let's just see what privilege sharing is and why is it such a good idea? Last week, James showed that if you write a program in C, you will almost inevitably have something bad or wrong in it. The problem is that if you have a large enough application and there is some kind of vulnerability present in it, then attackers can connect to the program, send requests to this application, trick it and do “bad” things.
Any application has access privileges. This means that it includes a lot of data that can be obtained with access. You can even delete these files, as you guys did in lab # 1. The problem is that a vulnerability in this large application may allow an attacker to change any of this data or to get enough privileges to manage the program if you are not careful. In this lecture, we look at what privilege separation is trying to do. It is necessary to take the program, divide it into parts and make sure that each of the individual elements has only the necessary privileges in order to properly perform their work.
On the left we have a program of 3 parts, and on the right data, also consisting of three parts. Properly assigned privileges mean that each part of the application has access only to its part of the data. And if we have a vulnerability of program X, then it will allow to take control of only one part of the data and will not be able to affect the data in the other two parts. So this idea of ​​privilege sharing is extremely powerful. It does not serve to specifically address the problem of buffer overflow or other vulnerabilities, it is just general requirements for the architecture of software products to ensure that vulnerabilities in one place of the system do not affect its other parts. Privilege sharing is quite common. So, to ensure the isolation of components within a program, virtual machines are often used.
You can take your large system and divide it into a bunch of VMs to isolate individual parts, but you can also use Unix to actually perform this isolation with "cutting." Unix provides quite a few mechanisms that OKWS actually uses to separate privileges.
Many applications actually use the privilege sharing practice. You guys probably used SSH, or "secure shell" quite often. This is a network protocol that is used for remote control of the OS and file transfer. He uses privilege separation in many of his components to make sure that his encryption keys are not solved and the server will not be compromised. More relevant for you is the Chrome web browser, in which privilege sharing is also implemented quite widely. So, if there is some kind of "bug" in the work of Chrome, the enemy will not be able to gain complete control over your computer.
This is a very brief summary of what privilege separation is and why OKWS is an interesting example. However, it is a more illustrative example than an important piece of software.
So OKWS , as I mentioned, will use Unix permissions and some sort of Unix mechanisms to separate the various components. It is important for us to understand how the Unix security mechanisms work. Unix as a tool for sharing privileges is not only important for understanding OKWS , it, like any other isolation tool, such as UID , VM , containers or any similar technology, allows you to understand the details of the process. Because there are many difficult parts of the process of obtaining access rights, and you can deal with an attacker who takes advantage of the vulnerability of any of these parts. Therefore, we will look at Unix in sufficient detail to understand what it is and how it should look in a particular security mechanism.
Perhaps, historically, Unix is ​​the best example of how to build a security mechanism. Its security mechanism arose in the process of satisfying the need to separate users from each other in a single Unix system. In this case, it was believed that there are a lot of users who use the same computer, and you need to keep them apart from each other. Thus, it is not necessarily a general purpose mechanism, but still one of the most common and widely used. So, Chrome is trying to use many mechanisms for the separation of privileges from Unix.
When you think about the protection mechanism, you should think about its principles, which mean that there is someone with privileges or rights, and Unix initiates or supports these rights. Therefore, I think that the subject, or subject, of Unix is ​​a process, since a process is supported, because every operation or request that we consider from a security point of view should be allowed or forbidden. This is likely to be an operation invoked by a process by making a syscall system call. What is important here is how we describe what privileges this process has.
Next, there is an object on which our process acts as a subject. He can modify objects, read them, watch them. In the OS there are many objects, the protection of which is worth worrying about. What objects do you think we should worry about?
Audience: about files!
Professor: correctly, about files and directories. What else?
Audience: About network sockets!
Prof: yes, great about network sockets. Anything else going on in the system?
Audience: other processes.
Prof: Right. In fact, this is similar to what the application or user should take care of, but there are different internal system components that you must also protect. Therefore, the process itself is not the subject that makes the system call, it is also something that another process can act on. He can kill him or create a new one. Therefore, you must find out what the rules of perception of the process as an object that can be manipulated are. What other things might worry us?
Audience: environment variables.
Professor: I think that they are probably not a subject that you can change, in the sense of controlling OC and having some kind of security policy. I think that environment variables are just a kind of state of a process contained in memory. But, I think, more generally, we are concerned about this part of the process that is contained in memory - environment variables, stacks, arguments, this is also quite important. Probably, in the memory of the process there are many things sensitive to interference from outside. What else?
Audience: file descriptors in general.
Professor: there is another internal circumstance that is of great importance. The files that are on the disk should worry us. But there is still such an operational tool as a file descriptor, which OKWS tries to use widely, and we will see what they are. What other things would you like to protect in the operating system?
Audience: hardware, or hardware.
Professor: yes, hardware requires no less protection than the abstract things that the OS provides us, we don’t want our processor to “freeze” for some reason when executing the program.
Audience: You should also consider protecting peripheral devices!
Professor: Oh, yes! So, additional devices, you are right, especially on a desktop computer, there are a lot of superfluous things there: a USB drive, a webcam, probably the display itself - you will want to protect some of this, because the applications connected with them should not “walk” "All over your screen.
I think, in fact, all these objects are not on the server side, they are just close enough to it. On your phone, a microphone is probably also a very important object that you also want to protect.
But I will leave this list, because then we will talk mainly about server applications, but you are absolutely right about the list of objects. I think for OKWS this is probably a more or less exhaustive list of things we could take care of, or at least used by OKWS .
So let's talk about how the OS kernel decides when a process can do something with any of these objects. Therefore, at a high level, we mainly think of the process as a subject having privileges granted by this principle, and the principle in the Unix system is a rather complicated thing.
There is something called User ID , which is a 32-bit integer. There is a group ID , which is also a 32-bit integer. In fact, there is no particular reason why they should be different.
It would be nice if they just made up a single set of 32-bit integers, but, unfortunately, Unix divides them into two categories. There are integers User ID , and integer values Group ID . When we talk about a process that has certain privileges, it means a process associated with a specific uid value. As a rule, a process has one uid , as well as a list of gid group identifiers that this process has. For historical reasons, it turned out that they are combined into one gid , and then combined into a list of other identifiers. Roughly speaking, a process can exercise the privileges represented by all these identifiers. So if the uid grants access to something, the process can do anything with it.
Now let's talk about files, directories and other types of objects. So what happens to the files, or rather, how to create Unix permissions for working with files? Everything is relatively simple with files, you are concerned about the operations you can do with them: reading, writing, possibly performing, as well as the ability to change the permissions themselves or other security properties.
Audience: breaking ties!
Professor: yes, disconnection, unlink - do you think this is a property of the file or directory itself? In fact, this distinction is a bit unclear. When Unix thinks about deleting a file, it is more concerned with the directory, because in Unix the file is really an inode , or inode. Therefore, in Unix, you can have several hard links to inodes and when you detach a specific Unix file name using unlink, you actually destroy only one of the file names, but it may have other names and other links to it. In fact, it is important whether you are allowed to change the directory pointing to the file and not to do anything with the inode of the file itself. So usually, the unlink , link , rename, and create operations are directory-related operations, so create affects both the directory and the new file. Therefore, we must find out which rules apply there.
In order to decide that someone can read or write a file, we are going to insert some permissions, or bits, into the inode file. In Unix, each inode , which is ultimately a file or directory, for security purposes has several interesting fields. Here is the user ID and the group ID, which, as we say, owns the file or owns the directory. Thus, you can manage all the files in your home directory because Unix has your uid . In Unix, there is also a set of permission bits that can be considered as part of a matrix, in basic design they look like r (read), w (write), and x (execute). We can specify these permissions for various subjects, and in Unix they are specified for the owner owner , that is, for the uid inode , for the group group that owns the file, that is, for gid , and for all others - other .
You can fill in this 3 by 3 binary matrix, where 1 means permission to perform a specific action, and 0 denies its execution:
This is how Unix stores permissions. There is a traditional way of coding these things, which you'll see often and which is probably worth mentioning. In Unix, this matrix is ​​encoded as an octal number, so each line here should be considered as the base number 8, so our matrix in this encoding will look like this: r is 4 bits, w is 2 bits, x is 1 bit, respectively, owner is this is 6 bits, and group and other contain 4 bits each.
You will often see such symbols in the lecture materials, so you can say that this file has a resolution of 6, 4, 4, that is, the owner can read and write the file, and the group owner and others can only read it.
These notations tell us when to read, write, and execute a file. What about changing the resolution for this file? This is not exactly a fair question, but what do you guys think about this? How should we decide that someone should be able to change these permissions, because this may also be necessary? Any thoughts on that?
Audience: if this person has access to the file?
Professor: perhaps it also depends on access privileges. On the other hand, you can create an overwritable rewritable file that you want to share with someone so that he can read, append, and modify your file, but then it also means that you can suddenly change permissions to make the file not rewritable or assign just myself.
Therefore, the creators of Unix decided that if you have a file, that is, your uid corresponds to the uid listed in the file, then by default you can change the permissions. Otherwise, you cannot. So if you only have gid and this group has all the permissions in the file, you still cannot change the permissions for this file. You can simply read, rewrite, do anything with it, but without the uid you cannot change the permissions.
Directories in Unix follow the same rules. Thus, detaching unlink and linking link records in a directory means having permission to write to that directory. If you want to rename a file, then you probably need to have rights to write to the directory where you get it from and to write to the directory where you put it. In some cases, hard links may cause problems, and these details are highlighted in the lecture materials.
In fact, in the catalog there is another interesting operation - search. Thanks to her, you can simply find the file in the directory. Unix encodes execute permissions as the ability to implement search for directories, so having execute permission for a directory actually means the ability to search for a specific file name. It may be that you do not need to have permission to the directory to search for the file name, but if you do not have permission to read, you cannot view the contents of the directory, that is, to find the file. This is useful in some situations when you need to restrict actions with some files or hide them from the user.
Let's take an example. What happens in Unix if I enter the open command ("/ etc / password") ? What does the kernel check on my behalf when I command it to make a system call?
Audience: does it check if you have permission to perform, etc.?
Professor: Yes, to a certain extent this is the case. I need to do something, etc.
Audience: and then perform the specified slash!
Professor: yes, actually I need to look at what / etc indicates? So if I don’t understand root permissions, it’s not going to work.
Audience: then you need to read / etc / password .
Professor: yes, it makes sense. Here is a little puzzle for you. Suppose MIT creates a group for all people associated with the 6.858 course, and other groups for all the TAs in MIT, which in Unix terminology is designated as gids , but they are not included in the 6.858 group of TAs for some silly reason. How can I create a file that will only be available for a group of 6.858 TAs?
Suppose I have 6.858 gid and TAs gid, but I can insert only one gid into the file.
Audience: you would not be able to do this, because here you can have TAs, not 6.858 TAs.
Professor: yes, that's true. Although there are students in the 6.858 group who are the TAs of other classes, so maybe this is not really cool. But, nevertheless, let's try to somehow make the intersection of these groups. For this we can use the permissions mechanism. /foo/bar/grades , foo , gid 6.858 . , , /foo . /bar , gid TAs, . /foo/bar/ , grades . , .