Quão seguro é compilar uma parte do código-fonte de um estranho aleatório? [fechadas]

40

Suponha que eu esteja revisando o código que os candidatos a emprego enviam para provar suas habilidades. Obviamente, não quero executar executáveis que eles enviam. Não é tão claro que prefiro não executar o resultado da compilação de seu código (por exemplo, O Java permite ocultar código rodável nos comentários ).

Que tal compilar seu código? Eu quero avisos de compilador, se houver, mas e se o código deles contiver algumas seqüências de caracteres inteligentes que exploram meu compilador e meu compilador compromete minha máquina?

Quando busco "vulnerabilidades do compilador" no Google, os acessos que recebo são sobre otimizações de compilador e emissão de código, e se o código emitido é tão seguro quanto o código-fonte original deveria ser.

Os compiladores são normalmente validados para garantir que não comprometam a máquina do usuário durante a compilação de algum código inteligente? Quão seguro é compilar um pedaço de código de um estranho?

    
por sharptooth 23.06.2015 / 13:27
fonte

13 respostas

32

Depende.

Esta parte do makefile pode excluir seu diretório inicial:

all:
    rm -rf ~

Então, se você precisar usar uma ferramenta (como cmake ou makefile system), então não é seguro. Apenas depende de quão malicioso é o codificador.

Por outro lado, os compiladores são programados por pessoas, portanto, eles têm erros. Então, talvez seja possível que alguém tenha encontrado uma maneira de executar códigos maliciosos durante a compilação.

Como sugerido nos comentários, se você quiser ter certeza de que nenhuma coisa engraçada está sendo feita em sua máquina, use uma máquina virtual.

    
por 23.06.2015 / 14:52
fonte
23
Tenho certeza que em algum lugar no negócio existem alguns caras inteligentes que já criaram um hack para uma versão específica de linguagem e compilador. Meu lugar favorito para procurar por algo assim provavelmente seria o concurso C ofuscado Internacional - (não sei se há algo comparável para Java). No entanto, na realidade, quão alto você considera o risco, assumiu que

  • o candidato faz uma impressão plausível em você, ele realmente quer o emprego na sua empresa (e não um processo)

  • o cara não sabe quanta revisão é feita na sua

  • ele não sabe qual versão exata do compilador você está usando

  • ele / ela não sabe se você usa um ambiente virtual ou um compilador on-line, apenas para estar seguro

  • você não aceita programas que sejam grandes demais para serem revisados com eficácia

  • você não compila nada que pareça suspeito para você

  • não há muitas pessoas no mundo que realmente sabem como realizar tecnicamente tal tarefa (e o googling sozinho não lhe dará um "ref rápido" ou tutorial sobre isso, como você já descobriu por você mesmo).

Portanto, embora a compilação não seja "totalmente segura" em teoria, na realidade, o IMHO é extremamente baixo e o seu "compilador é pego".

    
por 23.06.2015 / 14:23
fonte
11

Temos que distinguir vários casos:

  1. Um bug no compilador. Como todo programa complexo, um compilador pode ter bugs, e um desses bugs pode ser explorado.
  2. Um cavalo de tróia. O invasor pode fazer com que você execute algum código arbitrário como parte do processo de compilação. Um script de shell Makefile , a build.xml , a configure etc. Tecnicamente, isso não se deve à compilação do código do invasor, mas sim à configuração do ambiente de compilação.
  3. Idiomas que permitem a execução de código arbitrário em tempo de compilação. A linguagem de macro do Scala é Scala, a linguagem de macro do Common Lisp é Common Lisp, a linguagem de macros do Template Haskell é Haskell. Scala também tem plugins de compilador, que são novamente código Scala arbitrário que é executado em tempo de compilação. F # tem provedores de tipo.
  4. Idiomas que permitem a computação de Turing em tempo de compilação. Os sistemas de tipos de Scala e Haskell são Turing-complete, assim como os Templates de C ++. Você pode fazer com que o compilador execute cálculos arbitrários de Turing em tempo de compilação, incluindo, entre outros, loops infinitos. Note que Turing-complete significa que você pode computar toda função computável de Turing, isso não significa que você pode acessar o sistema de arquivos ou algo parecido. Mas você pode criar um programa que demore infinitamente para compilar.
  5. Tempos de compilação muito longos. Por exemplo, as regras do C # para resolução de sobrecarga são tão complexas que você pode codificar qualquer problema 3-SAT como resolução de sobrecarga C #. 3-SAT é, claro, famosa NP-completo. Em outras palavras, de acordo com nosso conhecimento atual, é impossível encontrar um algoritmo eficiente para resolução de sobrecarga em C #. Você não pode fazer a compilação demorar infinitamente, mas não é preciso um grande programa para fazer a compilação demorar mais do que a vida útil do universo, que é praticamente a mesma coisa.

