Windows PowerShellProtegendo o shell

Don Jones

Quando a equipe do Windows PowerShell sentou para criar um novo shell e a palavra "scripts" flutuou pela mesa, os suspiros de desalento provavelmente foram ouvidos por toda a cidade de Redmond. Afinal, os esforços anteriores da Microsoft dispensados aos scripts — estou falando do VBScript — não foram exatamente à prova de problemas. Um

modelo de execução excessivamente permissivo, combinado a uma predileção da maioria dos usuários de se conectar como administrador pleno, abriu o caminho para o desastre.

"Certamente", as pessoas presentes à primeira reunião do Windows PowerShell™ devem ter pedido, "não vamos passar por tudo aquilo novamente". E eles não passaram. A Microsoft melhorou muito a sua reputação em segurança, em grande parte porque começou a pensar nela em primeiro lugar em vez de ser a última preocupação no ciclo de desenvolvimento de um produto. Essa filosofia fica muito evidente no Windows PowerShell.

Por que os meus scripts não são executados?

Instale o Windows PowerShell em um computador novo e clique duas vezes em um arquivo .ps1: isso abrirá o Bloco de Notas, e não o Windows PowerShell. Isso acontece porque a extensão de nome de arquivo .ps1 — usada para scripts do Windows PowerShell — não possui uma associação com o próprio shell. Em outras palavras, você não pode executar um script simplesmente clicando duas vezes sobre ele. A única forma de executar um script é abrir o Windows PowerShell, digitar o nome do script e pressionar Enter.

Na verdade, simplesmente digitar o nome do script também não é o suficiente. Você pode ver na Figura 1 que há um arquivo Demo1.ps1 na pasta atual, mas digitar demo1 e pressionar Enter resulta em um erro: "O termo 'demo1' não é reconhecido como cmdlet, função, programa operável ou arquivo de script." Por que isso acontece? Afinal, o arquivo está bem ali.

Figura 1 Para evitar o seqüestro de comando, o Windows PowerShell exige um caminho para o seu script.

Figura 1** Para evitar o seqüestro de comando, o Windows PowerShell exige um caminho para o seu script. **(Clique na imagem para aumentar a exibição)

Esse é outro aspecto do modelo de segurança do Windows PowerShell. Usuários maliciosos normalmente tentam criar em outros shells um script com o mesmo nome de arquivo de um comando interno. Assim, por exemplo, se você quisesse que um usuário executasse o seu script, poderia chamá-lo de Dir.ps1 e soltá-lo e uma pasta. Se você convencesse o usuário a digitar Dir e pressionar Enter, o seu script seria executado no lugar do comando Dir esperado. Essa técnica é chamada de seqüestro de comando. No Windows PowerShell, você sempre terá de oferecer um caminho para script, o que protege bem o Windows PowerShell do seqüestro de comando.

A execução de demo1 não funciona porque não há um caminho, mas executar ./demo1 funciona. Isso acontece porque agora um caminho foi especificado — a pasta atual. É menos provável que essa linha de comando seja confundida com um comando interno, já que você nunca digitaria esse tipo de caminho se estivesse se referindo a um comando interno. Assim, exigir um caminho ajuda o Windows PowerShell a evitar o seqüestro de comando e a confusão sobre o que poderia acontecer ao pressionarmos Enter.

Uma diretiva para a execução de scripts

Então você tem uma cópia recém-instalada do Windows PowerShell, está usando a sintaxe apropriada e tenta executar um script. Para a sua surpresa, é exibida outra mensagem de erro, informando que o Windows PowerShell não pode executar scripts. O quê??? Bem-vindo à Diretiva de Execução do shell.

Você pode ver qual é a Diretiva de Execução atual ao executar Get-ExecutionPolicy no shell. Por padrão, ela é definida como Restricted, o que significa simplesmente que os scripts não serão executados. Nunca. Para ninguém. Por padrão, o Windows PowerShell só pode ser usado interativamente em vez de executar scripts. Você pode usar o cmdlet Set-ExecutionPolicy para escolher uma das quatro configurações possíveis da Diretiva de Execução:

  • Restricted, o padrão, não permite a execução de qualquer script.
  • AllSigned só executa scripts confiáveis (falarei mais sobre isso em instantes).
  • RemoteSigned executa scripts locais sem exigir que eles sejam confiáveis; no entanto, scripts baixados da Internet devem se tornar confiáveis antes que você possa executá-los.
  • Unrestricted permite que todos os scripts sejam executados, até os não confiáveis.

