¿Qué tan seguro es compilar una parte del código fuente de un extraño al azar? [cerrado]

40

Supongamos que estoy revisando el código que los solicitantes de empleo envían para demostrar sus habilidades. Claramente no quiero ejecutar los ejecutables que envían. No es tan claro que prefiero no ejecutar el resultado de la compilación de su código (solo por ejemplo, Java permite ocultar código ejecutable en comentarios ).

¿Qué hay de compilar su código? Quiero advertencias del compilador, si las hay, pero ¿qué pasa si su código contiene algunas secuencias de caracteres inteligentes que explotan mi compilador y mi compilador compromete mi máquina?

Cuando busco "vulnerabilidades del compilador" en Google, los resultados que recibo se refieren a las optimizaciones del compilador y la emisión de código, y si el código emitido es tan seguro como el código fuente original estaba destinado.

¿Los compiladores suelen validarse para garantizar que no comprometan la máquina del usuario al compilar algún código inteligente? ¿Qué tan seguro es compilar un fragmento de código de un extraño?

    
pregunta sharptooth 23.06.2015 - 13:27

13 respuestas

32

Depende.

Esta pieza de makefile podría eliminar su directorio de inicio:

all:
    rm -rf ~

Entonces, si necesita usar una herramienta (como cmake o makefile system), entonces no es seguro. Solo depende de lo malicioso que sea el codificador.

Por otro lado, los compiladores están programados por personas, por lo tanto tienen errores. Entonces, tal vez podría ser posible que alguien haya encontrado una forma de ejecutar código malicioso durante la compilación.

Como se sugiere en los comentarios, si desea asegurarse de que no se están haciendo cosas divertidas en su máquina, use una máquina virtual.

    
respondido por el BЈовић 23.06.2015 - 14:52
23

Estoy bastante seguro de que en algún lugar del negocio hay algunos tipos inteligentes que ya han creado un hack para un idioma específico y una versión del compilador. Mi lugar favorito para buscar algo como esto probablemente sería el concurso internacional de C ofuscado - (no sé si hay algo comparable para Java). Sin embargo, en realidad, ¿qué tan alto considera el riesgo, asumió que

  • el solicitante le hace una impresión plausible de que realmente quiere el trabajo en su empresa (y no en una demanda)

  • el tipo no sabe cuánto se hace la revisión en la suya

  • no sabe qué versión exacta de compilador está utilizando

  • no sabe si usas un entorno virtual o un compilador en línea, solo para estar seguro

  • no acepta programas que sean demasiado grandes para ser revisados de manera efectiva

  • no compilas nada que te parezca sospechoso

  • no hay muchas personas en el mundo que realmente sepan cómo realizar técnicamente una tarea de este tipo (y solo con Google no le dará una "referencia rápida" o tutorial sobre esto, como ya descubrió usted mismo).

Entonces, aunque la compilación no es "totalmente segura" en teoría, en mi humilde opinión, el riesgo es extremadamente bajo de que su "compilador sea pwned".

    
respondido por el Doc Brown 23.06.2015 - 14:23
11