# 4. e # 5. vai no máximo resultar em uma negação de serviço. Praticamente, os compiladores C ++ e Scala limitam a quantidade de recursão que você pode fazer, de modo que não é realmente possível escrever um loop infinito. No Scala, isso é apenas uma restrição de implementação, mas em C ++, é explicitamente permitido pela especificação, acredito.

# 2. está tecnicamente fora do escopo da questão porque a questão era sobre compilar código não executá-lo (OTOH, há a profunda questão filosófica: se a verificação de tipo de um programa Haskell pode executar cálculos arbitrários de Turing, é essa compilação ou execução de um programa?)

# 1. é improvável. Por um lado, compiladores de produção são muito complexos, então a probabilidade de erros é alta. Por outro lado, eles são rigorosamente testados, afinal, o manuseio grosseiro de entradas mal-formadas faz parte da descrição do trabalho de um compilador. Mesmo se eles não forem testados, eles serão bombardeados com código mal formado de qualquer maneira… apenas olhe algumas questões do StackOverflow para exemplos do que as pessoas de lixo eletrônico lançam em seus compiladores!

Isso nos deixa com 3. Alguns compiladores podem limitar o tipo de acesso que o código de tempo de compilação tem ao sistema, mas para alguns dos casos de uso, ter acesso total é inevitável. A finalidade dos provedores de tipos do F #, por exemplo, é "falsificar" tipos sintéticos para dados cujo sistema de tipos não corresponde aos F #, para que você possa interagir com, digamos, um serviço da Web que tenha um esquema WSDL moda. No entanto, para fazer isso, o provedor type precisa ter acesso ao recurso de esquema WSDL no sistema de arquivos ou na Web, portanto, ele precisa ter acesso ao sistema de arquivos e à rede.

Então, é seguro? Tecnicamente, não. Isso é arriscado? Na verdade não.

    
por 23.06.2015 / 17:18
fonte
3

Não deve haver risco apenas compilar o código. Em teoria pode haver um bug no compilador que um hacker esperto poderia tirar vantagem, mas é extremamente improvável.

Esteja ciente de que construção pode não ser seguro. Por exemplo, em C # 'build event' permite que você especifique linhas de comando arbitrárias para executar antes e depois da construção, o que é obviamente perigoso e muito mais fácil de explorar do que os estouros de buffer no código do compilador.

    
por 23.06.2015 / 14:06
fonte
3

Em vez de especular, eu realmente me preocupei em fazer algumas pesquisas sobre esse assunto antes de responder, indo para o recurso mais autoritário que eu conseguia pensar ( Detalhes do CVE ). Essa lista abrangente de explorações de segurança divulgadas publicamente é provavelmente a melhor que se pode fazer para avaliar os níveis de ameaça de vários tipos de software.

Eu não demorei a ler todo o material disponível, claro, mas selecionei alguns compiladores, IDEs e editores de texto "primários" para apresentar uma amostra de avaliação de ameaças . Se você é sério sobre a execução de qualquer software, você deve pelo menos ver quais ameaças estão lá fora. Observe também que o software antigo é geralmente mais problemático do que o software mais recente, portanto, executar o mais recente de tudo o que você está executando é o ideal.

Primeiro, podemos dar uma olhada em vários editores de texto. Parece que os melhores editores são os mais simples. Vi se você estiver usando um shell Linux ou o Bloco de Notas se estiver no Windows. Algo sem recursos de formatação, sem análise, visualização direta dos dados e finalização automática da análise se um único caractere estiver fora do esquema de codificação atual. Até mesmo o Notepad ++ teve um punhado de vulnerabilidades. Evite qualquer coisa complexa ao visualizar arquivos não confiáveis.

Em segundo lugar, podemos ver os IDEs. Se você optar por abrir o arquivo em um IDE, você deve estar ciente de que alguns IDEs relataram erros. Aparentemente, o Visual Studio tem explorações disponíveis através do mecanismo de extensões, portanto, abrir uma solução pode ser problemático. Evitar IDEs evita toda uma classe de problemas entre você e o código não confiável. Furar com VI parece muito mais seguro.