Francamente, AllSigned é a menor configuração que qualquer computador de produção deve ter. Acho que RemoteSigned pode ser útil em ambientes de desenvolvimento e de testes, mas não é, necessariamente, para o usuário típico. E eu não vejo nenhuma utilidade para a configuração Unrestricted e não me incomodaria em vê-la fora de alguma versão futura do Windows PowerShell.

É uma questão de confiança

O seu computador foi pré-configurado para confiar em determinadas Autoridades de Certificação raiz — ou seja, servidores que emitem certificados digitais. A Figura 2 mostra o aplicativo Opções da Internet do Painel de Controle, que lista as autoridades de certificação raiz confiáveis. No Windows Vista®, essa lista é bem curta e inclui somente algumas das maiores autoridades de certificação raiz comerciais. Em compensação, a lista padrão do Windows® XP é ampla e inclui muitas autoridades de certificação raiz das quais eu nunca ouvi falar. Quando uma autoridade de certificação raiz está nessa lista, essencialmente você está dizendo que confia na empresa que opera a autoridade de certificação raiz e que ela faz um bom trabalho ao verificar a identidade de alguém antes de emitir um certificado digital.

Quando você obtém um certificado digital de Classe III — comumente chamado de certificado de assinatura de código — a autoridade de certificação (que pode ser uma autoridade comercial ou privada que exista em sua organização) precisa verificar a sua identidade. Esse certificado digital é como um passaporte ou carteira de identidade eletrônicos. Antes de me dar uma identificação que diz que eu sou o Don Jones, por exemplo, a autoridade de certificação precisa executar algumas etapas para garantir que eu sou realmente Don Jones. Quando utiliza o seu certificado para assinar digitalmente um script do Windows PowerShell, o que pode ser feito por meio do cmdlet Set-AuthenticodeSignature, você está assinando o seu nome no script. É claro que, se você for capaz de obter um certificado falso com o nome de outra pessoa, poderá assinar o nome dela no script e é por isso que é tão importante que somente as autoridades de certificação confiáveis estejam na lista da Figura 2.

Figura 2 Autoridades de certificação raiz confiáveis padrão no Windows Vista

Figura 2** Autoridades de certificação raiz confiáveis padrão no Windows Vista **(Clique na imagem para aumentar a exibição)

Quando o Windows PowerShell verifica se um script é confiável — o que acontece quando é configurado com as Diretivas de Execução AllSigned e RemoteSigned — ele faz três perguntas:

  • Este script está assinado? Se não estiver, ele não será confiável.
  • A assinatura está intacta? Em outras palavras, o script mudou desde que foi assinado? Se a assinatura não estiver intacta, o script não será confiável.
  • A assinatura foi criada com um certificado digital emitido por uma autoridade de certificação raiz confiável? Se não foi, o script não será confiável.

CMDLET do mês: Set-AuthenticodeSignature

Set-AuthenticodeSignature é a chave para assinar digitalmente os scripts do seu Windows PowerShell, permitindo que você utilize a diretiva de execução mais segura do shell, AllSigned. Para usar esse cmdlet, você deve começar com outro — Get-ChildItem — que busca um certificado de assinatura de código instalado:

$cert = Get-ChildItem –Path cert:\CurrentUser\my –codeSigningCert

É preciso substituir o caminho do arquivo por um que aponte para um certificado instalado — qualquer um que possa ser acessado por meio da unidade cert:. Após o carregamento do certificado, execute isto para assinar um script:

Set-AuthenticodeSignature MyScript.ps1

–cert $cert

É claro que você terá de oferecer um caminho completo para o seu arquivo de script .ps1. O shell adicionará um bloco de assinatura ao arquivo.

Como a confiança pode aumentar a segurança? Sim, um hacker poderia escrever um script malicioso, assiná-lo e convencer alguém em seu ambiente a executá-lo. Como o script está assinado, ele será executado. Mas porque estava assinado, você poderá usar a assinatura para encontrar a identidade do autor e tomar a ação cabível (como chamar as autoridades responsáveis). No entanto, a pessoa teria de ser extremamente estúpida para criar um script malicioso e colocar seu nome verdadeiro nele!

É claro que, se um usuário malicioso for capaz de obter um certificado para a identidade de outra pessoa — digamos, de uma autoridade de certificação que não possui um processo de verificação de identidade muito bom — você não seria capaz de usar a assinatura para identificar o verdadeiro culpado. É por isso que as autoridades de certificação raiz em que você confia devem possuir um processo de verificação de identidade considerado satisfatório.

