[MUSIC] And in this one, we're going to talk about running subcommands, spawning subprocesses. Now, why is this a security issue? Well, many, many years ago, on a system that I worked on, games were extremely popular, and all of them had what was called an escape. So you would be playing your game, and if you wanted to do type commands, you would then type a specific character. And then you could just, it would give you a command interpreter, and you could just do whatever commands you wanted. The problem was people at this place were very competitive so we had the high score files. And in order to write to the high score file, the game had to be a privileged user, in this case it was root. Well one of the graduate students found out that when you spawned the command interpreter the UID was not reset. So, in essence to become root, what you would do is find a game with a high score file, start up the game, immediately type that character to get to that command interpreter and presto, you're now the system administrator That was not good, we'll talk about how to fix that in a moment. It's not just games that have this problem, system programs did as well. On one system, when the system crashed, it would save memory in a core dump, of course. And then you could use a program called crash to analyze the core dumps. Crash was not privileged user, it ran as you. However, in order to do the analysis, it needed to be able to read memory. So to prevent a user from accessing things other than memory, that the representation of memory was a file and that file was owned by a group called kmem. The crash program was run setgid to kmem. So, it ran as for example, Bishop, but the group was kmem and that group could read memory. Same problem, when you spawned the subshell, it didn't reset the GID. So I could then spawn a subshell, a command to interpreter, and then I could go in and since kmem could write to memory, I could go in and alter contents of the computer's current memory. This includes my UID, I could change that to 0 and all of a sudden I am root. Or I could look at what other people were typing, or I could delete data from their program's memories, or you could alter their programs. So that was a very serious problem. The point is, identity is more than just the user, it's also the group and you have to be aware of both of those. The reason these problems arise is because when you spawn a program, the privileges, or the rights, are preserved across that spawning. For example, on Linux, the system call to spawn a subcommand is some variant of exec, execve, execvp, execlp, execl, whatever. And that doesn't change the UIDs or the GIDs. So if I'm running a privileged program and then want to run an unprivileged sub program, my program has to do the resetting. Now the way you typically do this is first of all you split the program, you fork it into two processes. The newly created process, the child one, is still running with the program's privileges. You use setgid to change the GID to something safe, then you use setuid to change the UID to something safe, then you spawn the subcommand. And here are some general guidelines. If you're running a privileged program, UID or GID, the slide here says UID, first of all, apply the principle of least privilege. If you don't need a privilege, get rid of it. Drop to the lowest level of privilege you need to complete your task. And as I said earlier with the FTP example, if you do need to upgrade privileges temporarily, use the saved UID idea. So your program is running as root to do its task, then you drop the privileges and change it, for example, to Bishops. Now, the UID route saved as the saved UID and so now I can flip back to that when I need it, when they need it. A third rule of thumb, and this is critical, don't allow users to run arbitrary programs from within privileged programs. If you want them to be able to run programs like a command interpreter or whatever, then drop privileges first. Because if the users can run arbitrary programs, you can't control what they're going to do. Whereas if you drop privileges then the only thing they can do is what they could normally do anyway. The key point here is that you do the resetting after you do the split, after you do the fork, and do it unless it is absolutely essential to keep the privileges. Now many systems of library functions that will do this sort of thing for you, that would spawn subprocesses automatically. On Linux the tool are popen and system. On some versions of Linux, these will automatically drop privileges, but on others they won't and I would not depend on it. In general, avoid using those functions when you're dealing with privileged programs Okay, so how should you identify users? Well, there are a couple of system calls to do this. If you want the real user, that is the identity of the user who's running the program, use getuid, that gets you the real UID. If you want to know the identity of the user who's privileges the program is running with, use geteuid, that's the effective UID. And now this next one is tricky, if you want to know who the user is logged in as. Some systems in section two of the manual have a system called call get login and you can use that. But it's imperative you get the system call and not the library function because the system call will give you the correct identity of the user who logged in. However, the library function doesn't work that way. The library function get log in, it lets you see who is logged into the terminal that the standard input is coming from. If it's getting input from a file then it looks to see who is logged into the terminal where the standard output is going. If that's going to something other than a terminal, it looks to see who is logged in on the terminal where the error messages are going. And if those are going in a file, then it will give you a null, meaning it won't be able to figure out who has logged in. But the point is who's logged in at the terminal or who's working at the terminal may not be the person who is running the program. And as a result of that, you may get the wrong identity or the wrong privileges. cuserid is a variant of that, by the way.