Conozco a algunas personas que actualmente están trabajando en un proyecto para el ejército de los EE. UU. (Nivel de seguridad bajo, datos de tipo de recursos humanos sin combate).
Se envió un estado inicial del código del proyecto a los militares para su revisión, y ejecutaron el programa a través de algún tipo de herramienta de análisis de seguridad. Devolvió un informe de problemas de seguridad conocidos en el código y requirió cambios que debían implementarse antes de la entrega del producto final.
Uno de los elementos que debía resolverse era la eliminación de parte del proyecto que se escribió en Ruby, ya que es un lenguaje dinámico.
¿Cuál es el trasfondo / razón para no permitir que se use un lenguaje dinámico en una configuración segura? ¿Es este el gobierno que tarda en adoptar nuevas tecnologías? ¿O los lenguajes dinámicos presentan un riesgo de seguridad adicional en comparación con los lenguajes estáticos (ala C ++ o Java )?
fuente
Respuestas:
Hay una serie de cosas 'ordenadas' que se pueden hacer en lenguajes dinámicos que se pueden guardar en partes del código que no son inmediatamente obvias para otro programador o auditor en cuanto a la funcionalidad de un determinado código.
Considere esta secuencia en irb (shell ruby interactivo):
Lo que sucedió allí es que intenté llamar al método
foo
en una constante de cadena. Esto falló. Luego abrí la clase String y definí el métodofoo
o return"foobar!"
, y luego lo llamé. Esto funcionó.Esto se conoce como una clase abierta y me da pesadillas cada vez que pienso en escribir código en ruby que tenga algún tipo de seguridad o integridad. Claro que te permite hacer algunas cosas ordenadas bastante rápido ... pero podría hacerlo de manera que cada vez que alguien almacenara una cadena, la almacenara en un archivo o la enviara a través de la red. Y esta pequeña parte de la redefinición de la cadena se puede guardar en cualquier parte del código.
Muchos otros lenguajes dinámicos tienen cosas similares que se pueden hacer. Perl tiene Tie :: Scalar que puede cambiar detrás de escena cómo funciona un escalar dado (esto es un poco más obvio y requiere un comando específico que puede ver, pero un escalar que se pasa desde otro lugar podría ser un problema). Si tiene acceso al Perl Cookbook, busque la Receta 13.15 - Creación de variables mágicas con empate.
Debido a estas cosas (y otras a menudo son parte de lenguajes dinámicos), muchos enfoques para el análisis estático de la seguridad en el código no funcionan. Perl and Undecidability muestra que este es el caso y señala incluso estos problemas triviales con el resaltado de sintaxis (
whatever / 25 ; # / ; die "this dies!";
plantea desafíos porquewhatever
se pueden definir para tomar argumentos o no en tiempo de ejecución derrotando por completo un resaltador de sintaxis o un analizador estático).Esto puede ser aún más interesante en Ruby con la capacidad de acceder al entorno en el que se definió un cierre (ver YouTube: Mantener a Ruby Razonable de RubyConf 2011 por Joshua Ballanco). Fui informado de este video de un comentario de Ars Technica por MouseTheLuckyDog .
Considere el siguiente código:
Este código es completamente visible, pero el
mal
método podría estar en otro lugar ... y con clases abiertas, por supuesto, podría redefinirse en otro lugar.Ejecutando este código:
En este código, el cierre pudo acceder a todos los métodos y otros enlaces definidos en la clase en ese ámbito. Escogió un método aleatorio y lo redefinió para generar una excepción. (vea la clase Binding en Ruby para tener una idea de a qué tiene acceso este objeto)
Una versión más corta que muestra la redefinición de una variable:
Que, cuando se ejecuta produce:
Esto es más que la clase abierta que mencioné anteriormente que hace imposible el análisis estático. Lo que se demostró anteriormente es que un cierre que se pasa a otro lugar, lleva consigo el entorno completo en el que se definió. Esto se conoce como un entorno de primera clase (al igual que cuando puede pasar funciones, son funciones de primera clase, Este es el entorno y todos los enlaces disponibles en ese momento). Se podría redefinir cualquier variable que se definió en el alcance del cierre.
Bueno o malo, quejándose de rubí o no (hay usos donde uno quieren ser capaces de conseguir en el entorno de un método (véase Segura en Perl)), la cuestión de "¿por qué el rubí estar restringido en un proyecto del gobierno "Realmente se responde en ese video vinculado anteriormente.
Dado que:
Con las implicaciones de estas cuatro opciones de diseño, es imposible saber qué hace cualquier parte del código.
Puede leer más sobre esto en el blog Abstract Heresies . La publicación particular es sobre Scheme, donde se tuvo ese debate. (relacionado con SO: ¿Por qué Scheme no admite entornos de primera clase? )
Espero que esta sección muestre el aspecto peligroso de los entornos de primera clase y por qué se le pediría que elimine a Ruby de la solución provista. No se trata solo de que Ruby sea un lenguaje dinámico (como se mencionó en otra respuesta, se han permitido otros lenguajes dinámicos en otros proyectos), sino que hay problemas específicos que hacen que algunos lenguajes dinámicos sean aún más difíciles de razonar.
fuente
"many approaches to static analysis of security in code doesn't work"
, por lo que se rechaza porque no puede ser analizada (al menos por este grupo). Si lo estoy interpretando bien o si esa es una razón válida para rechazarlo, no lo sé.Asumiendo que la evaluación fue solo de seguridad, y no solo un escaneo de aceptación (es decir, no aceptan a Ruby porque no quieren apoyar a Ruby) entonces:
Las herramientas de análisis de seguridad suelen tener un mal momento con comportamientos dinámicos.
Por ejemplo:
Ejecute cualquier proyecto .NET escrito con características modernas como ASP.NET MVC y Entity Framework a través de algo como Veracode y vea qué tipo de lista de falsos positivos recibe en su informe.
Veracode incluso enumera muchas técnicas básicas dentro de las bibliotecas principales de .NET 4 como "marcos no compatibles" como no compatibles o beta solo aunque la mayoría de ellos tienen varios años en este momento.
Si se trata de una entidad que tiene una gran dependencia de dicha herramienta, casi se ven obligados a considerar a aquellos inseguros si no tienen la experiencia técnica y los recursos para evaluar manualmente un proyecto y ver si está escrito y seguro.
En las operaciones civiles donde los sistemas informáticos generalmente no controlan nada peligroso o terriblemente costoso, la mitigación es que se discuten los falsos positivos y generalmente se aceptan como tales a granel.
En las operaciones bancarias todavía tiene la posibilidad de una mitigación de falsos positivos, pero va a pasar mucho más tiempo discutiendo las minucias de cada elemento. Esto rápidamente se convierte en un costo prohibitivo y comienza a utilizar métodos más tradicionales.
En el ejército, la aviación, la industria pesada y similares, los sistemas pueden controlar cosas que tienen modos de falla terribles, por lo que pueden tener reglas muy estrictas sobre idiomas, compiladores, etc.
Las organizaciones también generalmente escriben su política de seguridad para el peor de los casos que conocen, por lo que incluso si está escribiendo algo trivial, si lo está escribiendo para una organización que tiene sistemas no triviales, el valor predeterminado generalmente será retenerlo. un estándar más alto a menos que alguien solicite una excepción específica.
fuente
Se pueden usar lenguajes dinámicos en aplicaciones militares y de defensa. Personalmente he usado y entregado Perl y Python en aplicaciones DoD. También he visto PHP y JavaScript utilizados y desplegados. En mi experiencia, la mayoría del código no compilado que he visto ha sido scripts de shell y Perl porque los entornos requeridos están aprobados e instalados en una variedad de posibles sistemas de destino.
El hecho de que estos lenguajes sean dinámicos probablemente no sea el problema. Los intérpretes para estos idiomas deben estar aprobados para su uso en los sistemas de destino. Si el intérprete no está aprobado para su uso (o tal vez sí, pero no está implementado en los sistemas de destino), entonces no se puede usar el idioma. El uso de un intérprete determinado (o cualquier aplicación) en un sistema seguro requiere cualquier número de obstáculos de seguridad: análisis de la fuente, la capacidad de compilar desde la fuente para entornos de destino, análisis adicional de los binarios, garantizar que no haya conflictos con la infraestructura existente, etc.
fuente
Pasé algún tiempo entrevistando con el Departamento de Defensa (DOD), para obtener un código de posición para la MMU del F-16 . Sin violar ninguna divulgación: la MMU es la unidad de computadora que controla casi todas las funciones del F-16. Es (obviamente) crítico que no se produzcan errores, como errores de tiempo de ejecución, durante el vuelo. Es igualmente crítico que el sistema realice operaciones informáticas en tiempo real.
Por esta y otras razones históricas, todo el código para este sistema está escrito o compilado en ADA, un lenguaje de programación estático orientado a objetos .
Odio citar demasiado, pero esto explica muy bien por qué se usan exactamente lenguajes estáticos (como ADA) para proyectos como este:
fuente
Tanto DoD como NASA tienen una larga historia con fallas de programación que les costaron miles de millones de dólares. Ambas instituciones han aceptado procesos que deberían protegerlos de la repetición de los mismos errores.
Esta es una idea errónea: los lenguajes dinámicos no son una tecnología nueva, son bastante antiguos. El problema es que si alguna vez tuvo un problema causado por un lenguaje dinámico (por ejemplo, por un tipeo débil / dinámico) y ese problema le costó mucho dinero, podría aceptar una política que le impediría volver a cometer el mismo error, por ejemplo Prohibir el uso de lenguajes dinámicos en sistemas sensibles.
Los lenguajes dinámicos a menudo "tragan" errores y terminan con un comportamiento inesperado. Esto es muy peligroso en sistemas sensibles. Si sucede algo incorrecto, desea saberlo lo antes posible.
Si se trata de seguridad, sería necesario ver el caso de uso real. Por ejemplo, no creo que una página web de Ruby on Rails sea automáticamente menos segura que una página web de Java.
fuente
Me gustaría agregar a las respuestas existentes describiendo SA-CORE-2014-005 de Drupal , que es una vulnerabilidad muy crítica que permite la inyección de SQL y, en última instancia, la ejecución de código arbitrario. Está causada por las reglas de tipeo dinámico y tipeo de ejecución laxa de PHP.
La totalidad del parche para este problema es:
Este código es parte de una capa de abstracción de SQL diseñada para evitar la inyección de SQL. Toma una consulta SQL con parámetros con nombre y una matriz asociativa que proporciona un valor para cada parámetro con nombre. Se permite que el valor sea una matriz, en casos como
WHERE x IN (val1, val2, val3)
, donde los tres valores se pueden pasar como un solo valor de matriz para un único parámetro con nombre.La vulnerabilidad se produce porque el código se supone que
$i
en$i => $value
debe haber un índice entero del valor. Continúa y concatena este "índice" directamente en la consulta SQL como parte del nombre de un parámetro, porque los enteros no necesitan ningún escape, ¿verdad?Desafortunadamente para Drupal, PHP no ofrece tal garantía. Es posible pasar otra matriz asociativa, cuyas claves son cadenas, y este bucle concatenará felizmente la clave de cadena en la consulta, tal como está (recuerde que el código cree que solo puede ser un entero).
Si bien hay formas de tener un error similar en un lenguaje de tipo estático, es poco probable. Un buen desarrollador consideraría las posibles cosas
$i
antes de concatenarlo en la consulta. Con un lenguaje tipado estáticamente, es muy fácil hacer cumplir que$i
debe ser un número entero, y en un código sensible a la seguridad como este, seguramente se haría.Además, el código realmente comprueba si el valor es una matriz antes de iterar sobre los elementos. Y aquí se encuentra una segunda parte de la falla que habilita esta vulnerabilidad: tanto una matriz asociativa como una matriz "normal" son verdaderas para
is_array
. Si bien también es cierto que en C #, tanto los diccionarios como las matrices lo sonIEnumerable
, es difícil construir código que combine las claves del diccionario con índices de matrices como este, incluso intencionalmente, y mucho menos accidentalmente.fuente
Si una base de código es segura o no depende de cómo escriba su código, cómo lo pruebe y cómo valide y monitoree su proceso de desarrollo e implementación. Los idiomas no son seguros ni inseguros, así es como codifica.
La mayoría de los incidentes de seguridad debidos a entradas maliciosas (inyecciones de sql, desbordamientos de búfer), virus, rootkits y troyanos. Ningún idioma puede protegerte de eso.
Por lo tanto, prohibir las clases de idiomas por ser "inseguros" no es una razón válida.
Sospecho que alguien, por cualquier razón, informado o no, decidió prohibir estos idiomas. Después de un tiempo se convirtió en una verdad organizacional . Puede haber sido cierto en ese momento para algunos proyectos, pero las culturas de control no están interesadas en cambiar las decisiones (admitir que estaban equivocadas) y prefieren reglas simples. Prosperan con las reglas y regulaciones y no importa si tienen sentido o no, lo que cuenta es la seguridad percibida .
Esto sucede todo el tiempo en las culturas de control. Lo veo más o menos a diario. No tiene sentido, pero así es como funciona. Si desea leer más sobre este tema tan relevante, le recomiendo el libro de Schneider " La alternativa de reingeniería ". Aquí hay un diagrama de cultura de Michael Sahoto / Agilitrix , basado en el libro de Schneider:
fuente
Por lo que puedo decir, la política oficial del Departamento de Defensa generalmente no prohíbe los lenguajes dinámicos.
Las normas para el software desarrollado o adquirido por el DoD son promulgadas por la Agencia de Sistemas de Información de Defensa (DISA). Su seguridad de las aplicaciones - Seguridad de Aplicaciones y Desarrollo guía de implementación técnica de seguridad (STIG) no prohíbe cualquier idioma en particular. No menciona a Ruby, pero menciona a Perl y Python que son igualmente dinámicos. Los menciona en el contexto de varios temas (siguiendo los estándares de codificación establecidos, evitando vulnerabilidades de inyección de comandos, etc.).
Probablemente lo que está viendo es una herramienta de escaneo demasiado estricta (hay varias diferentes mencionadas en el STIG, cada una puede tener su propia interpretación de las reglas) y / o una interpretación demasiado estricta de su salida.
fuente