Tenemos que distinguir varios casos:

  1. Un error en el compilador. Como todos los programas complejos, un compilador puede tener errores, y uno de esos errores puede ser explotable.
  2. Un caballo de Troya. El atacante puede hacer que ejecutes un código arbitrario como parte del proceso de compilación. Un Makefile , un build.xml , un configure shell script, etc. Técnicamente, esto no se debe a la compilación del código del atacante sino a la configuración del entorno de compilación.
  3. Idiomas que permiten que se ejecute código arbitrario en tiempo de compilación. El lenguaje de macros de Scala es Scala, el lenguaje de macros de Common Lisp es Common Lisp, el lenguaje de macros de la plantilla de Haskell es Haskell. Scala también tiene complementos de compilación, que nuevamente son códigos de Scala arbitrarios que se ejecutan en tiempo de compilación. F # tiene proveedores de tipo.
  4. Idiomas que permiten el cálculo de Turing en tiempo de compilación. Los sistemas de tipos de Scala y Haskell son Turing-completos, al igual que las Plantillas de C ++. Puede hacer que el compilador realice cálculos de Turing arbitrarios en el momento de la compilación, incluidos, entre otros, bucles infinitos. Tenga en cuenta que Turing-complete solo significa que puede calcular todas las funciones computables de Turing, no significa que pueda acceder al sistema de archivos o algo así. Pero, puedes hacer un programa que demore infinitamente en compilarse.
  5. Tiempos de compilación muy largos. Por ejemplo, las reglas de C # para la resolución de sobrecargas son tan complejas que puede codificar cualquier problema 3-SAT como la resolución de sobrecarga C #. 3-SAT es, por supuesto, famoso NP-completo. En otras palabras, de acuerdo con nuestro conocimiento actual, es imposible encontrar un algoritmo eficiente para la resolución de sobrecargas en C #. No se puede hacer que la compilación tarde infinitamente, pero no se necesita un gran programa para que la compilación tome más tiempo que la vida del universo, que es prácticamente lo mismo.

# 4. y # 5. a lo sumo resultará en una denegación de servicio. En la práctica, los compiladores de C ++ y Scala limitan la cantidad de recursión que puede hacer, por lo que no es posible en realidad escribir un bucle infinito. En Scala, eso es solo una restricción de implementación, pero en C ++, creo que está explícitamente permitido por la especificación.

# 2. está técnicamente fuera del alcance de la pregunta porque la pregunta era acerca de compilar el código que no lo está ejecutando (OTOH, está la pregunta filosófica profunda: si la comprobación de tipo de un programa Haskell puede realizar un cálculo de Turing arbitrario, ¿es esa compilación o está ejecutando un programa?)

# 1. es improbable Por un lado, los compiladores de producción son muy complejos, por lo que la probabilidad de errores es alta. Por otro lado, son rigurosamente probados, después de todo, el manejo correcto de una entrada mal formada es parte de la descripción del trabajo de un compilador. Incluso si no se prueban, serán bombardeados con códigos mal formados de todos modos ... ¡solo mire algunas preguntas de StackOverflow para ver ejemplos de lo que la gente de la basura tira a sus compiladores!

Esto nos deja con 3. Algunos compiladores pueden limitar el tipo de acceso que el código de tiempo de compilación tiene al sistema, pero para algunos de los casos de uso, tener acceso completo es inevitable. El propósito de los proveedores de tipos de F #, por ejemplo, es "falsificar" tipos sintéticos para los datos cuyo sistema de tipos no coincide con los de F #, de modo que pueda interactuar con, por ejemplo, un servicio web que tenga un esquema WSDL en una Moda. Sin embargo, para hacer esto, el proveedor de tipos necesita tener acceso al recurso de esquema WSDL en el sistema de archivos o en la web, por lo que necesita tener acceso a la red y al sistema de archivos.

Entonces, ¿es seguro? Técnicamente, no. ¿Es arriesgado? En realidad no.

    
respondido por el Jörg W Mittag 23.06.2015 - 17:18
3

No debería haber ningún riesgo simplemente compilando el código. En theory podría haber un error en el compilador que un pirata informático inteligente podría aprovechar, pero parece extremadamente improbable.

Tenga en cuenta que la construcción puede no ser segura. Por ejemplo, en C # 'evento de compilación' le permite especificar líneas de comando arbitrarias para ejecutar antes y después de la compilación, lo que obviamente es peligroso, y mucho más fácil de explotar que los desbordamientos de búfer en el código del compilador.

    
respondido por el JacquesB 23.06.2015 - 14:06
3

En lugar de especular, me molesté en hacer una investigación sobre este tema antes de responder, yendo al recurso más autoritario que se me ocurre ( CVE Details ). Esta lista completa de vulnerabilidades de seguridad divulgadas públicamente es probablemente lo mejor que uno podría hacer para evaluar los niveles de amenaza de varios tipos de software.