Se você usar a configuração da Diretiva de Execução AllSigned, terá de assinar digitalmente todos os scripts que criar antes que eles possam ser executados. O cmdlet Set-AuthenticodeSignature é muito fácil de usar, mas ainda assim isso representa um incômodo. É aqui que o software de terceiros pode ser conveniente. Eu recomendo que você selecione um editor de scripts ou um ambiente de desenvolvimento visual que assine automaticamente todos os seus scripts usando o certificado especificado. Dessa forma, a utilização de assinaturas será transparente e não exigirá um esforço extra. Se você quiser algumas sugestões de editores e de ambientes de desenvolvimento que oferecem suporte a esse recurso, visite alguns dos fóruns online sobre scripts (como o meu site, em ScriptingAnswers.com) e pergunte aos outros fãs do Windows PowerShell o que eles estão usando.

Depois de obter um certificado, você também pode executar o código de uma linha a seguir para assinar todos os scripts de um determinado local:

Get-Childitem *.ps1 | %{Set-AuthenticodeSignature $_.fullname $cert}

Protegido de forma centralizada

A Diretiva de Execução do Windows PowerShell pode, obviamente, ser configurada de computador em computador. Mas essa não é uma boa solução para ambientes corporativos. Em vez disso, você poderá usar a Diretiva de Grupo (os Modelos Administrativos do Windows PowerShell podem ser baixados de go.microsoft.com/fwlink/?LinkId=93675). Basta soltar o arquivo em um GPO (Objeto de Diretiva de Grupo) que afete todo o seu domínio e defini-lo como Restricted. Dessa forma, não importa onde o Windows PowerShell seja instalado, você poderá ter certeza de que os scripts não serão executados. Então, você poderá aplicar uma configuração mais permissiva (digamos, AllSigned) somente nos computadores que executarão scripts (como a sua própria estação de trabalho).

Credenciais alternativas

Ao contrário de qualquer linguagem de script administrativa anterior feita para Windows, o Windows PowerShell vem preparado até mesmo para lidar com credenciais alternativas de uma forma segura. Por exemplo, o cmdlet Get-WMIObject possui um parâmetro –credential, que permite a você especificar uma credencial alternativa para conexões WMI remotas. O parâmetro aceitará um nome de usuário mas não uma senha, impedindo que você codifique senhas confidenciais em um script de texto não criptografado. Em vez disso, quando você fornece um nome de usuário, o Windows PowerShell solicitará a senha usando uma caixa de diálogo. Se você planejar usar uma credencial alternativa novamente, poderá armazenar as informações de autenticação usando o cmdlet Get-Credential:

$cred = Get-Credential DOMAIN\USER

A senha será imediatamente solicitada e a credencial final será armazenada na variável $cred. Assim, a variável $cred poderá ser passada para o parâmetro –credential sempre que necessário. É possível até usar os cmdlets ConvertTo-SecureString e ConvertFrom-SecureString para converter a credencial em uma cadeia de caracteres criptografada ou para converter uma cadeia de caracteres anteriormente criptografada em uma credencial.

O problema disso é que a sua chave de criptografia termina sendo armazenada em um script de texto não criptografado, anulando totalmente a segurança. Em vez de fazer isso, adicione uma chamada a Get-Credential ao seu perfil do Windows PowerShell. Em seguida, quando o Windows PowerShell for executado, um nome de usuário e senha, armazenados em uma variável chamada $cred, serão imediatamente solicitados a você. Dessa forma, você sempre terá uma variável $cred disponível no shell para representar uma conta de administrador de domínio. E nunca terá de se preocupar com o armazenamento dessa credencial em outro local — já que ela será recriada sempre que o shell for aberto, não há necessidade de armazená-la.

Seguro por padrão

Por padrão, o Windows PowerShell é instalado e definido com as configurações mais seguras que pode haver para um shell administrativo que oferece suporte a scripts. A menos que você altere essas configurações, o Windows PowerShell permanecerá tão seguro quanto possível. Em outras palavras, tudo o que reduzir a segurança do Windows PowerShell será um resultado da sua decisão e das suas ações. Dessa forma, antes de alterar qualquer um dos padrões — reconfigurar associações de extensão de arquivo, alterar a Diretiva de Execução e assim por diante — verifique se você compreende totalmente as conseqüências de seus atos e esteja preparando para assumir a responsabilidade pelas mudanças.

Don Jones é o maior especialista em scripts da SAPIEN Technologies e instrutor do ScriptingTraining.com. Entre em contato com ele pelo seu site, ScriptingAnswers.com.

© 2008 Microsoft Corporation e CMP Media, LLC. Todos os direitos reservados. A reprodução parcial ou completa sem autorização é proibida..