Armazenamento isolado

Para aplicativos desktop, o armazenamento isolado é um mecanismo de armazenamento de dados que proporciona isolamento e segurança ao definir formas padronizadas de associar código a dados salvos. A padronização também fornece outros benefícios. Os administradores podem usar as ferramentas desenvolvidas para manipular armazenamentos isolados para configurar espaço de armazenamento de arquivos, definir políticas de segurança e excluir dados não utilizados. Com armazenamentos isolados, seu código não precisa mais de caminhos exclusivos para especificar locais seguros na sistema de arquivos e os dados são protegidos de outros aplicativos que só têm acesso a armazenamentos isolados. Informações embutidas em código que indicam onde a área de armazenamento de um aplicativo se encontra são desnecessárias.

Importante

O armazenamento isolado não está disponível para aplicativos da Store do Windows 8.x. Em vez disso, use as classes de dados de aplicativos nos namespaces Windows.Storage incluídos na API do Windows Runtime para armazenar dados e arquivos locais. Para saber mais, confira Dados de aplicativo no Centro de Desenvolvimento do Windows.

Compartimentos e Repositórios de Dados

Quando um aplicativo armazena dados em um arquivo, o nome do arquivo e o local de armazenamento devem ser escolhidos cuidadosamente para minimizar a possibilidade de o local de armazenamento ser conhecido por outro aplicativo e, portanto, tornar-se vulnerável a corrompimento. Sem um sistema padrão para gerenciar esses problemas, a improvisação de técnicas que minimizam conflitos de armazenamento pode ser complexo e os resultados podem não ser confiáveis.

Com armazenamento isolado, os dados são sempre isolados pelo usuário e pelo assembly. Credenciais como a origem ou o nome forte do assembly determinam a identidade do assembly. Os dados também podem ser isolados por domínio de aplicativo, usando credenciais semelhantes.

Quando você usa armazenamento isolado, os aplicativos salvam dados em um compartimento de dados específico que está associado a algum aspecto da identidade do código, como seu site, o editor ou a assinatura. O compartimento de dados é uma abstração, não um local específico de armazenamento; ele consiste em um ou mais arquivos de armazenamento isolados, chamados de repositórios, que contêm os locais reais dos diretórios em que os dados estão armazenados. Por exemplo, um aplicativo pode ter um compartimento de dados associado a ele, e um diretório de sistema de arquivos implementaria o repositório que de fato preserva os dados para o aplicativo. Os dados salvos no repositório podem ser qualquer tipo de dados, desde informações de preferências do usuário até o estado do aplicativo. Para o desenvolvedor, o local do compartimento de dados é transparente. Os repositórios normalmente residem no cliente, mas um aplicativo de servidor pode usar repositórios isolados para armazenar informações que personificam o usuário em cujo nome ele está funcionando. Armazenamentos isolados também podem armazenar informações em um servidor com um perfil móvel de usuário para que as informações viajem com o usuário móvel.

Cotas para armazenamento isolado

Uma cota é um limite na quantidade de armazenamento isolado que pode ser usada. A cota inclui bytes de espaço de arquivo, bem como a sobrecarga associada ao diretório e outras informações no repositório. O armazenamento isolado usa cotas de permissão, que são limites de armazenamento definidos com o uso de objetos IsolatedStoragePermission. Se você tentar gravar os dados que excedam a cota, uma exceção IsolatedStorageException será gerada. Uma política de segurança, a qual pode ser modificada com a .NET Framework Configuration Tool (Mscorcfg.msc), determina quais permissões são concedidas ao código. O código que recebeu IsolatedStoragePermission é restrito a não usar mais armazenamento do que o permitido pela propriedade UserQuota. No entanto, porque o código pode ignorar cotas de permissão ao apresentar identidades de usuário diferentes, as permissões de cotas servem mais como diretrizes de como o código deve se comportar em vez de atuar como um limite firme no comportamento do código.

As cotas não são aplicadas em repositórios móveis. Devido a isso, um nível um pouco mais alto de permissão é necessário para que o código as use. Os valores de enumeração AssemblyIsolationByRoamingUser e DomainIsolationByRoamingUser especificam uma permissão para usar o armazenamento isolado para um usuário móvel.