Em terceiro lugar, podemos ver compiladores reais. Eu visitei alguns, incluindo Adobe, Microsoft, Java e o C / C ++ do GNU, e descobri que, em geral, o código compilar (e até mesmo o construção , assumindo que não há customização arquivo) é relativamente seguro, mas cada um desses compiladores possui ou teve explorações de segurança que podem surgir da execução dos binários compilados. Em outras palavras, eles não poderiam pegar seu sistema simplesmente compilando, mas eles poderiam executar código.

Portanto, supondo que o método de entrega já não tenha invadido seu sistema (por exemplo, seu cliente de e-mail foi invadido, ou a unidade USB que veio foi infectada ...), leia o código-fonte e compile o código-fonte é provavelmente seguro. Ao pesquisar seu software específico, você pode torná-lo ainda mais seguro, por exemplo, validando se o arquivo está na página de código correta, etc. A execução do código deve ser feita apenas em hardware com o qual você simplesmente não se importa. Não é uma VM, mas um computador totalmente diferente fisicamente, sem acesso à rede e sem arquivos confidenciais ou dispositivos externos. Mesmo que você pense que você entenda o código, pesquisas simples mostram que até mesmo compiladores têm bugs que podem permitir que uma exploração de estouro de buffer oculto espreite por trás e execute código arbitrário, mas somente se você escolher executar ou depurar o programa. A compilação real deve ser segura.

    
por 23.06.2015 / 23:30
fonte
2

Bem, gostaria de começar com "revisar o código". Por que é necessário realmente executar o código?

Além disso, há muitos compiladores on-line onde você pode simplesmente colocar o código e compilá-lo e / ou executá-lo. Você pode tornar isso um requisito: ele compila neste e naquele compilador on-line.

Veja um exemplo de uma página com compiladores on-line: compiladores on-line

O código para revisão de uma entrevista de emprego não deve ser tão grande de forma alguma para você não entender o que está acontecendo.

    
por 23.06.2015 / 14:05
fonte
2

Are compilers typically validated to ensure they won't pwn the user machine when compiling some clever piece of code?

Em geral, eles são muito complexos e geralmente são escritos em idiomas nos quais não é prático provar essa propriedade.

Possivelmente não com essa intenção específica, mas a noção de compiladores de teste fuzz é pelo menos conhecida ( O LLVM agora pode testar o próprio fuzz ). Testes destinados a capturar a entrada que trava o compilador devido a erros do compilador tendem a também revelar falhas exploráveis.

Naturalmente você teria que investigar se o compilador específico em que você está interessado é testado ou fuzz-tested para encontrar falhas potenciais, e se os erros encontrados são realmente consertados. A regra prática é que, se houver falhas piores do que as exceções não memorizadas, sem investigar os detalhes, é necessário considerar uma possibilidade séria de que elas possam ser aproveitadas em explorações.

How safe is it to compile a piece of code from a stranger?

Infelizmente, quanto tempo é um pedaço de corda. Em princípio o email pode explorar seu cliente de email, ou o código-fonte pode explorar seu editor de texto ou cppcheck, antes mesmo de chegar ao seu compilador. A sugestão de Sebastian em comentários para usar um compilador online é muito boa, mas é claro que o código tem que estar em uma forma que o compilador aceitará.

Qualquer linguagem ou compilador com recursos para execução em tempo de compilação de código geral é altamente suspeito. Modelos de C ++ são funcionalmente completos, mas não têm acesso (pretendido) ao sistema, então eles são relativamente de baixo risco. BЈовић menciona make como extremamente alto risco (já que está executando o código do estranho, é só que o código é escrito na linguagem make , não no C ++). Se o compilador executar system , você estará no mesmo barco. Eu costumava trabalhar com um montador que, se bem me lembro, poderia fazer uma execução arbitrária de código em tempo de compilação. Ele foi planejado para calcular tabelas de consulta, mas acho que nada impediu que você fizesse chamadas do sistema.

Na prática , se o código parecer bom para mim e eu achar que entendi, então eu consideraria um risco extremamente baixo de compilá-lo, um risco bem menor do que dizer "navegar na internet com um navegador bloqueado ". Eu faço coisas mais arriscadas rotineiramente na minha máquina de propósito geral, mas muitas delas eu não faria, e. dentro de um laboratório de vírus ou em um servidor crítico. Se o código é engraçado ou evidentemente ofuscado, talvez eu não me arrisque a compilá-lo porque, além do risco de conter um exploit escondido no lixo ilegível, é um código de lixo. O código dissimulado é difícil, mas é possível. O código não autorizado que pwns a máquina através de uma exploração do compilador precisa conter uma carga útil não-trivial, então é extremamente difícil.

