NGWS SDK Documentation  

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

Types of isolation

Basic kinds of identity used in scoping isolated storage are as follows (with details following):

  1. user – authenticated user identity, or a unique “anonymous” user if none.
  2. domain – domain isolation is based on evidence associated with the application domain:
    • web applications identity is taken from their URL site (e.g. “http://www.microsoft.com”);
    • shell hosted code identity is based on the application directory path (e.g. “C:\office”).
  3. assembly – code is identified cryptographically by strong name or publisher
    • strong name – strong name identity (e.g. Microsoft.Office.* or Microsoft.Office.Word)
    • software publisher – software publisher identity (based on public key, like identity perm.)

NOTE: The terms ‘domain’ and ‘assembly’ are used to denote these specific identities in the remainder of the document.

First-time readers should not be daunted by the variety of identities used to scope data compartments. The “80%” case anticipated for all V1 isolated storage use is just going to be “user+domain”, that is: by application for a particular user. So when you use “app1” it has its store, and “app2” has its; other users of these same applications even on the same machine will get separate places for their data.

Machine containment

All isolated storage is contained by machine – that is, storage is not shared between machines, nor is data accessible across machines with this storage feature. (Inter-machine storage can be constructed on top of the basic functionality provided, but is not a goal of this feature itself.)

Machine containment is always implicit, by virtue of using storage facilities local to a given machine. The identity of a particular machine is never exposed by use of this feature.

Clarification: machine containment is described here in the sense that all user containment is implicitly scoped to the local machine code runs on.
For example, if Alice and Bob use an app on the same machine that app would use separate isolated stores for them. Then if Alice runs the same app on another machine she will get a different store there that is different from that on the first machine. This is the sense in which machine containment encompasses user.

<PUNT!> This spec uses the term “machine” compartment to refer to only machine containment irrespective of user, as opposed to what is actually machine+user containment which is denoted by the less cumbersome term “user”.

User containment

Isolated storage is contained by user in all but the most highly trusted level (level 3, below) of usage. User containment is important to ensure that information is never leaked from one user to another by means of this feature. The location of storage for user isolated storage is determined by the platform OS notion of user identity for the process the code is running in at the time the store is opened. Impersonation changes the notion of ‘current OS user’ dynamically.

User containment is always implicit, by virtue of using storage associated with a given user. The identity of a particular user is never exposed by use of this feature. On the Windows platform, user’s profile directory is where IsolatedStorage data is stored. (See data storage section following for details.)

On platforms that do not support different user login identities there is only one common user identity: effectively user containment is synonymous with machine containment in this case. Nevertheless, from a permission enforcement point of view this single user identity is still a user identity – in other words on these platforms, level 1 (below) isolated storage permission will allow use of this single (same as machine) user container.

Domain containment

Domain containment is based on evidence associated with the application domain the code is running in. As noted above, it is important to provide this IsolatedStorage containment even if based on a weak identity such as DNS name or installed location so as not to require digital signing in order to use the feature.

For web applications (a.k.a. “IE host”) hosted by a web browser, the URL determines the identity of the domain. Hosts such as IE associate URL evidence with the application domain that runs code from a web site. The domain identity for purposes of IsolatedStorage data compartmentalization is the full URL truncated at the rightmost slash. For example, if the URL evidence is “http://www.contoso.com/apps/myapp/home.htm” then the domain identity is derived as “http://www.contoso.com/apps/myapp”. Using the truncated URL rather than just the site allows a number of independent applications to coexist within a single site without conflicting storage use. While this does allow a malicious site to more easily use up storage, an intent attacker could still use different DNS site names rather easily in any case in which case there is no reliable way of knowing that it is really one entity consuming overly much storage. (To be blunt, we aren’t going to be able to deter malicious storage consumption very effectively in any case, so we should maximize benefit to real applications in the design.)

For shell hosted (a.k.a. “EXE host”) applications – typically, applications installed in a machine and launched – the domain identity is similarly derives from the application directory path. For example, if the main exe is run from the path “C:\office\winword.exe”, then truncation at the rightmost ‘\’ yields the domain identity “C:\office”.

Define app directory as: AddData(“AppDomainConfig.APPLICATION_BASE”)

The “friendly name” of the domain (AppDomain.GetFriendlyName) is associated with stores to help users identify the application that uses a certain store for purposes of administrating or clean-up of old information no longer needed. (We cannot expect users to recognize applications by their base URL.)

Assembly containment

In addition or instead of containment by domain, signed code assemblies may also have their own data storage compartment. Assembly identity is based on cryptographic digital signature, either by strong name or by software publisher. Generally speaking, strong name identity is most flexible, allowing both compartments unique to a particular component or broader namespaces that allow a suite of components to use a common share provided all are based on the same signing key. Software publisher is a simpler model where only the key identity defines the containment.

Strong name identity (e.g. Microsoft.Office.* or Microsoft.Office.Word) is valid for code that is signed with the private key corresponding to the public key forming the root of the strong name namespace. Separate data compartments can be used based on full or partial forms of the strong name of a component. For example, a assembly signed with strong name “first.second.third.fourth” can used any or all of these IsolatedStorage compartments: “first.second.third.fourth”, “first.second.third.*”, “first.second.*”, “first.*”, or “*” – all of which are rooted to the key associated with the digital signature of the code.

Software publisher containment identity is based on the public key corresponding to the private key used to sign the code (like the publisher identity permission). Only the key is used to determine identity: the signing certificate and whether or not there is a trust relationship (a la WinVerifyTrust) established is not relevant to this feature.

If an assembly has both strong name and software publisher identity, then that composite identity is used to define assembly containment. In other words, only assemblies with the same combination of both kinds of identity can access the same store.

Usages allowed by the permission

These basic identities enable the following types of isolation, listed in increasing level of trust (strong name and software publisher are basically same level of trust):

Level Isolated storage data containment Security impact
0 No isolated storage use allowed None
1 user + domain Data contained by domain

Potential denial-of-service

  user + domain + assembly  
2 user + assembly Potential app-to-app leakage
3 ALL users, domains, assemblies Potential for total compromise

Notes:
(1) all isolated storage containment implicitly includes “by machine” isolation

It is important to note that site identity is very weak (subject to spoofing), while cryptographically based code identities are very strong. Application code is expected to use appropriately strong identity to provide sufficient protection for the data being stored: always use strong identities for valuable or private data.

Here are a few scenario sketches to illustrate and motivate the need for these various types of storage:

  1. (user + domain) Typical use includes storing user parameters such as preferences of user data for use by a specific application. Data can only be accessed within the context of the same application and only when run by the same user. For example, an application might store user’s identifying information, save the state from the last time the application was run, use the store to record an audit trail of past application usage, and save preferences for options of the application.
  2. (user + domain + assembly) Similar to scenario above, but with a third party assembly that wants to keep a private data store. The assembly is private in the sense that only code in that assembly may access the data, yet the data store is also scoped by the application it runs in so that the assembly does not represent a potential leak exposing data to other applications. In particular, this addresses the web site isolation requirement of a web browser, where (without special trust) data of one site should never be leaked to another at the client. The scenario for this feature is similar to the above, with the third party code having its own container within the scope of the application in which it is being used.
  3. (user + assembly) In contrast to 2 above, this provides a data store for the assembly that is accessible in any domain context. The per-assembly data compartment requires additional trust as it potentially provides a “tunnel” between applications that could compromise the data isolation of applications, in particular web sites. Typical usage would be for user data that applies across multiple applications – for example, license information, user’s personal information (name, authentication credentials, etc.) that is independent of application.

Security risks of IsolatedStorage use

This section describes the security risks associated with the varying types of usage of the IsolatedStorage feature as described. Default policy will be assigned according to the risk / utility balance of each kind of usage.

Level 0: the feature is disabled so trivially there is no associated risk.

Level 1: data containment is scoped by domain identity

Stored information is only available within the same domain, as determined by the domain identity associated with the application domain. Signed assemblies within the application still have data compartment scoped by the domain identity so can’t bridge outside of the application via this feature. The remaining risk is denial of service whereby excessive amounts of storage are consumed, preventing use of storage for other use. For V1 we don’t plan to implement any kind of protection for this sort of denial of service attack; users should be able to handle this inconvenience by reclaiming the storage via normal or possibly manual means.

Note that strong protection against this sort of attack is extremely difficult without severely limiting the utility of the basic feature. For example, web browser “cookies” attempt to prevent denial of service attacks by restricting the size of each cookie (4kb) and the number of cookies (20) a single web site can store. Unfortunately it is easy to circumvent this protection by simply using multiple web sites in one attack.

There is a potential denial-of-service attack with this level of feature usage in that malicious code could intentionally consume large quantities of storage. By using numerous domain identities (such as by using several web site addresses, all owned by the attacker) an arbitrary amount of storage can be consumed, beyond the limits set for one domain identity. The only defense against these nuisance attacks are: restrict usage of level 1 to somewhat trustworthy applications, explicit user action to clean out storage, or possibly by an administrative tool that uses some heuristic to detect maximum storage usage and delete it.

Level 2: data containment is scoped by user (and assembly identity)
Information store is scoped by the assembly identity and is independent of what domain it is used in. An application using a third party assembly that has this permission potentially risks information leaking from the application.

This is an issue of the application trusting the assembly it uses. Of course security policy must also trust the code to allow this kind of usage, but there is a separate issue of applications trusting their assemblies independent of that. Ultimately, by choice of the components they call applications implicitly make these trust decisions.

Level 3: unrestricted (any user, any store)
This level potentially allows access to any store, even another user. A high level of trust by policy and by applications, as described in the preceding paragraph, is necessary to ensure that no security weaknesses are exposed by use of this feature.

OS level permissions to access store

Code must have all necessary native platform OS rights to access any stores. For example on Windows 2000, user permissions to read/write the files underlying isolated storage must satisfy the Access Control List (ACL) restrictions of the file system.

Within the NGWS platform, applications may expect to always have OS rights to access isolated storage within the current user scope. However, applications that do (platform-specific) impersonation need to be responsible for ensuring that they have the proper rights in the new user identity to use storage.

Administrative code that uses the highest “Level 3” permission also needs to satisfy OS restrictions, which may require OS-dependent code or setup.