Acesso Seguro

Usar o armazenamento isolado permite que aplicativos parcialmente confiáveis armazenem dados de uma maneira que é controlada pela política de segurança do computador. Isto é especialmente útil para componentes baixados que um usuário talvez queira executar com cautela. Uma política de segurança raramente concede esse tipo de permissão de código quando você acessa o sistema de arquivos usando mecanismos padrão de E/S. No entanto, por padrão, código executado do computador local, de uma rede local ou da Internet recebe a permissão para usar o armazenamento isolado.

Os administradores podem limitar a quantidade de armazenamento isolado que um aplicativo ou usuário tem disponível com base em um nível de confiança apropriado. Além disso, os administradores podem remover todos os dados persistentes de um usuário. Para criar ou acessar um armazenamento isolado, o código deve receber a permissão IsolatedStorageFilePermission apropriada.

Para acessar um armazenamento isolado, o código deve ter todos os direitos do sistema operacional da plataforma nativa necessários. As listas de controle de acesso (ACLs) que controlam quais usuários têm os direitos necessários para usar o sistema de arquivos devem ser satisfeitas. Os aplicativos .NET já possuem direitos do sistema operacional para acessar armazenamentos isolados, a menos que eles executem a personificação (referente à plataforma). Nesse caso, o aplicativo é responsável por garantir que a identidade do usuário personificado tenha os direitos adequados do sistema operacional para acessar o armazenamento isolado. Esse acesso oferece uma maneira conveniente para que códigos que são executados ou baixados da Web possam ler e gravar em uma área de armazenamento relacionada a um usuário específico.

Para controlar o acesso ao armazenamento isolado, o Common Language Runtime utiliza objetos IsolatedStorageFilePermission. Cada objeto tem propriedades que especificam os seguintes valores:

  • Utilização permitida, que indica o tipo de acesso que é permitido. Os valores são membros da enumeração IsolatedStorageContainment. Para obter mais informações sobre esses valores, consulte a tabela na próxima seção.

  • Cota de armazenamento, conforme descrito na seção anterior.

O runtime exige a permissão IsolatedStorageFilePermission quando o código tenta abrir um repositório pela primeira vez. Ele decide se essa permissão será concedida com base em quanto do código é confiável. Se a permissão é concedida, os valores de cota de armazenamento e de utilização permitida são determinados por política de segurança e pela solicitação do código para IsolatedStorageFilePermission. A política de segurança é definida com o auxílio da .NET Framework Configuration Tool (Mscorcfg.msc). Todos os chamadores na pilha de chamadas são verificados para garantir que cada chamador tenha pelo menos a utilização permitida apropriada. O runtime também verifica a cota imposta no código que abriu ou criou o depósito no qual o arquivo será salvo. Se essas condições forem atendidas, a permissão será concedida. A cota é verificada novamente sempre que um arquivo é gravado no repositório.

O código do aplicativo não é obrigado a solicitar permissão porque o Common Language Runtime concederá qualquer IsolatedStorageFilePermission apropriada com base na política de segurança. No entanto, existem bons motivos para solicitar as permissões específicas de que seu aplicativo necessita, incluindo IsolatedStorageFilePermission.

Uso permitido e riscos de segurança

O uso permitido especificado por IsolatedStorageFilePermission determina o grau ao qual o código terá permissão para criar e usar o armazenamento isolado. A tabela a seguir mostra como o uso permitido especificado na permissão corresponde a tipos de isolamento e resume os riscos de segurança associados a cada uso permitido.

