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

Reply via email to