Se você quiser analisar isso ainda mais, tente perguntar ao pessoal que hospeda os compiladores on-line. Se isso não tiver sido feito com eles (exceto se você chegar à atenção da NSA ou equivalente), você pode razoavelmente assumir que isso não será feito para você. Eles colocam algum esforço em executar o compilador em uma sandbox adequada, o que pode ser mais trabalhoso do que você está disposto a ir, mas eles podem pelo menos ser capazes de dizer com que frequência esse sandbox os poupa problemas.

    
por 23.06.2015 / 15:17
fonte
1

Embora isso seja geralmente uma preocupação, acho que o problema é inexistente devido à configuração.

O candidato enviou-lhe algum código-fonte. Como ou por que isso aconteceu?

Bem, obviamente, existem apenas três possibilidades:

  1. Você deu ao candidato uma tarefa para resolver um problema específico (bem definido) para avaliar suas habilidades.
  2. O candidato quer mostrar algo legal que escreveu.
  3. O candidato é um idiota ou um espião ou uma pessoa maliciosa e não está realmente interessado em ser contratado. Tudo o que ele espera é que você seja estúpido o suficiente para executar o código dele.

Cerca de 2) e 3)

O principal risco é distinguir entre 2) e 3). As chances são altas de que, se qualquer coisa que ele escreveu, vale a pena olhar para ele, é algo que você pode obter o código-fonte para on-line (de uma fonte "neutra") e com o qual você pode até estar familiarizado. ou é algo que você realmente não quer ver porque você infringe a propriedade intelectual de um concorrente (ex-empregador). O último significaria que você não iria querer contratar essa pessoa de qualquer maneira. Se você puder obter a fonte online, faça isso. Se você puder verificar a contribuição do candidato para um software bem conhecido (incluindo software proprietário) com seu nome em algum lugar nos créditos, faça-o.
Em todos os outros casos, simplesmente ignore o que ele lhe enviou. Não vale a pena olhar, ou é ilegal ou de alto risco.

Aproximadamente 1)

O candidato enviou-lhe uma coisa porque você deu a ele uma tarefa. Se você tem alguma competência (que eu suponho que você faça!), Então, para uma atribuição típica de programação (que você mesmo escolheu!), Você será capaz de dizer se é uma solução plausível. parece que pode funcionar olhando o código-fonte por menos de 30 segundos (mais provavelmente 10 segundos).

Se você não pode dizer que o programa provavelmente funcionará (ou o que ele está fazendo) dentro de 30 segundos, aquele que escreveu não é o tipo de pessoa que você deseja contratar, fullstop. Você quer que as pessoas escrevam códigos que outros humanos possam entender e manter. Você não quer alguém que esteja tentando ser esperto em você, nem alguém que vença regularmente o concurso C ofuscado. Não importa se o programa funciona. Assim que outra pessoa não consegue entender o código, ele nunca "funciona". Se o programa parece que provavelmente funcionará, mas você encontrar qualquer coisa que pareça "estranha" (digamos, sequências de escape unicode Java, literais C ++, material que se parece com trigramas, qualquer), trate a tarefa como "falha", mova para o próximo candidato. Não é necessário incluir nada parecido em 99% de todos os programas (e, com certeza, não em sua tarefa - espero). Então, se você encontrar algo "estranho" assim, o candidato não é alguém que você vai querer contratar.

Se o código passar nessa primeira triagem, você pode querer passar mais 2 a 3 minutos examinando-a com mais detalhes. Se você ainda está satisfeito com o que vê depois disso, você pode executá-lo através de um analisador estático e compilá-lo em uma máquina virtual em um nível de alerta alto.

Isso deve trazer problemas que você pode ter perdido ao ler a fonte (como invocar comportamento indefinido ou restringir a conversão). Compilar em primeiro lugar vai dizer se o candidato tem a diligência necessária e atenção aos detalhes, não tanto se ele tem habilidade de programação. Assim como escrever o nome do empregador corretamente em seu aplicativo e verificar a ortografia do seu CV antes de entregá-lo, é uma boa prática certificar-se de que o código-fonte que você compila sem erros (e preferencialmente sem avisos). Se alguém não fizer isso, você não quer contratá-lo.

O risco de coisas ruins acontecerem neste ponto (explorando o compilador e saindo da VM) é negligenciável, vendo como você já executou uma verificação de plausibilidade sobre o código. Não vai acontecer.

    
por 24.06.2015 / 12:08
fonte
0