No me tomé el tiempo de leer todo del material disponible, por supuesto, pero seleccioné algunos compiladores, IDE y editores de texto "primarios" para elaborar una muestra de evaluación de amenazas. . Si se toma en serio la posibilidad de ejecutar cualquier software, al menos debería ver qué amenazas existen. También tenga en cuenta que el software más antiguo generalmente tiene más errores que el software más nuevo, por lo que ejecutar lo último de lo que sea que esté ejecutando es ideal.

Primero, podemos echar un vistazo a varios editores de texto. Parece que los mejores editores son los más simples. Vi si estás usando un shell de Linux, o Bloc de notas si estás en Windows. Algo sin capacidades de formato, sin análisis, solo visualización directa de datos y terminación automática del análisis si un solo carácter está fuera del esquema de codificación actual. Incluso Notepad ++ ha tenido un puñado de vulnerabilidades. Evite cualquier cosa compleja cuando vea archivos que no sean de confianza.

Segundo, podemos mirar los IDEs. Si elige abrir el archivo en un IDE, debe tener en cuenta que algunos IDE han reportado errores. Aparentemente, Visual Studio ha tenido exploits disponibles a través del mecanismo de extensiones, por lo que abrir una solución podría ser problemático. Evitar IDEs evita una clase completa de problemas entre usted y el código no confiable. Quedarse con VI parece mucho más seguro.

En tercer lugar, podemos ver los compiladores reales. Busqué algunos, incluyendo Adobe, Microsoft, Java y C / C ++ de GNU, y encontré que, en general, compilaba el código (e incluso construye , asumiendo que no hay una marca personalizada file) es relativamente seguro, pero cada uno de esos compiladores tiene o tuvo vulnerabilidades de seguridad que podrían surgir al ejecutar los binarios compilados. En otras palabras, no pueden tomar su sistema simplemente compilando, pero pueden ejecutando el código.

Entonces, en conclusión, asumiendo que el método de entrega ya no secuestró su sistema (por ejemplo, su cliente de correo electrónico fue pirateado, o la unidad USB en la que se encontraba estaba infectada ...), leyendo el código fuente y compilando el código fuente. es probablemente seguro. Al investigar su software específico, podría hacerlo aún más seguro, por ejemplo, validando que el archivo está en la página de códigos correcta, etc. La ejecución del código solo debe realizarse en hardware que simplemente no le importa. No es una máquina virtual, sino una computadora completamente diferente, sin acceso a la red y sin archivos confidenciales o dispositivos externos. Incluso si piensa comprende el código, una investigación simple muestra que incluso los compiladores tienen errores que podrían permitir que un exploit de desbordamiento de búfer oculto se cuele por detrás y ejecute código arbitrario, pero solo si elige Ejecutar o depurar el programa. La compilación real debería ser segura.

    
respondido por el phyrfox 23.06.2015 - 23:30
2

Bueno, comenzaría con "revisando su código". ¿Por qué es necesario ejecutar el código?

Aparte de eso, hay muchos compiladores en línea donde puedes poner el código y compilarlo y / o ejecutarlo. Puede hacer que sea un requisito: compila en este y aquel compilador en línea.

Este es un ejemplo de una página con compiladores en línea: compiladores en línea

El código de revisión para una entrevista de trabajo no debe ser tan grande como para que no entiendas lo que está pasando.

    
respondido por el Pieter B 23.06.2015 - 14:05
2
  

¿Los compiladores suelen validarse para garantizar que no le ofrezcan al usuario?   ¿Máquina al compilar algún código inteligente?

En general, son demasiado complejos y, a menudo, se escriben en idiomas en los que no es práctico probar esta propiedad.

