Hi, good discussions here in that mail thread, but with every response it gets harder to follow and keep the overview. Therefore I created a new wiki page https://wiki.ubuntu.com/SecurityTeam/Specifications/ScopesConfinement to keep track. I tried to summarize some of the discussions and put it there, but this is not complete yet. Feel free to add more or change/edit what I wrote so far.
Thomas On 08/29/2013 02:27 AM, Michi Henning wrote: > Hi Jamie, > > thanks for taking the time to write all this up! > > Lengthy reply interspersed below… > >> To increase scopes development velocity, the scopes team will be using ICE >> (zeroc-ice) for scopes. ICE normally uses TCP/UDP and opens a socket on the >> loopback interface. This is very problematic for application confinement >> because >> apps that are allowed network access (the default in the SDK) would be able >> to >> connect to any of the loopback listeners. There are a number of ways to solve >> this, but the most elegant is to implement a unix domain socket plugin for >> ICE. >> The scopes team have done this and with this change and all scopes adopting >> it, >> application confinement can prevent apps from attacking the system. > > The domain socket plug-in for Ice is working fine. With that, access control > could be implemented by placing the socket on which a scope listens for > queries into a directory specific to that scope, and then setting search > permission on or off for that directory based on UID/GID/others. (We have to > use permissions on the directory because bind() creates a domain socket using > umask permission. We cannot guarantee that this will be correct, even if we > set umask ourselves, because that's full of race conditions. We would need a > per-thread umask, which doesn't exist.) > > The domain socket path is not mandatory. I can change the scopes machinery to > use TCP instead by editing a few configuration files. No recompilation > necessary. In that case, scopes would listen on localhost on a specific port > for incoming requests (two ports actually per scope, for reasons having to do > with threading). In this case, we would have to administer port numbers > manually, so each scope uses fixed immutable port numbers, and then apparmor > would have to somehow decide whether a process is allowed to connect to that > port or not. > >> As for confining scopes themselves, this is a hard problem because some >> scopes >> will need wide access to the filesystem, some networking to other sites, >> many to >> canonical.com/ubuntu.com. There are a few things that are useful with the >> current design: >> * only Canonical-trusted scopes will likely be able to share a process > > Any scopes that "trust each other" can be collocated in the same process. For > example, scopes from the same author could run in the same process. Whether > or not scopes share a process does not affect the scopes implementation. How > to group scopes into processes is decided via configuration files. > >> * any scopes requiring authentication credentials needs to be in its >> own process (to prevent other scopes from accessing shared memory) > > Yes. Any scope that "has secrets" needs to run in its own process. When > installing a scope, we just put the scope into a group of its own, so it gets > run as a separate process. > >> * it is possible that we could make it a requirement that scopes from >> the appstore (ie, non-Canonical scopes) must be in their own process > > I see no other option. Anything that's installed from a click package or > something like that must end up running as a separate process. > >> * we can trigger manual reviews for scopes in general, or scopes that >> need more flexible confinement. This is not optimal because we are striving >> for as little code-reviews as possible in the app store because it just >> doesn't scale. > > I agree. Less of this is better. > >> * we are able to revoke scopes from the app store if they are malicious > > Right. But that's no different from applications, really. And, of course, > once installed, a malicious scope or application can continue to do damage. > >> * appstore ratings will help self-regulate >> >> A few things not in our favor: >> * scopes can by design do anything > > Yes. There is nothing we can do about this. The scope is a shared library > that we load at run time with dlopen(). I cannot control what actions are > taken by the code I call in that library. > >> * scopes can be aggregated in any number of ways >> * due to aggregation, scopes are supposed to be able to communicate >> with arbitrary other scopes >> * even local scopes may be required to access canonical.com/ubuntu.com >> servers for side channel communications for recommendations > > At the very least, scopes will need to be able to reach the smart scopes > server, issuing REST request over HTTP. This appears to be non-negotiable. > > For scopes running on the local device, if we do not allow them to access the > network, they will be limited to producing information that can be found in > the file system only. But that has serious drawbacks. In particular, I could > not do things such as make a scope that, say, shows me recent emails from my > imap server or that connects to a news site behind a paywall and feeds me > headlines. > > The *only* way to run a scope that gets data that requires login credentials > is to run the scope locally. (Remote scopes cannot do anything that requires > authentication for a particular user.) But, pretty much by definition, if I > run something locally and it needs a password, this means that the local > thing is going remote with that password… > > Ideally, it should be possible to, on a per-scope basis, configure > permissions that specify where a process can and can't connect to. That way, > we could limit a scope to only connect to data sources that are legit, rather > than being able to roam the net at will and funnel away confidential > information. > >> Confining individual scopes requires a lot of thought and discussion. Some >> (non-exhaustive) discussion points: >> * can we agree that app store scopes must always run in their own process? > > I consider that a given. We can't collocate scopes from different authors. > Even disregarding the security implications, it makes sense not to collocate > just as a protection against bugs. If one scope has a bug and segfaults, > it'll take down all its collocated scopes with it… > >> * can we agree to kill a scope and all of its children if the scope is >> disabled >> or if the privacy setting is toggled to 'on' > > I cannot know what the children of a scope are. The scope can fork/exec and > damonize itself, and there is nothing I can do to stop that. I cannot use > process parent/child relationships to track this, for example, and I don't > think there is any other reliable way. > > If a scope is disabled, we can set the permissions on the directory for its > incoming sockets to 000, so no-one can connect to that scope anymore. But > that's about it. We'd have to make sure that the directory is owned by a > special scope user ID, obviously. > >> * can we agree that scopes must use the unix domain socket ICE plugin? How >> can >> we enforce this? (We should be able to prevent 'bind' for TCP and UDP using >> AppArmor IPC mediation, but perhaps the scopes architecture enforces this) > > The scopes architecture can't enforce anything. If the scope makes a system > call, I can't stop it. > >> * do we imagine that most scopes won't need filesystem access beyond what app >> store apps typically would need? (essentially read access to the install >> dir >> and write access to app/scope specific directories following the XDG base >> dir >> specification). If so, we may be able to treat these scopes like ordinary >> click apps (using a different AppArmor policy template though) where the >> reviews are/will be automatic. > > Some scopes deliver music and video content. Basically, they index media > files in the local filesystem. This means monitoring mounts, checking the > contents of removable media, looking in a number configurable locations for > music files, etc. Generally denying file system access to such scopes will > make them unusable. > >> * A big problem is that some scopes are expected to have access to other >> parts >> of the filesystem. What is to stop a malicious scope from sending all the >> user's data off to the internet? Would it be possible to say that if a >> scope >> needed filesystem access like this, it is not allowed to connect to the >> network at all? (ie, either have networking/very limited filesystem access >> or >> no networking/less limited filesystem access). This seems quite tricky to >> get >> right > > Seems like a good idea, buy I'm not totally sure of all the implications of > this approach. There may well be a security hole in this policy that I'm not > seeing at the moment. > >> * can we clearly define how aggregation works and how app store scopes are >> intended to participate in aggregation? Would it help if we said that app >> store scope can only be an aggragatee and not an aggregator? I don't have a >> handle on aggregation yet to understand all the security implications.... > > A scope is simply a data provider that responds to queries that arrive via > its network endpoint. The scope is not aware of the identity of the query > source. I cannot stop a scope from aggregating from another source. What the > scope does is up to the scope author. The only way to prevent scope A from > aggregating from scope B is to make it impossible for A to connect to B's > endpoint. As far as I can see, the only mechanism we currently have to > enforce this are the file system permissions on the directory that contains > the socket. > >> = Issue #2: scopes privacy = >> Related to confining scopes is enforcing network access based on the privacy >> setting. The good news is that the new design for 14.04 doesn't require that >> scope authors write code to honor the setting. Instead, if privacy is toggled >> on, scopes simply aren't sent the request for data. Individual scopes can >> also >> be toggled on and off so when a scope is disabled, it isn't sent any data. >> This >> does not handle malicious scopes that access the network directly however-- >> ie, >> a scope that ignores SIGTERM/SIGSTOP and keeps running behind the scenes to >> shovel data over the network). > > There is no difference between a privacy setting and the on/off setting, as > far as I can see. Whether the scope process is running or not is really a > secondary issue here. A scope that no-one can connect to is basically the > same as a scope that isn't running at all. > > As far as making a scope go away (in the sense of killing it), I believe this > is impossible. We cannot know when the scope does a fork/exec, for example > (unless apparmor can prevent that). If we indeed can use apparmor to prevent > fork/exec, I need to know about it at least. Currently, I don't need > fork/exec for what I'm doing. But I was thinking of possibly daemonizing the > scopes processes. (Not sure yet whether that's really desirable.) If we > daemonize, I will need fork (but not exec). In addition, the current > daemonize_me() implementation uses /proc to close open file descriptors. > That's way more efficient that trying to close open descriptors by calling > close() on MAXFD file descriptors. If apparmor prevents access to /proc, we > could change that part of the code to do the inefficient way. (Unfortunately, > there is no reliable way in Unix to say "close all file descriptors > 2", or > even "give me the largest open file descriptor".) > >> To deal with both well-behaved and malicious scopes, there was the idea of >> toggling between mostly-permissive AppArmor profiles to turn networking on >> and >> off. Local scopes would always be off while smart scopes get toggled based on >> privacy setting. This would work for 13.10 but is greatly complicated going >> forward because networking is pretty much always needed for the side channel >> communications. > > Smart scopes, by definition, have no privacy issues. Anything that runs on > the smart scopes server can only deal in public information because there is > no way to get per-user authentication data from the device to the SSS. Any > credentials that a scope running on the SSS requires would have to be > hard-baked into that scope. > >> Perhaps the design is sufficient to address scopes privacy though-- disabled >> scopes aren't ever called/aggregated and the scopes architecture prevents >> sending scopes data when the privacy setting is off, so a malicious scope >> can't >> override being disabled or the user's privacy setting. We can add to that >> SIGKILL for it and its children when it is disabled or the privacy setting is >> toggled to on. > > I can see the following options: > > - No-one but Canonical (and trusted third-parties, such as OEMs) can install > a scope on the device. That way, we can vet every line of code we execute. > Problem solved, at the cost of making it impossible to install scopes from > click packages. > > - By design, scopes are meant to be able to do things that are security > sensitive, such as logging into an imap server. (Such scopes *must* run > locally.) If we want to prevent one scope from snooping on another, it seems > we are restricted to what we can do with file system permissions and apparmor. > > Following up on the second point: > > - If a local scope has network access, that essentially means we must deny > that scope file system access (except maybe for a carefully selected subtree). > > - If a local scope has file system access, we must deny that scope network > access, otherwise, it can funnel away data (unless we write the scope > ourselves of course.) > > - For aggregating scopes, we have to prevent privilege escalation. I am not > sure whether this is achievable by using only file system permissions and > apparmor. But, basically, if a scope that delivers sensitive information > (either from a remote source or from the file system) can be spoken to by > another scope that then can stash the data away in Russia, it's game over. > > Another option we could explore is to run Ice over SSL. Ice has an SSL > transport and, with appropriate certificates, we can control exactly who can > connect to whom. What worries me about this scenario is the complexity. We'd > have to generate certificates on the fly during installation, protect those > certificates and keep track of them, generate the necessary configuration on > the fly, etc. This is really complex and, even if we get it right > technically, it could be very difficult to be sure that the end result is > still secure. One little setting incorrect somewhere, and we have a hole… > > The real problem here appears to be not so much the technical issues around > controlling access to network endpoints and the like, but the design. > Application confinement works because applications are isolated from each > other. The idea of aggregation is anathema to that. > > But, even if we remove the idea of aggregation altogether, we still have this > problem. As long as there is IPC involved, we have network endpoints that are > potentially vulnerable. In theory, a scope could cobble network packets > together by hand and issue a request to an Ice endpoint without using any of > the scopes or Ice runtime at all… (It's not difficult to do this.) > > It seems the entire thing boils down to two points: > > - If we use IPC, we need to be able to control who can talk to whom. > > - Given that, we then need a policy that decides who can talk to whom, to > stop privilege escalation and leaking of data. > > If we assume that the first problem is solved, are we confident that we can > come with a suitable policy? If not, we need to go back to the drawing board. > > Michi. > -- ubuntu-devel mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/ubuntu-devel
