Saltar al contenido

¿Por qué la ofuscación del sistema operativo se defiende contra “Es un sistema Unix”? ¿No se ha implementado ampliamente?

Solución:

Antes de desarmar tu idea, déjame decirte que es una idea realmente interesante y fue muy divertido pensar en ella.

¡Continúe pensando fuera de la caja y haga preguntas interesantes!

Muy bien, ¡hagamos esto!


Demos un paso atrás y preguntemos por qué ese vigilabebés está ejecutando Linux en primer lugar. ¿Qué pasaría si no hubiera un sistema operativo y la aplicación estuviera escrita en un código de microcontrolador desnudo (piense en el código arduino)? Entonces no habra sudo o ls o incluso un caparazón para que lo use el atacante, ¿verdad?

No soy un experto aquí, pero espero que nosotros, como industria, hayamos gravitado hacia la instalación de Linux en algo lo suficientemente grande como para ejecutarlo en gran medida para la conveniencia de los desarrolladores:

  1. Reducción del tiempo de desarrollo: al construir su genio de auto-parcheo de sincronización en la nube administrado por Internet y compatible con WiFi y bluetooth con aplicaciones complementarias de Android e iOS, Linux viene con todas las bibliotecas, utilidades y controladores que necesita para hacer eso.
  2. Mayor capacidad de prueba: si el dispositivo está ejecutando bash o busybox con un puerto SSH, entonces es muy fácil conectarse y averiguar qué salió mal durante la fase de prueba del producto.

Para que su idea de ofuscación funcione, necesitaría ofuscar no solo los nombres de las utilidades de línea de comandos como sudo y ls, pero también todas las API del kernel de Linux para evitar que el atacante suelte su propio binario compilado que llama al kernel directamente. Así que echemos otro vistazo a tu idea:

La implementación sería bastante fácil para los compiladores. Tome el caso más simple de “cambiar el nombre de esta función y todas las llamadas a ella”. Podría darle a un compilador de sistema operativo y a un compilador de aplicaciones los mismos nombres aleatorios y podrían comunicarse entre sí.

Deberá realizar esta compilación aleatoria usted mismo; de lo contrario, alguien podría buscar las asignaciones en Google.

Por lo tanto, deberá compilar el kernel desde el código fuente con su “compilador de ofuscación” para que solo usted conozca las asignaciones de las API de kernel ofuscadas. (¿Alguna vez construiste el kernel de Linux desde la fuente? Ciertamente es más una tarea que docker pull alpine, que es la dirección en la que parece ir la cultura de desarrollo).

Pero un sistema operativo es más que un núcleo. ¿Quiere controladores para el chip wifi Broadcom BCM2837 que viene en ese dispositivo mini-pc? Necesitará compilar ese controlador contra su kernel ofuscado con su compilador, si Broadcom le da el código fuente. Luego, deberá construir todas las pilas de software de red y wifi de GNU. ¿Cuántas otras cosas necesitará encontrar la fuente y agregar a su canal de compilación antes de tener un sistema operativo en funcionamiento?

Ah, y si los repositorios ascendentes de cualquiera de esas cosas emiten un parche, ahora eres responsable de reconstruirlo. (asumiendo que guardó los archivos de mapeo de ofuscación del compilador que coinciden con el binario de su kernel) y enviarlo a sus dispositivos porque, por diseño, sus dispositivos no pueden usar parches binarios producidos por el proveedor.

Ah, y para frustrar a los piratas informáticos, no habrá nada de esto “Aquí están los archivos binarios de Whizpopper 1.4.7”, oh no, necesitará crear una versión ofuscada de forma única de todo, desde el kernel hasta por dispositivo que envías.


Entonces a tus preguntas:

  1. ¿La ofuscación del sistema operativo como se describe se usa ampliamente y simplemente no la he encontrado?
  2. Si no se usa ampliamente, ¿cuáles son las barreras prácticas o técnicas para su uso?

Creo que la respuesta es que lo que estás describiendo frustra por completo el propósito de usar componentes de software preexistentes si necesitas encontrar y construir literalmente todo desde la fuente. En realidad, podría ser menos esfuerzo deshacerse del sistema operativo por completo, fingir que es 1960 y escribir su aplicación directamente en el microcódigo de la CPU.

Me gusta la seguridad más que a la mayoría de los desarrolladores, pero me gusta que se joda.

