Pergunta

Eu estou tentando Grokar o propósito de SecureString do .NET. De MSDN:

Uma instância da classe System.String é tanto imutável e, quando não for mais necessária, não pode ser programaticamente agendada para coleta de lixo; isto é, a instância é somente leitura depois de ser criado e não é possível prever quando a instância será apagado da memória do computador. Consequentemente, se um objeto String contém informações confidenciais, como uma senha, número de cartão de crédito ou dados pessoais, há o risco da informação poderia ser revelado depois que é usado porque a sua aplicação não pode excluir os dados do memória do computador.

Um SecureString objeto é semelhante a um objeto String em que tem um valor de texto. No entanto, o valor de um objeto SecureString é automaticamente criptografados, pode ser modificado até que suas marcas de aplicação lo como somente leitura, e pode ser excluído da memória do computador por qualquer aplicação ou o coletor de lixo .NET Framework.

O valor de uma instância de SecureString é automaticamente criptografados quando a instância é inicializado ou quando o valor é modificado. Sua aplicação pode tornar o imutável exemplo e evitar uma nova alteração, invocando o método MakeReadOnly.

É a cifra automática a grande recompensa?

E por que não posso apenas dizer:

SecureString password = new SecureString("password");

em vez de

SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
    pass.AppendChar(c);

Que aspecto da SecureString eu estou ausente?

Foi útil?

Solução

Algumas partes da estrutura que atualmente usam SecureString :

O objetivo principal é reduzir a superfície de ataque, em vez de eliminá-lo. SecureStrings está "preso" na RAM para que o lixo Collector não vai movê-lo ou fazer cópias do mesmo. Ele também garante que o texto simples não são escritos para o arquivo de troca ou em depósitos centrais. A criptografia é mais como ofuscação e não vai parar um hacker determinado, no entanto, que seria capaz de encontrar o chave simétrica usada para criptografar e descriptografar-lo.

Como já foi dito, a razão que você tem que criar um SecureString caractere por caractere é por causa da primeira falha óbvia de fazer o contrário: você provavelmente tem o valor secreto como uma string simples já, então qual é o ponto?

SecureString s são o primeiro passo para resolver um problema da galinha e do ovo, por isso mesmo que a maioria dos cenários atuais exigem convertê-los de volta para cordas regulares para fazer qualquer uso deles em tudo, a sua existência no âmbito agora significa um melhor suporte para eles no futuro - pelo menos a um ponto em que seu programa não tem que ser o elo mais fraco.

Outras dicas

Muitos dos grandes respostas; aqui está um breve resumo do que foi discutido.

A Microsoft implementou a classe SecureString em um esforço para fornecer melhor segurança das informações sensíveis (como cartões de crédito, senhas, etc.). Ele fornece automaticamente:

  • criptografia (no caso de despejos de memória ou página caching)
  • fixando na memória
  • capacidade de marca como somente leitura (para evitar quaisquer alterações posteriores)
  • construção segura, não permitindo uma constante de cadeia a ser aprovada em

Atualmente, SecureString é limitada em uso, mas esperar melhor adoção no futuro.

Com base nesta informação, o construtor do SecureString não deve apenas ter uma string e fatia-lo até matriz de char como tendo a seqüência de enunciados derrotas a finalidade de SecureString.

Informações adicionais:

  • A pós da Segurança do .NET blog falando sobre o mesmo que coberto aqui.
  • um revisitando-lo e mencionar uma ferramenta que pode despejar o conteúdo do SecureString.

Editar: Eu achei difícil escolher a melhor resposta como há uma boa informação em muitos; muito ruim não há opções de resposta assistida.

Resposta Curta

Por que não posso apenas dizer:

SecureString password = new SecureString("password");

Porque agora você tem password na memória; com nenhuma maneira de limpá-lo -. que é exatamente o ponto de SecureString

Long Resposta

A razão SecureString existe é porque você não pode usar ZeroMemory para limpar os dados confidenciais quando você está feito com ele. Ela existe para resolver um problema que existe porque do CLR.

Em um nativa aplicação regular você chamaria SecureZeroMemory :

Preenche um bloco de memória com zeros.

Nota : SecureZeroMemory é é idêntico ao ZeroMemory, exceto o compilador não vai otimizar-lo afastado.

O problema é que você não pode ZeroMemory chamada ou SecureZeroMemory dentro .NET. E em cordas .NET são imutáveis; você não pode mesmo sobrescrever o conteúdo da string como você pode fazer em outros idiomas:

//Wipe out the password
for (int i=0; i<password.Length; i++)
   password[i] = \0;

Então, o que você pode fazer? Como é que podemos fornecer a capacidade em .NET para limpar uma senha ou número de cartão de crédito a partir da memória quando estamos a fazer com ele?

A única maneira isso pode ser feito seria colocar a corda em algum bloco nativa memória, onde você pode ZeroMemory então chamada. Um objeto de memória nativa, tais como:

  • um BSTR
  • um HGLOBAL
  • CoTaskMem memória não gerenciada

SecureString dá a capacidade perdida de volta

Em .NET, cordas não pode ser limpo quando você está feito com eles:

  • são imutáveis; você não pode substituir seu conteúdo
  • você não pode Dispose deles
  • sua limpeza está à mercê do coletor de lixo

SecureString existe como uma maneira de passar em torno de cordas de segurança, e ser capaz de garantir a sua limpeza quando você precisa.

Você fez a pergunta:

Por que não posso apenas dizer:

SecureString password = new SecureString("password");

Porque agora você tem password na memória; com nenhuma maneira de limpá-lo. É preso lá até o CLR passa a decidir re-uso dessa memória. Você colocou-nos de volta à direita onde começamos; a execução da aplicação com uma senha não pode se livrar, e onde um despejo de memória (ou Process Monitor) pode ver a senha.

SecureString usa a API de Proteção de Dados para armazenar a string encriptada na memória; dessa forma a cadeia não vai existir em swapfiles, despejos de memória, ou mesmo na janela variáveis ??locais com um colega olhando por cima do seu deveria.

Como faço para ler a senha?

Em seguida, é a pergunta: Como faço para interagir com a corda? Você absolutamente não quer um método como:

String connectionString = secureConnectionString.ToString()

porque agora você está de volta para a direita onde você começou - uma senha que você não pode se livrar. Você deseja força desenvolvedores a lidar com a corda sensível corretamente - para que ele pode ser apagado da memória.

É por isso que .NET fornece três funções auxiliares úteis para marshall um SecureString em uma memória não gerenciada:

Você converter a string em uma bolha de memória não gerenciada, lidar com isso, e, em seguida, limpe-o novamente.

Algumas APIs aceitar SecureStrings . Por exemplo, em ADO.net 4,5 a SqlConnection.Credential leva um conjunto SqlCredential :

SqlCredential cred = new SqlCredential(userid, password); //password is SecureString
SqlConnection conn = new SqlConnection(connectionString);
conn.Credential = cred;
conn.Open();

Você também pode alterar a senha dentro de uma cadeia de conexão:

SqlConnection.ChangePassword(connectionString, cred, newPassword);

E há um monte de lugares no interior .NET onde continuam a aceitar uma cadeia simples para fins de compatibilidade, em seguida, rapidamente se transformar em torno de uma colocá-lo em um SecureString.

Como colocar texto no SecureString?

Isso ainda deixa o problema:

Como faço para obter uma senha para o SecureString em primeiro lugar?

Este é o desafio, mas o ponto é para você pensar sobre a segurança.

Às vezes, a funcionalidade está já previsto para você. Por exemplo, o WPF PasswordBox controle pode retornar a senha digitada como um SecureString diretamente:

PasswordBox .SecurePassword propriedade

Obtém a senha atualmente detida pela PasswordBox como SecureString .

Isso é útil porque em todos os lugares que você costumava passar em torno de um string bruta, agora você tem o sistema de tipo reclamando que SecureString é incompatível com cadeia. Você quer ir para o maior tempo possível antes de ter que converter sua volta SecureString em seqüência regular.

A conversão de um SecureString é bastante fácil:

  • SecureStringToBSTR
  • PtrToStringBSTR

como em:

private static string CreateString(SecureString secureString)
{
    IntPtr intPtr = IntPtr.Zero;
    if (secureString == null || secureString.Length == 0)
    {
        return string.Empty;
    }
    string result;
    try
    {
        intPtr = Marshal.SecureStringToBSTR(secureString);
        result = Marshal.PtrToStringBSTR(intPtr);
    }
    finally
    {
        if (intPtr != IntPtr.Zero)
        {
            Marshal.ZeroFreeBSTR(intPtr);
        }
    }
    return result;
}

Eles apenas realmente não quero que você fazê-lo.

Mas como faço para obter uma string em um SecureString? Bem, o que você precisa fazer é parar de ter uma senha em um string em primeiro lugar. Você necessário para tê-lo em something else. Mesmo uma matriz Char[] seria útil. |

Isso é quando você pode anexar cada personagem e limpe o texto simples quando você está feito:

for (int i=0; i < PasswordArray.Length; i++)
{
   password.AppendChar(PasswordArray[i]);
   PasswordArray[i] = (Char)0;
}

Você precisa de sua senha armazenada em alguns de memória que você pode limpar. Carregá-lo no SecureString de lá.


tl; dr: de SecureString existir para fornecer o equivalente a ZeroMemory

.

Algumas pessoas não ver o ponto em limpeza a senha do usuário da memória quando um dispositivo está bloqueado , ou limpeza limpeza keystrokes da memória após they'authenticated . Essas pessoas não usar SecureString.

Há muito poucos cenários onde você pode sensatamente usar SecureString na versão atual do quadro. É realmente útil apenas para interagir com APIs não gerenciadas - você pode organizá-la usando Marshal.SecureStringToGlobalAllocUnicode.

Assim que você convertê-lo para / de um System.String, você derrotou seu propósito.

O MSDN amostra gera o SecureString um personagem em um momento de console de entrada e passa a string segura para uma API não gerenciado. É um pouco complicado e pouco realista.

Você pode esperar futuras versões do .NET para ter mais apoio para SecureString que irá torná-lo mais útil, por exemplo:.

  • SecureString Console.ReadLineSecure () ou semelhante para ler a entrada consola num SecureString sem todo o código convoluto, com a amostra.

  • substituto WinForms TextBox que as lojas de sua propriedade TextBox.Text como uma cadeia de seguro para que as senhas podem ser inseridos de forma segura.

  • Extensões para APIs de segurança relacionadas para permitir senhas a ser passado como SecureString.

Sem o acima, SecureString será de valor limitado.

Creio que a razão pela qual você tem que fazer personagem acrescentar em vez de um instanciação plano é porque no fundo passando "password" para o construtor de SecureString coloca que "password" corda na memória derrotando a finalidade de corda segura.

Por acrescentando você está apenas colocando um carácter de cada vez na memória que é likley não ser adjacentes uns aos outros tornando-se fisicamente muito mais difícil de reconstruir a string original. Eu posso estar errado aqui, mas é assim que me foi explicado.

O objetivo da classe é para evitar que dados seguros de ser exposto através de um despejo de memória ou uma ferramenta similar.

MS descobriu que, em certos casos de causar o servidor (desktop, qualquer que seja) para travar houve momentos em que o ambiente de execução faria um despejo de memória expondo o conteúdo do que está na memória. Seguro de Cordas criptografa-lo na memória para impedir o atacante de ser capaz de recuperar o conteúdo da string.

Um dos grandes benefícios de um SecureString é que ele é suposto evitar a possibilidade de seus dados sejam armazenados no disco devido a cache de página. Se você tiver uma senha na memória e, em seguida, carregar um grande programa ou conjunto de dados, sua senha pode ficar gravado para o arquivo de troca como seu programa é paginada falta de memória. Com um SecureString, pelo menos, os dados não serão sentados em torno indefinidamente em seu disco em texto claro.

Eu acho que é porque a cadeia é para ser seguro, isto um hacker não deve ser capaz de lê-lo. Se você inicializa-lo com uma corda, o hacker poderia ler a string original.

Bem, como a descrição estados, o valor é armazenado criptografado, com meios que um despejo de memória do seu processo não irá revelar o valor da string (sem algum trabalho bastante grave).

A razão que você não pode simplesmente construir um SecureString de uma string constante é porque então você se ter uma versão não criptografada da corda na memória. Limitá-lo a criar a string em pedaços reduz o risco de ter a seqüência inteira na memória de uma vez.

Eu iria parar de usar SecureString. Looks como caras PG estão caindo suporte para ele. Possivelmente até mesmo retirá-lo no futuro - https://github.com / dotnet / apireviews / árvore / master / 2015/07/14-SecureString .

Devemos remover a criptografia de SecureString em todas as plataformas em .NET Núcleo - Devemos SecureString obsoleto - Nós provavelmente não deve expor SecureString em .NET Núcleo

Outro caso de uso é quando você está trabalhando com aplicativos de pagamento (POS) e você simplesmente não pode usar estruturas de dados imutáveis ??, a fim de armazenar dados sensíveis porque você é cuidadoso desenvolvedor. Por exemplo: se eu irá armazenar dados do cartão sensíveis ou metadados autorização em seqüência imutável há sempre seria o caso quando esses dados estarão disponíveis na memória para quantidade significativa de tempo depois de ter sido descartado. Eu não posso simplesmente substituí-lo. Outra grande vantagem que tais dados sensíveis sendo mantido na memória criptografada.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top