Posiblemente no con esta intención específica, pero la noción de compiladores de prueba fuzz es al menos conocida ( LLVM ahora puede hacer fuzz-test en sí mismo ). Las pruebas destinadas a captar la entrada que bloquea el compilador debido a errores del compilador tenderán a encontrar fallas explotables.

Naturalmente, tendrías que ver si el compilador específico en el que estás interesado está probado o no está probado para encontrar bloqueos potenciales, y si los errores encontrados están reparados. La regla de oro es que si hay accidentes peores que sin excepciones sin memoria, entonces, sin investigar más los detalles, debe considerar una posibilidad seria de que puedan aprovecharse para explotarlas.

  

¿Qué tan seguro es compilar un fragmento de código de un extraño?

Desafortunadamente, ¿cuánto tiempo es un trozo de cuerda? En principio el correo electrónico podría explotar su cliente de correo, o el código fuente podría explotar su editor de texto o cppcheck, incluso antes de que llegue al compilador. La sugerencia de Sebastian en los comentarios sobre el uso de un compilador en línea es bastante buena, pero, por supuesto, el código debe estar en una forma que el compilador acepte.

Cualquier lenguaje o compilador con facilidades para la ejecución en tiempo de compilación de código general es, por supuesto, altamente sospechoso. Las plantillas de C ++ están funcionalmente completas pero no tienen acceso (previsto) al sistema, por lo que son relativamente de bajo riesgo. BЈовић menciona make como extremadamente alto riesgo (ya que está ejecutando el código del extraño, es solo que el código está escrito en el lenguaje make , no en C ++). Si el compilador ejecuta system , entonces estás en el mismo barco. Solía trabajar con un ensamblador que, si recuerdo correctamente, podría hacer una ejecución de código de tiempo de compilación arbitraria. Fue diseñado para computar tablas de consulta, pero no creo que nada te impida hacer llamadas al sistema.

En la práctica , si el código me parece bien y creo que lo comprendo, consideraría que es un riesgo extremadamente bajo compilarlo, un riesgo mucho menor que decir "navegar por Internet con un navegador bloqueado ". Hago cosas más riesgosas de manera rutinaria en mi máquina de propósito general, pero muchas de ellas no las haría, por ejemplo. Dentro de un laboratorio de virus o en un servidor crítico. Si el código es divertido o está evidentemente ofuscado, entonces no me arriesgo a compilarlo porque, aparte del riesgo, podría contener un exploit oculto en la basura ilegible, es un código basura. El código infiltrado es difícil pero posible. El código secreto que maneja la máquina a través de un exploit de compilador debe contener una carga útil ejecutable no trivial, por lo que es extremadamente difícil.

Si desea profundizar en esto, intente preguntar a las personas que albergan compiladores en línea. Si no se lo han hecho a ellos, entonces (salvo que llame la atención de la NSA o su equivalente), puede suponer razonablemente que no se lo harán a usted. Hacen un poco de esfuerzo para ejecutar su compilador en una caja de arena adecuada, lo que podría ser más esfuerzo de lo que estás dispuesto a hacer, pero al menos podrían decirte con qué frecuencia la caja de arena les ahorra problemas.

    
respondido por el Steve Jessop 23.06.2015 - 15:17
1

Aunque esto es generalmente una preocupación, creo que el problema no existe debido a la configuración.

El solicitante te envió un código fuente. ¿Cómo o por qué sucedió eso?

Bueno, obviamente solo hay tres posibilidades:

  1. Le asignó al solicitante una tarea para resolver un problema particular (bien definido) para evaluar sus habilidades.
  2. El solicitante quiere mostrar algo bueno que escribió.
  3. El solicitante es un imbécil o un espía o una persona maliciosa y no está realmente interesado en ser contratado. Todo lo que espera es que seas lo suficientemente estúpido como para ejecutar su código.

Acerca de 2) y 3)