La respuesta de Mike dice básicamente todo lo que tengo que ofrecer sobre por qué esto es una mala idea desde una perspectiva de desarrollo (y, como dice el comentario de Ghedipunk, una característica de seguridad inutilizable no proporciona seguridad). Entonces, en cambio, voy a hablar sobre por qué desde una perspectiva de seguridad, nunca harías esto.

La respuesta es sorprendentemente simple: es una pérdida de tiempo y existen opciones estrictamente mejores. Cada estúpido doodad de IoT (recuerde, la “s” en “IoT” significa Seguro) que no se molesta en implementar tales características seguro que no iría con un enfoque como usted sugiere.

  1. La idea completa simplemente no funcionará para restringir las llamadas al sistema. Un atacante puede simplemente establecer algunos registros e invocar un código de operación y boom, están en el kernel ejecutando la llamada al sistema de su elección; ¿A quién le importa cuál es su nombre simbólico? Claro, puede manipular la tabla syscall para complicar esto (si no le importa tener que recompilar todo y hacer que la depuración de su kernel personalizado sea una forma de infierno) pero es como ofuscar el sistema operativo en uso; ¿Por qué molestarse cuando hay tan pocos candidatos? Incluso si el atacante no quiere aplicar ingeniería inversa al código existente en el sistema, la fuerza bruta debería ser posible a menos que el espacio de búsqueda de índices de llamadas utilizables sea más amplio de lo que he visto en un sistema integrado.
  2. ¿Por qué ofuscar los nombres de los comandos cuando puede hacerlos completamente inaccesibles? A chroot no funcionará para elementos integrados de shell si estás ejecutando un caparazón, pero funciona bien para todo lo demás y, en realidad, ¿por qué su aplicación en una caja de uso único y personalizada estaría ejecutando un shell? Quiero decir, las unidades de desarrollo tendrían una instalada, con fines de prueba, y tal vez eso no se elimine en su imagen minorista porque es vago o cree que lo necesitará nuevamente. Pero un atacante no podría ejecutarlo desde el contexto en el que se ejecuta su aplicación. Un simple chroot (o una caja de arena / cárcel / contenedor más complicada) puede hacer que el programa no pueda ejecutar, o incluso acceder, a cualquier archivo más allá de los necesarios para su trabajo.
  3. ¿Por qué ofuscar las API del kernel cuando simplemente puede eliminar el acceso a ellas? Hay una serie de sistemas de espacio aislado que pueden restringir las llamadas que puede realizar un proceso (o sus descendientes … si incluso se le permite crear alguno). Consulte https://stackoverflow.com/questions/2146059/limiting-syscall-access-for-a-linux-application

Si su objetivo es privar a un atacante de ls y cat, hay una alternativa aún mejor a la ofuscación: simplemente no instale esas utilidades.

Si bien no diría que esto es un ampliamente implementar enfoque, es al menos implementar. Por ejemplo, considere distroless, una colección de imágenes de la ventana acoplable con prácticamente nada en ellas. Algunos de ellos (como el de ir) literalmente tienen nada en ellos. Un ataque a un sistema que se ejecuta en un contenedor de este tipo no puede obtener acceso al shell porque no hay ningún shell para ejecutar.

Entonces, la única forma de obtener acceso al shell atacando una aplicación en dicho contenedor es eludir el tiempo de ejecución del contenedor, que está diseñado para evitar precisamente eso.

Si bien di un ejemplo de una imagen de la ventana acoplable, el mismo concepto se puede aplicar a los sistemas operativos en general. Por ejemplo, ls y cat son parte del coreutils paquete en Debian. Podrías correr apt-get remove coreutils y confíe en que un atacante no podrá utilizar ls o cat como parte de un ataque. Por supuesto, esto significa que tampoco puede usarlos, y probablemente hay muchas otras cosas que dependen de coreutils eso también tendrá que eliminarse, pero para un dispositivo integrado o un servidor que hace solo una cosa que puede estar bien.

El principio general es reducir la “superficie de ataque”: cuanto más “cosas” tiene un objetivo, más fácil es comprometerse. Las cosas podrían ser puertos de red abiertos, líneas de código o binarios instalados. Si el objetivo es aumentar la seguridad, entonces eliminar todas las “cosas” innecesarias es un buen comienzo.

Si haces scroll puedes encontrar las reseñas de otros programadores, tú de igual manera tienes el poder dejar el tuyo si lo deseas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *