Segurança em scripts é um aspecto fundamental para qualquer profissional que utiliza PowerShell, seja em ambientes corporativos ou pessoais. Scripts mal elaborados podem vazar credenciais, expor dados sensíveis ou ser explorados por agentes mal-intencionados. Nesta aula, vamos explorar como proteger informações confidenciais dentro de seus scripts e como evitar armadilhas comuns que comprometem a segurança.

O PowerShell oferece vários mecanismos para lidar com segurança, mas muitos deles são mal compreendidos ou mal utilizados. Vamos desmistificar conceitos como Execution Policy, entender a importância de usar objetos seguros como PSCredential e adotar boas práticas que elevam o nível de segurança dos seus scripts. O objetivo é que você saia desta aula com habilidades práticas para escrever scripts que não exponham segredos e que sigam padrões recomendados pela comunidade e pela Microsoft.

Credenciais seguras

Trabalhar com credenciais em scripts é uma necessidade comum, seja para autenticar em serviços, executar comandos com privilégios ou acessar recursos remotos. No entanto, armazenar senhas em texto puro dentro do script é um erro grave, pois qualquer pessoa com acesso ao arquivo pode ler a senha. O PowerShell oferece o tipo System.Management.Automation.PSCredential, que encapsula um nome de usuário e uma senha de forma segura. A senha é armazenada como um objeto SecureString, que é criptografado na memória usando APIs do Windows (DPAPI). Isso significa que, mesmo se você inspecionar a memória do processo, não verá a senha em texto puro.

Para criar um objeto PSCredential, você pode usar o cmdlet Get-Credential, que exibe uma caixa de diálogo solicitando usuário e senha. Em cenários não interativos, você pode construir um PSCredential a partir de um SecureString. Veja o exemplo a seguir:

# Criando um SecureString a partir de uma string (NUNCA faça isso em produção!)
$senha = ConvertTo-SecureString "MinhaSenhaForte" -AsPlainText -Force
$credencial = New-Object System.Management.Automation.PSCredential("usuario", $senha)

# Usando a credencial em um cmdlet
Get-WmiObject -Class Win32_ComputerSystem -Credential $credencial

Note que a string original "MinhaSenhaForte" ainda existe no script em texto puro. Isso é apenas para demonstração. Em scripts reais, você deve obter o SecureString de fontes seguras, como um arquivo criptografado ou o cofre de segredos (Secret Management). O ideal é nunca ter a senha em texto puro no código-fonte.

Evitando texto plano

Manter senhas e outros dados sensíveis em texto puro é uma das maiores falhas de segurança. Em scripts, isso pode ocorrer de várias formas: variáveis que armazenam senhas como strings, parâmetros que aceitam senhas em texto puro, ou até mesmo saídas de comandos que exibem informações confidenciais. Para evitar isso, sempre utilize SecureString e PSCredential quando lidar com senhas. Além disso, evite registrar (log) informações sensíveis, pois os logs podem ser acessados por terceiros.

Outra prática é usar o cmdlet Export-Clixml para salvar credenciais em um arquivo XML criptografado. Esse método usa a DPAPI do Windows, que associa a criptografia ao usuário e à máquina. Assim, somente o usuário que criou o arquivo pode descriptografá-lo na mesma máquina. Veja como fazer:

# Salvar credencial em arquivo criptografado
$credencial = Get-Credential
$credencial | Export-Clixml -Path "C:\Segredos\credencial.xml"

# Recuperar a credencial
$credencialImportada = Import-Clixml -Path "C:\Segredos\credencial.xml"

Isso é muito mais seguro do que armazenar a senha em um arquivo de texto ou planilha. No Windows, a criptografia é forte e impede que outros usuários (ou malware) leiam o conteúdo sem a devida autorização. Lembre-se de que o arquivo XML contém a senha criptografada, mas não é à prova de tudo: se um invasor conseguir executar código no contexto do seu usuário, ele poderá descriptografar. Portanto, proteja o arquivo com permissões NTFS adequadas.

Execution policy não é segurança

Muitos iniciantes acreditam que a Execution Policy do PowerShell é uma medida de segurança que impede a execução de scripts maliciosos. Na verdade, a Execution Policy é apenas uma conveniência administrativa que controla se os scripts podem ser executados e de quais fontes. Ela não protege contra scripts maliciosos, pois um usuário pode facilmente contorná-la (por exemplo, digitando o conteúdo do script diretamente no console ou usando powershell -ExecutionPolicy Bypass). Portanto, nunca confie na Execution Policy como uma barreira de segurança.

