Class 23 (Make-up; video-recorded) CS 202 1 May 2015 On the board ------------ 1. Last time 2. Protection and security in Unix --Intro --The Unix protection model --Setuid --[next time] TOCTTOU --------------------------------------------------------------------------- 1. Last time --stack smashing 2. Protection and security in Unix A. Intro --why security in the OS? managing resources for different applications must protect different users from one another file system memory processes --access control matrix (conceptual construct) File 1 File 2 File 3 .... User 1 r/w User 2 r User 3 w --don't maintain matrix manually or entirely --use tools such as groups or role-based access control individuals roles resources x r1 a y r2 b z c [lots of diagonal lines between but not across columns] B. The Unix protection model --designed for specific purpose: multiple users time-sharing a Unix system. here's the security model: [ON THE BOARD] (i) UIDs and GIDs (ii) access control on files, per UID and per GID (iii) special user: root (UID=0) to which access control doesn't apply (iv) privileged operations only root can do (v) some implicit privileges (i) process has a user ID and one or more group IDs (ii) access control on files --system stores with each file --user who owns the file and group that file is in --permissions for user, anyone in the file's group, and other --can see this by doing "ls -l": rw- rw- r-- .... basic operations: read, write, execute [rwx] --which permissions apply? --if process's UID matches , then user permissions --if process has GID matching , then group permissions --otherwise, 'other'. --directory has permissions too --"read" means, roughly, "can list files in this directory" --"execute" means, roughly, "can use pathnames in this directory" (iii) uid 0, called root, treated specially by the kernel as administrator --uid 0 has all permissions --how do uid's get set? setuid() call uid=0 can change to any other uid other uid's cannot invoke setuid(), to a first approximation --Unix login runs as root checks username, password against /etc/shadow calls setuid(user), runs user's shell --Here's more detail on login --Unix users typically stored in files in /etc --key files include "passwd", "group", and, often, "shadow" or "master.passwd" --purpose of shadow file is to separate the material that needs to be user-visible (list of users and UIDs on the system) from the cryptographic material. passwords are never stored in the clear, but you don't want to expose "shadow" to users. they could then easily conduct an offline dictionary attack. making the shadow file non-world-readable addresses that. --for each user, the files contain: --the textual username (for example, "mwalfish" or "root") --numeric user ID and group IDs --one-way hash of user's password: (salt, H(salt,pasword)) [salt makes it harder to break many passwords at once: attacker who is working on the password file offline cannot just compare the hashes to pre-computed values; the attacker must, for each entry, pump every password through the hash function.] --other information, including user's full name, login shell, etc. --/usr/bin/login runs as root --Reads username and password from terminal --Looks up username in /etc/passwd, etc. --Computes H(salt, typed password) and checks that it matches the hash in the "shadow" or "password" file --If matches, sets group ID and user ID corresponding to username --Execute user's shell with execve system call --Unfortunately, this security model (where uid 0 can do anything) leads to lots of privileged code, which in turn means that bugs are particularly dangerous. --Here's an example that uses login. Consider that on some systems, rlogind (remote login) runs as root. --The "login" command takes a flag, "-f" which means "don't ask for password". If the flag is supplied, the login succeeds only if the requested username is the current user, or if the current user is root. Unfortunately, rlogind runs "login username". Attack: at the login screen, pass user "-froot". So it looks like this: login: -froot [no password] # Why this worked on that buggy system: rlogind then runs: "login -froot" login sees "-f" flag and asks, "Is the requesting user the same?" (Answer: yes. Both login and rlogind are running as root here.) (iv) there are certain operations that only root can do Examples: --binding to ports less than 1024 --change current process's user or group ID --mount or unmount file systems --opening raw sockets (so you can do something like ping remote machines, for example) --set clock --halt or reboot machine --change UIDs (so login program needs to run as root) [Problem: you need to have all of root's permission to do *any* of these things (yes, can drop privileges, but we'll see that's easier said than done). That is a *lot* of privilege to do any one action. That is problematic for reasons we'll see.] (v) some implicit privileges --file descriptors, etc. --fork() gives parent ability to control child, etc. --can ptrace() processes at same UID (sort of) result: everything is a bit incoherent C. Setuid --Some legitimate actions require more privs than UID --E.g., how should users change their passwords? --Passwords are stored in root-owned /etc/passwd and /etc/shadow files (see above) --going to go into a bit of detail. why? because setuid/setgid are the sole means on Unix to *raise* a process's privilege level --Solution: Setuid/setgid programs --special "setuid" bit in the permissions of a file --Run with privileges of file's owner or group --Each process has _real_ and _effective_ UID/GID -- _real_ is user who launched setuid program -- _effective_ is owner/group of file, used in access checks --for setuid programs, on exec() of binary, kernel sets effective uid = file uid --examples: [mig ~]$ ls -l `which ping` -rwsr-xr-x 1 root root 35680 2010-03-12 05:41 /bin/ping* [my-local-computer ~]$ ls -l `which passwd` -r-sr-xr-x 1 root wheel 70352 Jun 18 2009 /usr/bin/passwd* [note the 's'] --Obviously need to own file to set the setuid bit --Need to own file and be in group to set setgid bit --(idea: a way for root -- or another user -- to delegate its ability to do something.) --Examples: --/usr/bin/passwd : change a user's passwd. User needs to be able to run this, but only root can modify the password file. --/bin/su: change to new user ID if correct password is typed. --/sbin/ping: users need to be able to ping but only root is allowed to open "raw sockets" (example of incoherent security model; but very hard to fix) --Have to be EXTREMELY careful when writing setuid code [Imagine that you are writing or installing a setuid program. In other words, you are willing to let that program run with *your* privileges.] --Fundamental reason you need to be careful: very difficult to anticipate exactly how and in what environment the code will be run....yet when it runs, it runs with *your* privileges (where "your" equals "root" or "whoever set the setuid bit on some code they wrote") --NOTE: Attackers can run setuid programs any time (no need to wait for root to run a vulnerable job) --FURTHER NOTE: Attacker controls many aspects of program's environment --Example attacks: --Close fd 2 before execing program --now, setuid program opens a file, for example the password file.... (normally, would be fd=3, but because fd 2 was closed, the file will be given fd 2). --then, the program later encounters an error message and does fprintf(stderr, "some error msg"). --result: the error message goes into the password file! --fix: for setuid programs, kernel will open dummy fds for 0,1,2 if not already open --Set maximum file size to zero (if, say, setuid program changes a password and then rebuilds some password database) --[more next time]