Uso permitido Tipos de isolamento Impacto de segurança
None Nenhum armazenamento isolado é permitido. Não há impacto de segurança.
DomainIsolationByUser Isolamento por usuário, domínio e assembly Cada assembly possui um sub-repositório separado dentro do domínio. Repositórios que usam essa permissão também são implicitamente isolados por computador. Esse nível de permissão deixa recursos abertos para superutilização não autorizada, embora cotas impostas tornem isso mais difícil. Isso é denominado um ataque de negação de serviço.
DomainIsolationByRoamingUser Igual a DomainIsolationByUser, mas o armazenamento é salvo em um local que irá transitar se os perfis de usuário móvel estiverem ativados e as cotas não forem aplicadas. Como as cotas devem ser desativadas, os recursos de armazenamento são mais vulneráveis a um ataque de negação de serviço.
AssemblyIsolationByUser Isolamento por usuário e assembly Repositórios que usam essa permissão também são implicitamente isolados por computador. As cotas serão aplicadas nesse nível para ajudar a evitar um ataque de negação de serviço. O mesmo assembly no outro domínio pode acessar esse repositório, abrindo a possibilidade de vazamento de informações entre aplicativos.
AssemblyIsolationByRoamingUser Igual a AssemblyIsolationByUser, mas o armazenamento é salvo em um local que irá transitar se os perfis de usuário móvel estiverem ativados e as cotas não forem aplicadas. O mesmo que em AssemblyIsolationByUser, mas sem as cotas, o risco de um ataque de negação de serviço aumenta.
AdministerIsolatedStorageByUser Isolamento por usuário. Normalmente, apenas ferramentas administrativas ou de depuração usam esse nível de permissão. O acesso com essa permissão permite que o código exiba ou exclua qualquer um dos arquivos ou diretórios de armazenamento isolados do usuário (independentemente do isolamento do assembly). Riscos incluem, mas não estão limitados a, vazamento de informações e perda de dados.
UnrestrictedIsolatedStorage Isolamento por todos os usuários, domínios e assemblies. Normalmente, apenas ferramentas administrativas ou de depuração usam esse nível de permissão. Esta permissão cria o potencial de um comprometimento total de todos os repositórios isolados para todos os usuários.

Segurança de componentes de armazenamento isolados em relação a dados não confiáveis

Esta seção é aplicável às estruturas a seguir:

  • .NET Framework (todas as versões)
  • .NET Core 2.1+
  • .NET 5+

O .NET Framework e .NET Core oferecem armazenamento isolado como um mecanismo para persistir dados para um usuário, um aplicativo ou um componente. Esse é um componente herdado projetado principalmente para cenários de Segurança de Acesso do Código, agora preteridos.

Várias APIs de armazenamento isoladas e ferramentas podem ser usadas para ler os dados entre limites de confiança. Por exemplo, a leitura dos dados de um escopo amplo de computador pode agregar dados de outras contas de usuário possivelmente menos confiáveis no computador. Componentes ou aplicativos lidos de escopos amplos de computador de armazenamento isolado devem estar cientes das consequências da leitura desses dados.

APIs sensíveis à segurança que podem ser lidas no escopo amplo de computador

Componentes ou aplicativos que chamam qualquer uma das seguintes APIs lidas do escopo amplo de computador:

A ferramenta de armazenamento isoladostoreadm.exe será afetada se for chamada com o comutador /machine, conforme mostrado no seguinte código:

storeadm.exe /machine [any-other-switches]

A ferramenta de armazenamento isolada é fornecida como parte do Visual Studio e do SDK do .NET Framework.

Se o aplicativo não envolver chamadas para as APIs anteriores ou se o fluxo de trabalho não envolver chamadas storeadm.exe dessa maneira, este documento não se aplicará.

Impacto em ambientes multiusuários

Conforme mencionado anteriormente, o impacto na segurança dessas APIs resulta da leitura de dados gravados em um ambiente de confiança em um ambiente de confiança diferente. O armazenamento isolado geralmente usa um dos três locais para ler e gravar dados:

  1. %LOCALAPPDATA%\IsolatedStorage\: por exemplo, C:\Users\<username>\AppData\Local\IsolatedStorage\ para o escopo User.
  2. %APPDATA%\IsolatedStorage\: por exemplo, C:\Users\<username>\AppData\Roaming\IsolatedStorage\ para o escopo User|Roaming.
  3. %PROGRAMDATA%\IsolatedStorage\: por exemplo, C:\ProgramData\IsolatedStorage\ para o escopo Machine.

Os dois primeiros locais são isolados por usuário. O Windows garante que diferentes contas de usuário no mesmo computador não possam acessar as pastas de perfil do usuário umas das outras. Duas contas de usuário diferentes que usam armazenamentos User ou User|Roaming não verão os dados umas das outras e não podem interferir nos dados umas das outras.