Em vez disso, a segurança deve ser baseada em princípios como o princípio do menor privilégio, assinatura de scripts com certificados confiáveis e auditoria. O PowerShell oferece suporte a assinatura de scripts usando Set-AuthenticodeSignature, o que permite verificar a integridade e a origem do script. Se você definir uma política de execução como AllSigned, apenas scripts assinados por um editor confiável serão executados, o que adiciona uma camada de segurança. No entanto, isso ainda não é infalível, pois um usuário pode optar por executar scripts não assinados se tiver permissão para alterar a política.

# Verificar a política de execução atual
Get-ExecutionPolicy

# Definir como AllSigned (exige assinatura)
Set-ExecutionPolicy -ExecutionPolicy AllSigned -Scope LocalMachine

# Assinar um script com um certificado
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
Set-AuthenticodeSignature -FilePath "C:\Scripts\meuscript.ps1" -Certificate $cert

Lembre-se: a Execution Policy não é um controle de segurança, mas sim uma configuração que pode ser alterada por qualquer usuário com privilégios. Para ambientes corporativos, use AppLocker ou WDAC (Windows Defender Application Control) para restringir a execução de scripts de forma mais robusta.

Boas práticas

Adotar boas práticas de segurança em scripts é essencial para reduzir riscos. Aqui estão algumas recomendações importantes:

  • Nunca inclua senhas em texto puro no código. Sempre use SecureString ou PSCredential.
  • Use o módulo Microsoft.PowerShell.SecretManagement para armazenar segredos de forma centralizada e segura.
  • Evite usar parâmetros que aceitem senhas como strings. Em vez disso, aceite SecureString ou PSCredential.
  • Não faça log de informações sensíveis. Se precisar registrar, ofusque os dados.
  • Valide e sanitize todas as entradas do usuário para prevenir injeção de comandos ou scripts.
  • Use o princípio do menor privilégio: execute scripts com as permissões mínimas necessárias.
  • Assine seus scripts para garantir integridade e autenticidade.
  • Mantenha o PowerShell atualizado para receber correções de segurança.

Um exemplo de boa prática é usar o módulo SecretManagement para recuperar segredos sem expô-los:

# Exemplo com SecretManagement (requer módulo instalado)
Register-SecretVault -Name MyVault -ModuleName SecretManagement.KeePass
$credencial = Get-Secret -Name "AdminCred" -Vault MyVault

Essa abordagem centraliza o armazenamento de segredos e evita que eles fiquem espalhados em scripts.

Referências

Exercícios

  1. Crie um script que solicite uma credencial ao usuário e a armazene em um arquivo XML criptografado.

    ✓ Resposta:
    $credencial = Get-Credential
    $credencial | Export-Clixml -Path "$env:USERPROFILE\credencial.xml"
  2. Explique por que a Execution Policy não deve ser considerada uma medida de segurança.

    ✓ Resposta: A Execution Policy é uma configuração que controla se scripts podem ser executados e de quais fontes, mas pode ser facilmente contornada por um usuário com privilégios (por exemplo, usando -ExecutionPolicy Bypass). Ela não impede a execução de scripts maliciosos, pois não valida o conteúdo ou a intenção do script. Portanto, não é uma barreira de segurança eficaz.
  3. Como você pode criar um PSCredential sem que a senha apareça em texto puro no script?

    ✓ Resposta: Você pode usar Get-Credential para solicitar interativamente, ou recuperar um SecureString de um arquivo criptografado com Import-Clixml, ou usar o módulo SecretManagement. Nunca converta uma string em SecureString com ConvertTo-SecureString -AsPlainText em scripts de produção.
  4. Escreva um trecho de código que assina um script com um certificado de assinatura de código.

    ✓ Resposta:
    $cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
    Set-AuthenticodeSignature -FilePath "C:\Scripts\meuscript.ps1" -Certificate $cert
  5. Qual é a importância de usar o módulo SecretManagement em vez de armazenar credenciais em variáveis?

    ✓ Resposta: O SecretManagement centraliza o armazenamento de segredos em cofres seguros, como KeePass, Azure Key Vault ou o Windows Credential Manager. Isso evita que as credenciais fiquem expostas no código ou em arquivos de configuração, além de permitir rotação e auditoria centralizada. Também facilita a conformidade com políticas de segurança.

Observações finais

Segurança em scripts não é um tópico único, mas uma mentalidade. Sempre questione: onde estão os segredos? Quem pode acessá-los? Como posso minimizar a superfície de ataque? Lembre-se de que a segurança é um processo contínuo, e as práticas aqui apresentadas são fundamentais para proteger seus scripts e ambientes. Além disso, mantenha-se atualizado com as melhores práticas da Microsoft e da comunidade PowerShell.