Conheço algumas pessoas que estão atualmente trabalhando em um projeto para as forças armadas dos EUA (baixo nível de segurança, dados do tipo recursos humanos que não são de combate).
Um estado inicial do código do projeto foi submetido aos militares para revisão e eles executaram o programa através de algum tipo de ferramenta de análise de segurança. Ele retornou um relatório de problemas de segurança conhecidos no código e exigiu alterações que precisavam ser implementadas antes da entrega do produto final.
Um dos itens que precisavam ser resolvidos foi a remoção de parte do projeto que foi escrito em Ruby por ser uma linguagem dinâmica.
Qual é o motivo / motivo para não permitir que um idioma dinâmico seja usado em um ambiente seguro? O governo está demorando para adotar novas tecnologias? Ou as linguagens dinâmicas representam um risco adicional à segurança em comparação às linguagens estáticas (ala C ++ ou Java )?
Respostas:
Há várias coisas "legais" que podem ser feitas em linguagens dinâmicas que podem ser escondidas em partes do código que não são imediatamente óbvias para outro programador ou auditor quanto à funcionalidade de um determinado pedaço de código.
Considere esta sequência no irb (ruby shell interativo):
O que aconteceu lá é que tentei chamar o método
foo
em uma constante String. Isso falhou. Abri a classe String e defini o métodofoo
o return"foobar!"
e, em seguida, o chamei. Isso funcionou.Isso é conhecido como classe aberta e me dá pesadelos toda vez que penso em escrever código em ruby que tenha qualquer tipo de segurança ou integridade. Claro que isso permite que você faça algumas coisas legais bem rápido ... mas eu poderia fazer isso toda vez que alguém armazenasse uma string, a armazenasse em um arquivo ou a enviasse pela rede. E esse pequeno pedaço de redefinição da String pode ser colocado em qualquer lugar do código.
Muitas outras linguagens dinâmicas têm coisas semelhantes que podem ser feitas. O Perl tem o Tie :: Scalar que pode nos bastidores mudar o funcionamento de um determinado escalar (isso é um pouco mais óbvio e requer um comando específico que você pode ver, mas um escalar que é passado de outro lugar pode ser um problema). Se você tiver acesso ao Perl Cookbook, procure a Receita 13.15 - Criando variáveis mágicas com gravata.
Devido a essas coisas (e outras geralmente fazem parte de linguagens dinâmicas), muitas abordagens para a análise estática da segurança no código não funcionam. Perl e Indecidibilidade mostram que esse é o caso e apontam até esses problemas triviais com destaque da sintaxe (
whatever / 25 ; # / ; die "this dies!";
apresenta desafios porquewhatever
podem ser definidos para receber argumentos ou não em tempo de execução, derrotando completamente um marca-texto ou analisador estático da sintaxe).Isso pode se tornar ainda mais interessante no Ruby com a capacidade de acessar o ambiente em que um fechamento foi definido (consulte YouTube: Mantendo o Ruby Reasonable from RubyConf 2011 por Joshua Ballanco). Fui informado deste vídeo de um comentário da Ars Technica por MouseTheLuckyDog .
Considere o seguinte código:
Este código é totalmente visível, mas o
mal
método pode estar em outro lugar ... e com classes abertas, é claro, pode ser redefinido em outro lugar.Executando este código:
Nesse código, o fechamento pôde acessar todos os métodos e outras ligações definidas na classe nesse escopo. Ele escolheu um método aleatório e o redefiniu para gerar uma exceção. (veja a classe Binding no Ruby para ter uma ideia do que esse objeto tem acesso)
Uma versão mais curta que mostra a redefinição de uma variável:
Que, quando executado, produz:
Isso é mais do que a classe aberta que mencionei acima, que torna impossível a análise estática. O que foi demonstrado acima é que um fechamento que é passado em outro lugar leva consigo o ambiente completo em que foi definido. Isso é conhecido como ambiente de primeira classe (assim como quando você pode passar funções, elas são funções de primeira classe, este é o ambiente e todas as ligações disponíveis naquele momento). Pode-se redefinir qualquer variável definida no escopo do fechamento.
Bom ou mau, queixando-se de rubi ou não (há usos onde se poderia desejar para ser capaz de chegar ao ambiente de um método (ver Seguro em Perl)), a questão do "por que rubi ser restringida em um projeto do governo "realmente é respondido no vídeo vinculado acima.
Dado que:
Com as implicações dessas quatro opções de design, é impossível saber o que qualquer parte do código faz.
Mais sobre isso pode ser lido no blog Abstract Heresies . O post em particular é sobre o Scheme em que esse debate foi realizado. (relacionado com SO: por que o Scheme não suporta ambientes de primeira classe? )
Espero que esta seção mostre o aspecto de perigo dos ambientes de primeira classe e por que seria solicitado a remover o Ruby da solução fornecida. Não é apenas porque Ruby é uma linguagem dinâmica (como mencionado em outras respostas, outras linguagens dinâmicas foram permitidas em outros projetos), mas também por questões específicas que tornam ainda mais difícil pensar em algumas linguagens dinâmicas.
fonte
"many approaches to static analysis of security in code doesn't work"
, então ela é rejeitada porque não pode ser analisada (por este grupo, pelo menos). Se estou interpretando direito ou se é mesmo um motivo válido para rejeitá-lo, não sei.Supondo que a avaliação era apenas de segurança, e não apenas uma verificação de aceitação (ou seja, eles não aceitam Ruby porque não desejam dar suporte a Ruby), então:
As ferramentas de análise de segurança normalmente passam mal com comportamentos dinâmicos.
Por exemplo:
Execute qualquer projeto .NET escrito com recursos modernos como ASP.NET MVC e Entity Framework através de algo como Veracode e veja que tipo de lista de lavanderia de falsos positivos você recebe em seu relatório.
A Veracode até lista muitas técnicas básicas nas bibliotecas principais do .NET 4 como "estruturas não suportadas" como não suportadas ou beta apenas, embora a maioria delas tenha vários anos de idade neste momento.
Se você estiver lidando com uma entidade que depende fortemente de tal ferramenta, elas são quase forçadas a considerá-las inseguras se não tiverem o conhecimento técnico e os recursos para avaliar manualmente um projeto e verificar se ele está escrito e seguro.
Nas operações civis em que os sistemas de computador geralmente não controlam nada perigoso ou terrivelmente caro, a atenuação é que você discute os falsos positivos e eles geralmente são aceitos como tal em massa.
Nas operações bancárias, você ainda tem uma chance de uma mitigação de falsos positivos, mas gastará muito mais tempo discutindo as minúcias de cada item. Isso rapidamente se torna proibitivo em termos de custos e você começa a usar métodos mais tradicionais.
Nas forças armadas, na aviação, na indústria pesada e similares, os sistemas podem controlar coisas que têm terríveis falhas nos modos desses sistemas, para que possam ter regras muito estritas sobre idiomas, compiladores, etc.
As organizações também geralmente escrevem sua política de segurança para o pior caso que conhecem, portanto, mesmo se você estiver escrevendo algo trivial, se estiver escrevendo para uma organização que possui sistemas não triviais, o padrão geralmente será mantê-la um padrão mais alto, a menos que alguém solicite uma exceção específica.
fonte
Linguagens dinâmicas podem ser usadas em aplicações militares e de defesa. Eu pessoalmente usei e entreguei Perl e Python em aplicativos do DoD. Também vi PHP e JavaScript usados e implantados. Nas minhas experiências, a maioria do código não compilado que eu vi foram scripts de shell e Perl porque os ambientes necessários são aprovados e instalados em uma variedade de possíveis sistemas de destino.
O fato de essas linguagens serem dinâmicas provavelmente não é o problema. Os intérpretes para esses idiomas devem ser aprovados para uso nos sistemas de destino. Se o intérprete não for aprovado para uso (ou, talvez seja, mas não estiver implantado nos sistemas de destino), o idioma não poderá ser usado. O uso de um determinado intérprete (ou qualquer aplicativo) em um sistema seguro requer vários obstáculos de segurança: análise da fonte, capacidade de compilar a partir da fonte para ambientes de destino, análise adicional dos binários, garantindo que não haja conflitos com a infraestrutura existente, etc.
fonte
Passei algum tempo entrevistando o DOD (Departamento de Defesa), para obter um código de posição para a MMU do F-16 . Sem violar nenhuma não divulgação: a MMU é a unidade de computador que controla quase todas as funções do F-16. É (obviamente) fundamental que nenhum erro, como erros de tempo de execução, ocorra durante o voo. É igualmente crítico que o sistema realize operações de computação em tempo real.
Por esse e outros motivos históricos, todo o código desse sistema é gravado ou compilado no ADA, uma linguagem de programação estática orientada a objetos .
Detesto citar muito, mas isso explica muito bem por que exatamente as linguagens estáticas (como o ADA) são usadas para projetos como este:
fonte
Tanto o Departamento de Defesa quanto a NASA têm uma longa história de falhas de programação que custam bilhões de dólares. Ambas as instituições aceitaram processos que deveriam protegê-las de repetir os mesmos erros.
Isso é um equívoco - linguagens dinâmicas não são uma nova tecnologia, são bastante antigas. O problema é que, se você já teve um problema causado por uma linguagem dinâmica (por exemplo, digitação fraca / dinâmica) e esse problema custou muito dinheiro, você pode aceitar uma política que o impediria de cometer o mesmo erro novamente - por exemplo, banir o uso de linguagens dinâmicas em sistemas sensíveis.
Linguagens dinâmicas geralmente "engolem" erros e acabam com algum comportamento inesperado. Isso é muito perigoso em sistemas sensíveis. Se algo de errado está acontecendo, você deve saber o mais rápido possível.
Se a segurança estiver em causa, seria necessário ver o caso de uso real. Por exemplo, eu não acho que uma página da web do Ruby on Rails seja automaticamente menos segura que uma página da Java.
fonte
Gostaria de acrescentar às respostas existentes descrevendo o SA-CORE-2014-005 do Drupal , que é uma vulnerabilidade altamente crítica que permite a injeção de SQL e, finalmente, a execução arbitrária de código. É causado pelas regras de digitação dinâmica do PHP e de lax runtime.
A totalidade do patch para esse problema é:
Esse código faz parte de uma camada de abstração SQL projetada para impedir a injeção de SQL. É necessária uma consulta SQL com parâmetros nomeados e uma matriz associativa que fornece um valor para cada parâmetro nomeado. É permitido que o valor seja uma matriz, em casos como
WHERE x IN (val1, val2, val3)
, em que todos os três valores podem ser passados como um único valor de matriz para um único parâmetro nomeado.A vulnerabilidade ocorre porque o código assume que
$i
no$i => $value
deve ser um número inteiro de índice do valor. Ele continua e concatena esse "índice" diretamente na consulta SQL como parte de um nome de parâmetro, porque números inteiros não precisam ser escapados, certo?Infelizmente para o Drupal, o PHP não fornece essa garantia. É possível passar em outro array associativo, cujas chaves são strings, e esse loop concatenará alegremente a chave da string na consulta, como está (lembre-se de que o código pensa que só pode ser um número inteiro).
Embora existam maneiras de ocorrer um erro semelhante em um idioma estaticamente digitado, elas são improváveis. Um bom desenvolvedor consideraria as possíveis coisas
$i
antes de concatená-las na consulta. Com uma linguagem de tipo estaticamente, é muito fácil aplicar que$i
deve ser um número inteiro e, em códigos sensíveis à segurança como este, isso certamente seria feito.Além disso, o código realmente verifica se o valor é uma matriz antes de iterar sobre os itens. E aqui está uma segunda parte da falha que habilita essa vulnerabilidade: um array associativo e um array "normal" retornam true para
is_array
. Embora também seja verdade que em C #, tanto dicionários quanto matrizesIEnumerable
, é difícil construir código que conflite as chaves do dicionário com índices de matriz como esse mesmo intencionalmente, e muito menos acidentalmente.fonte
A segurança ou não de uma base de código depende de como você escreve seu código, de como testá-lo e de como validar e monitorar seu processo de desenvolvimento e implantação. Os idiomas não são seguros nem inseguros, é como você codifica.
A maioria dos incidentes de segurança devido a entradas maliciosas (injeções de sql, estouros de buffer), vírus, rootkits e cavalos de Troia. Nenhum idioma pode protegê-lo disso.
Portanto, proibir classes de idiomas por serem "inseguras" não é uma razão válida.
Suspeito que alguém, por qualquer motivo - informado ou não - tenha decidido proibir esses idiomas. Depois de um tempo, tornou-se uma verdade organizacional . Pode ter sido verdade naquele momento em alguns projetos, mas as culturas de controle não gostam de mudar decisões (admitem que estavam erradas) e preferem regras simples. Eles prosperam em regras e regulamentos e não importa se fazem sentido ou não, é a segurança percebida que conta.
Isso acontece o tempo todo em culturas de controle. Eu vejo isso mais ou menos diariamente. Não faz sentido, mas é assim que acontece. Se você quiser ler mais sobre este tópico altamente relevante, recomendo o livro de Schneider " The Alternative Reengineering ". Aqui está um diagrama de cultura de Michael Sahoto / Agilitrix , baseado no livro de Schneider:
fonte
Pelo que sei, a política oficial do Departamento de Defesa geralmente não proíbe idiomas dinâmicos.
Os padrões para software desenvolvido ou adquirido pelo Departamento de Defesa são promulgados pela Agência de Sistemas de Informação de Defesa (DISA). Sua Application Security - Application Security & Development Guia de Implementação Técnico de Segurança (STIG) não proíbe qualquer linguagem particular. Não menciona Ruby, mas menciona Perl e Python, que são igualmente dinâmicos. Ele os menciona no contexto de vários tópicos (seguindo os padrões de codificação estabelecidos, evitando as vulnerabilidades de injeção de comando, etc.).
Provavelmente, o que você está vendo é uma ferramenta de varredura excessivamente rigorosa (existem várias diferentes mencionadas no STIG, cada uma pode ter sua própria interpretação das regras) e / ou interpretação excessivamente rigorosa de sua saída.
fonte