El principal riesgo es distinguir entre 2) y 3). Las posibilidades son altas de que si lo que escribió es que vale la pena mirar , es algo con lo que puede obtener el código fuente en línea (de una fuente "neutral") y es posible que ya esté familiarizado con eso. o es algo que en realidad no quiere ver porque infringiría la propiedad intelectual de un competidor (antiguo empleador). Esto último significaría que no querrías contratar a esa persona de todos modos.
Si puede obtener la fuente en línea, hágalo. Si puede verificar la contribución del solicitante a un software conocido (incluido el software propietario) por su nombre en algún lugar de los créditos, hágalo.
En cualquier otro caso, simplemente ignora lo que te envió. No vale la pena verlo, ni es ilegal, ni de alto riesgo.

Acerca de 1)

El solicitante te envió algo porque le diste una tarea. Si tiene alguna competencia (¡lo cual supongo que tiene!), Entonces para una asignación de programación típica (... ¡que incluso se eligió a sí mismo!), Podrá decir si es una solución plausible parece que podría funcionar al mirar el código fuente durante menos de 30 segundos (más probablemente 10 segundos).

Si no puede decir que el programa probablemente funcionará (o lo que está haciendo) dentro de los 30 segundos, el que lo escribió no es el tipo de persona que desea contratar. Quieres personas que escriban códigos que otros humanos puedan entender y mantener. No quieres a alguien que intente ser inteligente contigo, ni a alguien que gane regularmente el concurso de C ofuscado. Ni siquiera importa si el programa funciona. Tan pronto como otra persona no puede entender el código, nunca "funciona". Si el programa parece que probablemente funcionará, pero encuentras algo que parece "extraño" (por ejemplo, secuencias de escape de Java Unicode, literales de cadena cruda de C ++, cosas que parecen trigrafos, lo que sea), trata la asignación como "fallida", mueve en el siguiente solicitante. No es necesario incluir nada parecido en el 99% de todos los programas (y, por supuesto, no en su tarea, espero). Por lo tanto, si encuentra algo "extraño" como ese, el solicitante no es alguien que querrá contratar.

Si el código pasa la primera clasificación, es posible que desee dedicar otros 2 o 3 minutos a examinarlo más detenidamente. Si aún está satisfecho con lo que ve después de eso, puede ejecutarlo a través de un analizador estático y compilarlo en una máquina virtual con un alto nivel de advertencia.

Eso debería mostrar los problemas que puede haber perdido al leer la fuente (como invocar un comportamiento indefinido o reducir la conversión). En primer lugar, la compilación le dirá si el solicitante tiene la diligencia necesaria y la atención a los detalles, no tanto si tiene habilidades de programación. Al igual que escribir correctamente el nombre del empleador en su solicitud y revisar la ortografía de su CV antes de entregarlo, es una buena práctica que se asegure de que el código fuente que entrega se compile sin errores (y preferiblemente sin advertencias). Si alguien no lo hace, no desea contratarlo.

El riesgo de que ocurran cosas malas en este punto (explotando el compilador y saliendo de la máquina virtual) es despreciable, ya que se ha realizado una verificación de plausibilidad sobre el código. No va a suceder.

    
respondido por el Damon 24.06.2015 - 12:08
0

Si le preocupa la posibilidad, tome una máquina más antigua (¿no tenemos la mayoría de nosotros sentados?), instale la versión actual de Linux y compilador & c, copie el código fuente en ella, desenchufe el cable de red (o apagar WiFi), y hacer las compilaciones. Si algo desagradable sucede, no afectará a ninguna otra cosa.

Y para el malware en Makefile, ejecútelo con la marca -n (IIRC, RTMF) para ver qué hará sin hacerlo realmente.

* A menos que, por supuesto, su programador haya codificado el malware para que espere una reconexión, pero en ese caso usted: a) borra la máquina; yb) enviar el currículum vitae del chico a la NSA, porque se desperdicia en el mundo comercial :-)

    
respondido por el jamesqf 23.06.2015 - 19:20
0

