¿Qué medida de seguridad se debe implementar antes de ejecutar los archivos cargados por el usuario?

39

Quiero hacer un pequeño rompecabezas de programación en mi sitio web. Va a haber una tarea. Se le pedirá al usuario que cargue un archivo fuente de C ++ con su solución. El archivo debe compilarse, ejecutarse con alguna entrada y comprobarse si produce la salida correcta. ¿Cuáles son los riesgos de seguridad? ¿Cómo me aseguro de que el archivo cargado no pueda hacer nada malicioso?

Alternativamente, hay sitios como Tutorials Point que te permiten compilar y ejecutar el código C ++. ¿Cómo gestionan la seguridad?

    
pregunta Jen 06.02.2017 - 02:30
fuente

3 respuestas

53

Es imposible analizar un programa para averiguar si hará algo malicioso. Esto es cierto independientemente de si está intentando analizar el código fuente o el código compilado.

La forma de hacer lo que está pidiendo se hace compilando y ejecutando el código en un arenero. Una vez que el programa ha finalizado (o después de un tiempo de espera que ha decidido), destruye el arenero.

La seguridad de tal construcción es tan segura como la caja de arena que está utilizando. Dependiendo de los requisitos del código que necesita para ejecutar el sandbox, puede ser algo simple como el modo de computación segura de Linux, o algo complicado como una máquina virtual completa, idealmente sin conectividad de red.

Cuanto más complicado sea el recinto de seguridad, mayor será el riesgo de una vulnerabilidad de seguridad en el recinto de seguridad que socava un diseño que de otra manera sería bueno.

Algunos idiomas se pueden compilar de forma segura fuera de un arenero. Pero hay idiomas donde incluso compilarlos puede consumir una cantidad impredecible de recursos. Esta pregunta en un sitio asociado muestra algunos ejemplos de cómo un código fuente pequeño puede explotar en una salida grande.

Si el compilador en sí está libre de vulnerabilidades, puede ser suficiente para establecer límites en la cantidad de CPU, memoria y espacio en disco que puede consumir. Para mayor seguridad, puede ejecutar el compilador dentro de una máquina virtual.

Obviamente, estos métodos se pueden combinar para una capa adicional de seguridad. Si tuviera que construir un sistema así, probablemente iniciaría una máquina virtual y dentro de la máquina virtual usaría ulimit para limitar el uso de recursos del compilador. Luego vincularía el código compilado en un contenedor para ejecutarlo en modo de computación segura. Finalmente, aún dentro de la máquina virtual, ejecutaría el ejecutable vinculado.

    
respondido por el kasperd 06.02.2017 - 02:49
fuente
28

Este es un problema realmente difícil, y uno que todos los jueces de códigos en línea deben resolver. Básicamente, está preguntando cómo puede evitar que alguien que puede ejecutar un código arbitrario en su máquina lo tome.

He estado programando en un juez en línea ( Kattis ) durante aproximadamente una década, y estas son algunas de mis experiencias de construcción Las soluciones de seguridad para este tipo de escenario:

  1. Las primeras versiones estaban basadas en una cárcel de Solaris. Resulta que puedes causar bastantes estragos dentro de una cárcel, y no te da la granularidad que necesitas.
  2. Implementamos una solución de filtrado de llamadas al sistema usando ptrace. Esto introduce una gran sobrecarga (en varios cambios de contexto) en la llamada al sistema, y mantener el perfil de seguridad sincronizado a medida que cambian los compiladores y los corredores es una pesadilla. El último clavo en el ataúd para esta solución fue roscado. Si permite el subprocesamiento, una aplicación puede utilizar un subproceso para volver a escribir la llamada al sistema entre la inspección y la ejecución, y por ejemplo, Java requiere el subprocesamiento.
  3. En estos días usamos una combinación de cgroups y espacios de nombres. Esto proporciona una sobrecarga sorprendentemente baja, y como estos son parte de las primitivas de seguridad en el kernel de Linux, son robustos. Echa un vistazo a MOE Isolate para tener una idea de cómo se puede hacer esto. Aislar lo más probable es que resuelva su problema.

Tenga en cuenta que si bien los contenedores, como la ventana acoplable o las máquinas virtuales, son populares, es posible que no sean la mejor opción para una solución de seguridad en este tipo de escenario. Es difícil obtener el control detallado y la supervisión de recursos que probablemente desee, es difícil evitar que un proceso malicioso se atasque dentro de su contenedor y, comenzar y destruir los contenedores tiene una gran cantidad de gastos generales.

    
respondido por el pehrs 06.02.2017 - 14:45
fuente
7

En el caso particular de un sitio web de rompecabezas, considere la alternativa: no se moleste. Pida a los participantes que carguen la salida para que no tenga que ejecutar código no confiable. Esto le ahorra poder de cómputo, evita riesgos de seguridad y permite que las personas compitan en cualquier idioma. Si hay un premio en juego, puede verificar la entrada ganadora de forma manual.

Si la forma de tu rompecabezas lo permite, puedes frustrar las soluciones de copiar y pegar generando entradas aleatorias y escribiendo un verificador. Así es como funciona Google Code Jam. Consulte enlace

    
respondido por el Colonel Panic 06.02.2017 - 16:32
fuente

Lea otras preguntas en las etiquetas