Se a possibilidade o preocupa, pegue uma máquina antiga (a maioria de nós não tem um monte de gente por perto?), instale a versão atual do Linux e do compilador, copie o código fonte para ela, desconecte o cabo de rede (ou desligue o WiFi) e faça as compilações. Se alguma coisa desagradável acontecer, ela não afetará mais nada.

E para malware no Makefile, execute-o com o sinalizador -n (IIRC, RTMF) para ver o que ele fará sem realmente fazer isso.

* A menos que seu programador codifique o malware para que ele aguarde uma reconexão, mas nesse caso você a) limpe a máquina; e b) encaminhar o currículo do cara para a NSA, porque ele está perdido no mundo comercial: -)

    
por 23.06.2015 / 19:20
fonte
0

O resultado é que existe risco. O risco é bem pequeno, como outras respostas notam, mas existe um risco. Isso significa que você precisa fazer duas perguntas:

  1. O que posso fazer para reduzir o risco?
  2. O risco é alto o suficiente para que eu me importe?

O segundo é o que você colocou aqui nesta questão, mas é o foco errado para este caso em particular. A resposta para atenuar o risco é clara e prontamente disponível: não compile o código na sua máquina . Você tem duas maneiras óbvias de compilá-lo sem usar sua máquina:

  1. Use uma máquina virtual (como @FlorianMargaine apontou imediatamente nos comentários). Você simplesmente faz um instantâneo antes de compilar e restaura o instantâneo quando terminar.
  2. Use um serviço hospedado (como um compilador on-line).

Estas formas de mitigar seu risco são tão óbvias, baratas e de fácil acesso que não vale a pena gastar muito tempo tentando analisar o tamanho do risco. Basta fazer um deles e acabar com isso.

    
por 24.06.2015 / 01:06
fonte
0

O Visual Studio realmente avisa se você abrir um projeto em um local não confiável (por exemplo, download ou compartilhamento de rede).

Um exemplo de como isso poderia ser explorado seria com um projeto do WPF: você pode referenciar classes .NET a partir do XAML e fornecer cargas do IntelliSense, do VS e executar as classes referenciadas em tempo de design.

Isso significa que um invasor pode soltar um arquivo .dll malicioso no diretório bin, substituir o código-fonte por um não-malicioso e, em tempo de design, a DLL é executada. Após sua primeira compilação, todos os rastros do binário malicioso desaparecem.

Portanto, mesmo que todo o código fornecido seja "limpo", o compilador está livre de erros e você, é claro, nunca executará manualmente nenhum arquivo .EXE fornecido. O código malicioso ainda pode ser executado em segundo plano. (Para estar protegido contra esse ataque específico, você pode apenas certificar-se de que NÃO há binários na árvore de diretórios antes de abrir a solução. O VS solicitará que você crie a solução antes de fornecer o IntelliSense em tempo de design.)

Vetores semelhantes provavelmente existem com outras linguagens / sistemas operacionais.

    
por 24.06.2015 / 04:15
fonte
0

Lendo código-fonte: totalmente seguro. Compilando o código fonte: totalmente seguro. Executando binários compilados: bem ... isso depende.

A compilação é apenas o computador que lê o código-fonte e grava seu equivalente em formato binário. Após a compilação, você só tem dois documentos: um legível por humanos e outro legível por computador. A menos que você consiga que o computador leia (ex. Execute) o segundo documento, nada vai acontecer.

    
por 23.06.2015 / 14:06
fonte
-1

Acho que você está preocupado com um dos dois sabores:

  • malware sofisticado e orientado a exploits : improvável, especialmente porque eles são direcionados a hardware e / ou software muito específico e [com base na sua pergunta] seu invasor provavelmente não possui esse nível de conhecimento do sistema. / li>
  • coisas que estragam o seu ambiente : diretivas de travessuras maliciosas (por exemplo, excluir seu diretório pessoal) ou diretivas inconsideradas / incompetentes que alteram o comportamento do seu sistema (por exemplo, reescrevendo variáveis de ambiente PATH ou LIBRARY)

Algumas pessoas sugeriram máquinas virtuais ou sistemas antigos, mas eu ofereço uma solução muito mais fácil: compilar como usuário diferente com permissões reduzidas / diferentes . Muito mais fácil do que configurar uma máquina virtual ou um computador dedicado.

Se for improvável que seu sistema seja invadido por explorações em tempo de compilação, restaure a partir de backups (você tem esses, certo?).

    
por 23.06.2015 / 23:26
fonte