La conclusión es que existe riesgo . El riesgo es bastante pequeño como señalan otras respuestas, pero existe un riesgo. Eso significa que necesitas hacer dos preguntas:

  1. ¿Qué puedo hacer para mitigar el riesgo?
  2. ¿Es el riesgo lo suficientemente alto como para que me importe?

El segundo es lo que has planteado aquí en esta pregunta, pero es el enfoque equivocado para este caso en particular. La respuesta para mitigar el riesgo es clara y está disponible: no compile el código en su máquina . Tiene dos formas obvias de compilarlo sin utilizar su máquina:

  1. Use una máquina virtual (como @FlorianMargaine señaló inmediatamente en los comentarios). Simplemente tome una instantánea antes de compilar y luego restaure la instantánea cuando haya terminado.
  2. Use un servicio alojado (como un compilador en línea).

Estas formas de mitigar su riesgo son tan obvias, baratas y de fácil acceso que no vale la pena perder mucho tiempo tratando de analizar qué tan grande es el riesgo. Solo haz uno de ellos y termina con él.

    
respondido por el jpmc26 24.06.2015 - 01:06
0

Visual Studio en realidad le advierte si abre un proyecto desde una ubicación no confiable (e, g, descargado o recurso compartido de red).

Un ejemplo de cómo podría explotarse esto sería con un proyecto WPF: puede hacer referencia a las clases .NET desde XAML, y para proporcionar IntelliSense, VS carga y ejecuta las clases a las que se hace referencia en el momento del diseño.

Eso significa que un atacante puede colocar un archivo .dll malicioso en el directorio bin, reemplazar el código fuente por uno no malicioso y, en el momento del diseño, se ejecuta el archivo DLL. Después de su primera compilación, todos los rastros del binario malicioso desaparecen.

Entonces, aunque todo el código provisto está "limpio", el compilador está libre de errores y, por supuesto, nunca ejecutas manualmente ningún .EXE provisto, el código malicioso aún podría ejecutarse en segundo plano. (Para estar a salvo de ese ataque específico, puede asegurarse de que NO haya archivos binarios en el árbol de directorios antes de abrir la solución. VS le pedirá que cree la solución antes de proporcionar IntelliSense en el momento del diseño).

Es probable que existan vectores similares con otros lenguajes / sistemas operativos.

    
respondido por el Lukas Rieger 24.06.2015 - 04:15
0

Código fuente de lectura: totalmente seguro. Código fuente de compilación: totalmente seguro. Ejecutando binarios compilados: bueno ... eso depende.

Compilar es solo la computadora que lee el código fuente y escribe su equivalente en forma binaria. Después de la compilación, solo tiene 2 documentos: uno legible por humanos y otro legible por computadora. A menos que haga que la computadora lea (es decir, ejecute) el segundo documento, nada va a suceder.

    
respondido por el gbjbaanb 23.06.2015 - 14:06
-1

Creo que estás preocupado por uno de los dos sabores:

  • software malicioso sofisticado, dirigido a la explotación : poco probable, especialmente porque están dirigidos a hardware y / o software muy específicos y [según su pregunta] su atacante probablemente no tenga ese nivel de conocimiento del sistema.
  • cosas que se atornillan a su entorno : directivas de broma maliciosas (por ejemplo, eliminar su directorio de inicio) o directivas desconsideradas / incompetentes que cambian el comportamiento de su sistema (por ejemplo, volver a escribir las variables de entorno PATH o LIBRARY)

Algunas personas han sugerido máquinas virtuales o sistemas antiguos, pero ofrezco una solución mucho más sencilla: compilar como usuario diferente con permisos reducidos / diferentes . Mucho más fácil que configurar una máquina virtual o una computadora dedicada.

Si es poco probable que su sistema se vea afectado por las vulnerabilidades en tiempo de compilación, restaure desde copias de seguridad (las tiene, ¿no?).

    
respondido por el brian_o 23.06.2015 - 23:26

Lea otras preguntas en las etiquetas