O terceiro local é compartilhado em todas as contas de usuário no computador. Contas diferentes podem ler e gravar nesse local e podem ver os dados umas das outras.

Os caminhos anteriores podem ser diferentes com base na versão do Windows em uso.

Agora considere um sistema multiusuário com dois usuários registrados, Mallory e Bob. Mallory consegue acessar o diretório C:\Users\Mallory\ do perfil de usuário e pode acessar o local de armazenamento compartilhado amplo do computador C:\ProgramData\IsolatedStorage\. Ela não pode acessar o diretório C:\Users\Bob\ do perfil de usuário do Bob.

Se Mallory quiser atacar Bob, ela pode gravar dados no local de armazenamento amplo do computador e tentar influenciar Bob a ler do repositório amplo do computador. Quando Bob executa um aplicativo que lê deste repositório, esse aplicativo funcionará nos dados que o Mallory colocou lá, mas de dentro do contexto da conta de usuário do Bob. O restante deste documento contempla vários vetores de ataque e quais etapas os aplicativos podem executar para minimizar o risco desses ataques.

Observação

Para que esse ataque ocorra, Mallory requer:

  • Uma conta de usuário no computador.
  • A capacidade de colocar um arquivo em um local conhecido no sistema de arquivos.
  • Saber que Bob executará em algum momento um aplicativo que tenta ler esses dados.

Não são vetores de ameaças que se aplicam a ambientes de área de trabalho padrão de usuário único, como computadores domésticos ou estações de trabalho corporativas de funcionário único.

Elevação de privilégio

Um ataque de elevação de privilégio ocorre quando o aplicativo de Bob lê o arquivo de Mallory e tenta executar uma ação automaticamente com base no conteúdo dessa carga. Considere um aplicativo que lê o conteúdo de um script de inicialização do repositório amplo de computador e passa esse conteúdo para Process.Start. Se Mallory puder colocar um script mal-intencionado no repositório amplo de computador, quando Bob iniciar seu aplicativo:

  • O aplicativo analisa e inicia o script mal-intencionado de Mallory sob o contexto do perfil de usuário de Bob.
  • Mallory obtém acesso à conta do Bob no computador local.

Negação de serviço

Um ataque de negação de serviço ocorre quando o aplicativo de Bob lê o arquivo de Mallory e falha ou, de outra forma, para de funcionar corretamente. Considere novamente o aplicativo mencionado anteriormente, que tenta analisar um script de inicialização do repositório amplo de computador. Se Mallory puder colocar um arquivo com conteúdo malformado no repositório amplo de computador, ela poderá:

  • Fazer com que o aplicativo de Bob gere uma exceção no início do caminho de inicialização.
  • Impedir que o aplicativo seja iniciado com êxito devido à exceção.

Ela então negou a Bob a capacidade de inicializar o aplicativo sob sua própria conta de usuário.

Divulgação de informações confidenciais

Um ataque de divulgação de informações ocorre quando Mallory pode enganar Bob para divulgar o conteúdo de um arquivo ao qual Mallory normalmente não tem acesso. Considere que Bob possui um arquivo secreto C:\Users\Bob\secret.txt que Mallory quer ler. Ela sabe o caminho para este arquivo, mas não pode lê-lo porque o Windows a proíbe de obter acesso ao diretório do perfil de usuário de Bob.

Em vez disso, Mallory coloca um link físico no repositório amplo de computador. Esse é um tipo especial de arquivo que não possui conteúdo, apontando para outro arquivo no disco. Ao tentar ler o arquivo do link físico, o conteúdo do arquivo direcionado pelo link será lido. Depois de criar o link físico, Mallory ainda não consegue ler o conteúdo do arquivo porque não tem acesso ao destino (C:\Users\Bob\secret.txt) do link. No entanto, Bob tem acesso a esse arquivo.

Quando o aplicativo de Bob lê do repositório amplo de computador, ele lê inadvertidamente o conteúdo de seu arquivo secret.txt, como se o próprio arquivo estivesse presente no repositório amplo de computador. Quando o aplicativo de Bob é encerrado, se ele tentar salvar o arquivo novamente no repositório amplo de computador, ele acabará inserindo uma cópia real do arquivo no diretório *C:\ProgramData\IsolatedStorage*. Como esse diretório é legível por qualquer usuário no computador, o Mallory agora consegue ler o conteúdo do arquivo.

