Class 24 CS 202 5 May 2015 On the board ------------ 1. Last time 2. Protection and security in Unix, continued --[last time] Intro --[last time] The Unix protection model --Setuid --TOCTTOU 3. Other thoughts on security --------------------------------------------------------------------------- 1. Last time described setuid BTW, where do you think a file's owner, group, setuid are stored? --dir entry? --inode? 2. Protection and security in Unix, continued A. [last time] Intro B. [last time] Unix protection model C. Setuid --Example attacks: --a program called "preserve" installed as setuid root; used by old editors to make a backup of files in a root-accessible directory --preserve runs system("/bin/mail"). --"system" uses the shell to parse its argument --now if IFS (internal field separator) is set to "/" before running vi, then we get the following: --vi forks and execs /usr/lib/preserve (IFS is still set to '/', but exec() call doesn't care) --preserve invokes system("/bin/mail"), but this causes shell to parse the arguments as: bin mail --which means that if the attacker locally had a malicious binary called 'bin', then that binary could do: cd /homes/mydir/bin cp /bin/sh ./sh chown root sh # this succeeds because 'bin' is running as root chmod 4755 sh # this succeeds because 'bin' is running as root --result is that there is now a copy of the shell that is owned by root and setuid root --anyone who runs this shell has a root shell on the machine --fix: shell has to ignore IFS if the shell is running as root or if EUID != UID. --also, modern shells refuse to run scripts that are setuid. (the issue there is a bit different, but it is related.) --ptrace() example What is ptrace()? It's a system call, used by debuggers Lets one process modify another's memory Attack 1: --attacker ptraces setuid program P --P runs with root's privileges --now manipulate P's memory, get arbitrary privilege on the machine. this is bad. --fix: don't let process ptrace more privileged process or another user's process for example, require sender to match real and effective UID of target Attack 2: --attacker owns two unprivileged processes A and B. --A ptraces B. so far, so good. no violation of the rule above. --Then B execs a setuid program (for example, "su whatever"), which causes B's privilege to be raised. (recall that the "su" program is setuid root. "su pat" becomes user "pat" if someone types pat's password.) --Now A is connected to a process that is running with root's privileges. A can use B's elevated privileges. This is bad. --fix: disable/ignore setuid bit on binary if ptraced target calls exec() --> but let root ptrace anyone Attack 3: --now, say that A and B are unprivileged processes owned by attacker --say A ptraces B. so far, so good. no violation of prior two rules. --say A executes "su attacker", i.e., it's su'ing to its own identity --While su is superuser, B execs "su root" --remember, the attacker programmed B, and can arrange for it to exec the command just above. --BUT! remembering the ptrace rules above, the ptrace succeeds. the reason is that at this moment A is the superuser, so no problem with B's exec() honoring the setuid. --attacker types password into A, gets shell, and now this (unprivileged) shell is attached to "su root". --the attacker can now manipulate B's memory (disable password checks, etc.) so that the "su root" succeeds, at which point A is connected to a root shell See Linux Yama module as a partial defense: https://www.kernel.org/doc/Documentation/security/Yama.txt Another issue: --consider a setuid process that does a bunch of privileged things and then drops privileges to become user again --should be okay, right? *****--NO. once the process has seen something privileged and then become the user again, it can be ptraced(), and the confidential things it has seen (or the privileged resources that it holds) can be manipulated by an unprivileged user.**** --fix? make software much more complicated. separate a single process into separate ones, for example. D. TOCTTOU attacks (time-of-check-to-time-of-use) --very common attack --say there's a setuid program that needs to log events to a file: fd = open(logfile, O_CREAT|O_WRONLY|O_TRUNC, 0666); --what's the problem? --setuid program shouldn't be able to write to file that user can't. thus: if (access(logfile, W_OK) < 0) return ERROR; fd = open(logfile, ....) should fix it, right? NO! --here's the attack........ setuid program attacker creat("/tmp/X"); check access("/tmp/X") --> OK unlink("/tmp/X"); symlink("/tmp/X", "/etc/passwd") open("/tmp/X") --from the BSD man pages: "access() is a potential security hole and should never be used." --the issue is that access check and open are non-atomic --to fix this, have to jump through hoops: manually traverse paths. check at each point that the dir you're in is the one you expected to be in (i.e., that you didn't accidentally follow a symbolic link). maybe check that path hasn't been modified also need to use APIs that are relative to an opened directory fd: -- openat, renameat, unlinkat, symlinkat, faccessat -- fchown, fchownat, fchmod, fchmodat, fstat, fstatat Or Wrap groups of operations in OS transactions --Microsoft supports transactions on Windows Vista and newer https://msdn.microsoft.com/en-us/library/windows/desktop/bb986748%28v=vs.85%29.aspx --research papers: http://www.fsl.cs.sunysb.edu/docs/valor/valor_fast2009.pdf http://www.sigops.org/sosp/sosp09/papers/porter-sosp09.pdf E. Thoughts / editorial --at a high level, the real issue is not ptrace. it's not even buggy code. the real issue is that the correct version of the code is way harder to write than the incorrect version: --correct version has to traverse path manually --be super-careful when running as setuid --cannot just blame application writers; must also blame the interfaces with which they're presented. --rules are incoherent. not clear how permissions compose --for all that, Unix security is actually quite inflexible: --can't pass privileges to other processes --can't have multiple privileges at once --not a very general mechanism (cannot create a user or group unless root) F. Other issues: can create hard link to any file, even if we can't read or write it attacks: 1. keep around buggy setuid code --attack: create local hard link to buggy code (call it something innocuous so no one notices). now you can keep using it as an attack vector, even after root rm's the buggy version and installs the fixed version. the attacker keeps using it through the innocuous name. 2. keep around sensitive data --attack: use hard links to keep a copy of sensitive data around. then, later, if you are able to obtain root access, you can read the data. --another issue: (used to be) easy to escape from chroot with uid=0 fd=open("/"), chroot("/tmp"), fchdir(fd), chroot("./../../../..") 3. Other thoughts on security A. Question: can you ensure privacy through encryption? --answer: DEPENDS ON THE THREAT MODEL (and what you mean by privacy). --what if you know that two nations are talking? --what if you know that Coca Cola is talking to bankruptcy lawyers? (sometimes, you don't need to know *what* information is being relayed. sometimes, it's enough to know that two parties are communicating.) B. What about CAPTCHAs? (as an example of another security technique....) --can't work in every case: bot the human's computer, solve the CAPTCHA, ship somewhere else C. Why isn't gmail encrypted? D. Airport security --threat model? [thanks to David Mazieres, Nickolai Zeldovich, Robert Morris for some of sections 2, 3]