OKWS ==== background: web service architecture with apache clients -> apache -> application code -> database apache, app code runs as the "www" user app code: fetch/change user profile, send message, find friends database often runs as a separate user (maybe on another machine) however, SQL interface to the DB allows app to access all the data what's the policy the paper is trying to uphold? dating web site: mostly about data secrecy doesn't sound like they're as concerned with integrity of data if attacker sends spam from the server, not a big deal what attacks might we worry about? bugs in Apache that let attacker execute code (buffer overflow, etc) bugs in application code that let attacker execute code (buffer overflow) bugs in application code that let attacker bypass protection SQL injection, missing access checks attacks on the browser okws concerned with attackers compromising server-side components (all of the above except for browsers) can we avoid the problem in the first place? avoid storing really sensitive data online credit card #s: store last 4 digits or conf# instead of entire cc# this is reasonable in some cases (e.g. microsoft's private key) separate web servers two physical machines, completely separate systems or maybe separate VMs, firewalls, etc when doesn't this work? sharing of data, e.g. okws's example of a dating site login (pw checking) sending messages (lookup email) finding other people (lookup other personal data) would rather not have to register with 3 different systems for this! even more: if i change my name in one, should propagate to others what's the okws plan? "aspects .. most vulnerable to attack are the least useful to attackers" overall idea: principle of least privilege break up the system into many components minimize privilege needed by/available to each component (privilege, like "trusted", is a bad thing from a security viewpt) why is this hard? hard to minimize needed privileges code written in a way that requires many diff privileges throughout redesign app so code needing each privilege is separated hard to minimize available privileges unix, SQL do not have great mechanisms for controlling privileges background: Unix protection mechanisms uid/gid file system access, kill/debug other processes (same uid) bummer: everyone can access large portions of FS (/tmp, /etc/passwd) only root (uid 0) can change the uid/gid of a process once process has non-zero uid, cannot change it setuid binaries exception: an executable might have a special "setuid" flag set on it means: when executed, run with uid of file owner instead of caller typical use case: setuid binaries owned by root programs like login, su, passwd, .. Unix has many such programs, because root needed for many things common problem: caller controls many things about process controls all arguments controls environment variables controls working directory hard to write safe code for these setuid applications need to be paranoid about almost everything in your environment! libraries you might want to use are not sufficiently paranoid chroot assumption: setuid binaries are vulnerable and unavoidable need to prevent compromised processes from exploiting them mechanism: change root directory, so process cannot name those programs chroot /var/okws/run /bin/sh /tmp in this chroot'ed process maps to /var/okws/run/tmp only effective for non-root users: root can escape chroot in many ways kernel trusts root to do many things, incl read/write kernel memory f=open("/"); chroot("/tmp"); fchdir(f); chdir("../../.."); also helps avoid the large amount of default-accessible files file descriptors process has handles to kernel objects it can read/write, called FDs can always read/write file descriptors you have, regardless of uid/gid FDs can refer to files, network connections, or pipes to other procs can pass these handles across pipes (socketpairs really) network access all processes can equally talk to the network only root can listen on "privileged" ports (< 1024) okws design how does OKWS partition things? should each service run in a separate process? should each user run in a separate process? how should each service access the data? how does okws achieve this partitioning? separate uid + process for each service main server code also partitioned into functions log, launch, dispatch, files chroot to prevent processes from accessing extra files RPC between processes db proxy limits data access interface figure 1: process diagram how does this overlay onto machines? many front-end machines run everything but the db proxies and DBs DBs run a number of db proxies (for each "view" of the database) how does a request get processed in this model? accepted by okd okd reads the first line of req, figures out which service to use okd logs request, sends file descriptor to that service service reads rest of HTTP request, uses dbproxy to process service may need HTML templates -- fetch from pubd and cache service logs request, sends response back to user where does web user authentication happen? probably there's a login service that checks user passwords gives user's browser a cookie that other services will accept does this mean that if you compromise one service, you can take this cookie and impersonate user in other services? why do we need a db proxy? why not a separate DB for each service? presumably some (but not all) data shared between services what's the point of dbproxy tokens? want to ensure only authorized processes get access (i.e. want to ensure only the right arrows in our diagram exist) within the OS, kernel enforces this, but need sth else between machines so each service gets tokens for only the dbproxy's it needs to access why not process per user? per user * service? expensive in terms of performance (would also need some scheme for DB access control) what's the difference between the dbproxy and the service itself? potentially a fuzzy boundary service might generate HTML (but modern browsers can run JS to do this) service might have code that accesses more data than client should see (but even if service compromised, dbproxy prevents all DB from export) table 1: why not have a separate chroot directory for each service & okld? okld needs to set up directory for each service not many files of interest in /var/okws/run (as opposed to oklogd, pubd which have interesting files) doesn't seem like there's something deep here table 1: why have a separate UID for each service? why separate GID? separate UID to prevent kill, ptrace, etc between services separate GID to grant file execute perms w/o giving file ownership towards the end of sec 4.1: owner root, grp svcgid, perms 0410 does okws achieve its goal? what are the components we should consider? [client] okld okd pubd oklogd service dbproxy [database] what's the effect of each component being compromised? okld: root! everything on that machine. maybe not complete database access though. okd: can intercept/modify all user HTTP reqs/responses, steal passwds bad but maybe can't access data of users that didn't log in pubd: can corrupt templates, maybe leverage to exploit bug in svc? oklogd: corrupt/ignore/remove/falsify log entries service: send garbage to user, access data for svc (what dbproxy allows) dbproxy: access/change all user data in the database it's talking to likely one database and many dbproxy processes possible to have multiple databases altogether what's the "attack surface" of each component? okld: signals that a child process has died okd: parsing the first line of HTTP request pubd: requests to fetch templates from okd, svcs oklogd: log messages from okd, okld, svcs service: HTTP requests from users (and control msgs from okd) dbproxy: requests from services requests from unauthorized services (though easily discarded) how does okws compare to apache? apache doesn't run anything as root (how does it bind to port 80? how does okd do the same?) okws adds some complexity due to structure, C++ okws still doesn't protect different web users from each other plausible that okws is more secure neither really addresses attacks on clients/browsers how would you compromise this system? exploit buffer overflow or the like in C++ code okd can be used to steal user credentials service can be used to steal all data available to svc maybe try to find a SQL injection attack in some dbproxy could we improve the security of okws? get rid of okld running as root? maybe have each other service be a setuid-user binary? problem: one service should not be able to invoke another need to ensure only okld (and not others) can start it. could use groups for permissions why didn't okws do this? problem: if service owns file, can change permissions! not a huge win even if we could solve it somehow still need to set up setuid binaries as root ahead of time okld also twiddles around with the file system as root still need to initially start as root to listen on port 80 separate web users from one another? can the OS make it easier to privilege-separate applications like this? probably -- lots of people have tried, could make a nice final project next lecture is about one such system (Flume)