Práticas recomendadas para se defender contra esses ataques

Importante: se o ambiente tiver vários usuários mutuamente não confiáveis, não chame a API IsolatedStorageFile.GetEnumerator(IsolatedStorageScope.Machine) nem invoque a ferramenta storeadm.exe /machine /list. Ambos pressupõem que estão operando em dados confiáveis. Se um invasor puder propagar uma carga mal-intencionada no repositório amplo de computador, essa carga poderá gerar uma elevação do ataque de privilégios no contexto do usuário que executa esses comandos.

Se estiver operando em um ambiente de vários usuários, reconsidere o uso de recursos de armazenamento isolados direcionados ao escopo do Computador. Se um aplicativo precisar ler dados de um local amplo de computador, prefira ler os dados de um local que seja gravável somente por contas de administrador. O diretório %PROGRAMFILES% e o hive do registro HKLM são exemplos de locais graváveis somente por administradores e legíveis por todos. Os dados lidos desses locais são, portanto, considerados confiáveis.

Se um aplicativo precisar usar o escopo do Computador em um ambiente de vários usuários, valide o conteúdo de qualquer arquivo lido no repositório amplo de computador. Se o aplicativo desserializar grafos de objeto desses arquivos, considere o uso de serializadores mais seguros, como XmlSerializer em vez de serializadores perigosos como BinaryFormatter ou NetDataContractSerializer. Tenha cuidado com grafos de objetos profundamente aninhados ou grafos de objetos que executam a alocação de recursos com base no conteúdo do arquivo.

Locais de Armazenamento Isolados

Às vezes é útil verificar uma alteração em um armazenamento usando o sistema de arquivos do sistema operacional. Talvez você também queira saber o local dos arquivos de armazenamento isolados. Esse local é diferente dependendo do sistema operacional. A tabela a seguir mostra os locais raiz em que um armazenamento isolado é criado em alguns sistemas operacionais comuns. Procure diretórios Microsoft\IsolatedStorage neste local raiz. Você deve alterar as configurações de pasta para mostrar arquivos e pastas ocultos para ver um armazenamento isolado no sistema de arquivos.

Sistema operacional Localização no sistema de arquivos
Windows 2000, Windows XP, Windows Server 2003 (atualização do Windows NT 4.0) Repositórios com suporte a uso móvel =

<SYSTEMROOT>\Perfis\<usuário>\Dados de aplicativos

Repositórios não móveis =

<SYSTEMROOT>\Perfis\<usuário>\Configurações locais\Dados de aplicativos
Windows 2000 – Instalação limpa (e atualizações do Windows 98 e Windows NT 3.51) Repositórios com suporte a uso móvel =

<SYSTEMDRIVE>\Documentos e configurações\<usuário>\Dados de aplicativos

Repositórios não móveis =

<SYSTEMDRIVE>\Documentos e configurações\<usuário>\Configurações locais\Dados de aplicativos
Windows XP, Windows Server 2003 – Instalação limpa (e atualizações do Windows 2000 e Windows 98) Repositórios com suporte a uso móvel =

<SYSTEMDRIVE>\Documentos e configurações\<usuário>\Dados de aplicativos

Repositórios não móveis =

<SYSTEMDRIVE>\Documentos e configurações\<usuário>\Configurações locais\Dados de aplicativos
Windows 8, Windows 7, Windows Server 2008, Windows Vista Repositórios com suporte a uso móvel =

<SYSTEMDRIVE>\Usuários\<usuário>\AppData\Roaming

Repositórios não móveis =

<SYSTEMDRIVE>\Usuários\<usuário>\AppData\Local

Criando, Enumerando e Excluindo Armazenamento Isolado

O .NET fornece três classes no namespace System.IO.IsolatedStorage para ajudar a executar as tarefas que envolvem o armazenamento isolado:

As classes de armazenamento isolado permitem que você crie, enumere e exclua o armazenamento isolado. Os métodos para a execução dessas tarefas estão disponíveis através do objeto IsolatedStorageFile. Algumas operações exigem que você tenha a permissão IsolatedStorageFilePermission que representa o direito para administrar o armazenamento isolado; você também pode precisar ter direitos do sistema operacional para acessar o arquivo ou diretório.

Para uma série de exemplos que demonstram tarefas de armazenamento isoladas comuns, confira os tópicos listados em Tópicos relacionados.

Cenários para armazenamento isolado

O armazenamento isolado é útil em muitas situações, inclusive nestes quatro cenários:

  • Controles baixados. Controles de código gerenciado baixados da Internet não têm permissão para escrever no disco rígido por meio de classes normais de E/S, mas eles podem usar o armazenamento isolado para persistir as configurações do usuário e o estado dos aplicativos.

  • Armazenamento de componentes compartilhado. Componentes que são compartilhados entre aplicativos podem usar o armazenamento isolado para fornecer acesso controlado a repositórios de dados.

  • Armazenamento de servidor. Aplicativos de servidor podem usar o armazenamento isolado para fornecer armazenamento individual para um grande número de usuários que estão realizando solicitações ao aplicativo. Pelo fato do armazenamento isolado ser sempre segredado por usuário, o servidor deve personificar o usuário que fez a solicitação. Nesse caso, os dados são isolados com base na identidade do principal, que é a mesma identidade que o aplicativo usa para fazer a distinção entre os seus usuários.

  • Roaming. Os aplicativos também podem usar o armazenamento isolado com perfis de usuários móveis. Isso permite que repositórios isolados de um usuário façam roaming com o perfil.

Não use um armazenamento isolado nas seguintes situações:

  • Para armazenar segredos de alto valor, como chaves sem criptografia ou senhas, pois o armazenamento isolado não é protegido contra código altamente confiável, código não gerenciado ou usuários confiáveis do computador.

  • Para armazenar código.

  • Para armazenar configurações e opções de implantação, as quais são controladas pelos administradores. (As preferências do usuário não são consideradas como definições de configuração, pois os administradores não as controlam.)

Muitos aplicativos usam bancos de dados para armazenar e isolar os dados. Nesse caso uma ou mais linhas em um banco de dados podem representar o armazenamento para um usuário específico. Você pode optar por usar armazenamento isolado em vez de um banco de dados quando o número de usuários é pequeno, quando as despesas no uso de um banco de dados é significativa ou quando não existe nenhum recurso de banco de dados. Além disso, quando o aplicativo requer um armazenamento que seja mais flexível e complexo do que aquele fornecido por uma linha em um banco de dados, o armazenamento isolado pode fornecer uma alternativa viável.

Título Descrição
Tipos de isolamento Descreve os diferentes tipos de isolamento.
Como: Obter repositórios para o armazenamento isolado Fornece um exemplo de uso da classe IsolatedStorageFile para obter um armazenamento isolado por usuário e assembly.
Como: Enumerar repositórios para o armazenamento isolado Mostra como usar o método IsolatedStorageFile.GetEnumerator para calcular o tamanho de todo o armazenamento isolado para o usuário.
Como: Excluir repositórios no armazenamento isolado Mostra como usar o método IsolatedStorageFile.Remove de duas maneiras diferentes para excluir repositórios isolados.
Como: Prever condições de espaço insuficiente com o armazenamento isolado Mostra como a medir o espaço restante em um armazenamento isolado.
Como: Criar arquivos e diretórios no armazenamento isolado Fornece alguns exemplos de criação de arquivos e diretórios em um repositório isolado.
Como: Localizar arquivos e diretórios existentes no armazenamento isolado Demonstra como ler a estrutura de diretórios e arquivos no armazenamento isolado.
Como: Ler e gravar em arquivos no armazenamento isolado Fornece um exemplo de gravação de uma cadeia de caracteres em um arquivo de armazenamento isolado, seguida por sua leitura de volta.
Como: Excluir arquivos e diretórios no armazenamento isolado Demonstra como excluir arquivos e diretórios isolados.
E/S de arquivo e de fluxo Explica como você pode executar acesso síncrono e assíncrono a fluxos de dados e arquivos.

Referência