Por el momento, hay dos enfoques principales para la b煤squeda de vulnerabilidades en las aplicaciones: an谩lisis est谩tico y din谩mico. Ambos enfoques tienen sus pros y sus contras. El mercado llega a la conclusi贸n de que ambos enfoques deben usarse: resuelven problemas ligeramente diferentes con resultados diferentes. Sin embargo, en algunos casos, el uso del an谩lisis est谩tico es limitado, por ejemplo, cuando no hay c贸digo fuente. En este art铆culo, hablaremos sobre una tecnolog铆a bastante rara pero muy 煤til que le permite combinar las ventajas de los enfoques est谩ticos y din谩micos: el an谩lisis est谩tico del c贸digo ejecutable.
Vamos de lejosSeg煤n la compa帽铆a de antivirus McAfee, el da帽o global provocado por el cibercrimen en 2017 ascendi贸 a alrededor de $ 600 mil millones, lo que equivale al 0,8% del PIB mundial. Vivimos en la era de la tecnolog铆a de la informaci贸n, cuyos detalles espec铆ficos han sido la r谩pida integraci贸n de la red global y las tecnolog铆as de Internet en todas las esferas de la actividad humana. Ahora los delitos cibern茅ticos ya no est谩n fuera de lo com煤n.
Las estad铆sticas muestran un aumento en el cibercrimen exponencialmente.
La vulnerabilidad de las aplicaciones se ha convertido en un problema grave: seg煤n el Departamento de Seguridad Nacional de EE. UU., M谩s del 90% de los ciberataques exitosos se implementan utilizando diversas vulnerabilidades en las aplicaciones. Los m茅todos de explotaci贸n de vulnerabilidades m谩s famosos son:
- Inyecci贸n SQL
- desbordamiento de b煤fer
- secuencias de comandos de crossite
- Usando una configuraci贸n insegura.
El an谩lisis de software (software) para detectar la presencia de capacidades no declaradas (NDV) y vulnerabilidades es la tecnolog铆a principal para garantizar la seguridad de las aplicaciones.
Hablando de tecnolog铆as cl谩sicas y bien establecidas para analizar software en busca de vulnerabilidades y NDV (para el cumplimiento de los requisitos de seguridad de la informaci贸n), podemos distinguir:
- an谩lisis de c贸digo est谩tico (pruebas de seguridad de aplicaciones est谩ticas);
- an谩lisis de c贸digo din谩mico (Dynamic Application Security Testing).
Existe IAST (an谩lisis interactivo), sin embargo, es esencialmente din谩mico (en el proceso de an谩lisis, un agente adicional observa lo que sucede durante la ejecuci贸n de la aplicaci贸n). RASP (Runtime Application Self-Defense), que a veces tambi茅n se menciona en varias herramientas de an谩lisis, es m谩s probable que sea una herramienta de protecci贸n.
El an谩lisis din谩mico (el m茅todo "Black Box") es una verificaci贸n del programa durante su ejecuci贸n. Las siguientes ventajas se pueden distinguir de este enfoque.
- Dado que las vulnerabilidades est谩n en el programa ejecutable y el error se detecta utilizando su operaci贸n, la generaci贸n de falsos positivos es menor que la del an谩lisis est谩tico.
- No se necesita c贸digo fuente para realizar el an谩lisis.
Pero tambi茅n hay desventajas.
- Cobertura incompleta del c贸digo y, por lo tanto, existen riesgos de vulnerabilidades faltantes. Por ejemplo, el an谩lisis din谩mico no puede encontrar vulnerabilidades asociadas con el uso de criptograf铆a d茅bil o marcadores como "bomba temporal".
- La necesidad de ejecutar la aplicaci贸n, que en algunos casos puede ser dif铆cil. El lanzamiento de la aplicaci贸n puede requerir una configuraci贸n compleja y la configuraci贸n de varias integraciones. Adem谩s, para que los resultados sean lo m谩s precisos posible, es necesario reproducir el "entorno de combate", pero es dif铆cil darse cuenta de esto sin da帽ar el software.
El an谩lisis est谩tico (el m茅todo de la "Caja blanca") es un tipo de prueba de programa en el que el programa no se ejecuta.
Enumeramos los beneficios.
- Cobertura completa del c贸digo, lo que lleva a la b煤squeda de m谩s vulnerabilidades.
- Sin dependencia del entorno en el que se ejecutar谩 el programa.
- La capacidad de implementar pruebas en las etapas iniciales de escritura de c贸digo para un m贸dulo o programa en ausencia de archivos ejecutables. Esto le permite integrar de manera flexible una soluci贸n similar en el SDLC (Ciclo de vida de desarrollo de software ciclo de vida de desarrollo de software) al comienzo del desarrollo.
El 煤nico inconveniente del m茅todo es la presencia de falsos positivos: la necesidad de evaluar si el analizador indica un error real o si es probable que este falso positivo.
Como podemos ver, ambos m茅todos de an谩lisis tienen ventajas y desventajas. Sin embargo, 驴es posible de alguna manera utilizar las ventajas de estos m茅todos y minimizar las desventajas? S铆, si aplica el an谩lisis binario: la b煤squeda de vulnerabilidades en archivos ejecutables mediante an谩lisis est谩tico.
An谩lisis binario o tecnolog铆a de an谩lisis de archivos ejecutables
El an谩lisis binario permite el an谩lisis est谩tico sin c贸digo fuente, por ejemplo, en el caso de contratistas externos. Adem谩s, la cobertura del c贸digo ser谩 completa, en contraste con la aplicaci贸n del m茅todo de an谩lisis din谩mico. Mediante el an谩lisis binario, puede verificar las bibliotecas de terceros utilizadas en el proceso de desarrollo para las que no hay c贸digo fuente. Adem谩s, mediante el an谩lisis binario, puede realizar una verificaci贸n de control de la versi贸n, comparando los resultados del an谩lisis del c贸digo fuente del repositorio y el c贸digo ejecutable del servidor de combate.
En el proceso de an谩lisis binario, la imagen binaria se transforma en una representaci贸n intermedia (representaci贸n interna o modelo de c贸digo) para su posterior an谩lisis. Despu茅s de eso, los algoritmos de an谩lisis est谩tico se aplican a la representaci贸n interna. Como resultado, el modelo actual se complementa con la informaci贸n necesaria para la detecci贸n adicional de vulnerabilidades y NDV. En la siguiente etapa, la aplicaci贸n de las reglas para buscar vulnerabilidades y NDV.
Escribimos m谩s sobre el esquema de an谩lisis est谩tico
en un art铆culo anterior . A diferencia del an谩lisis de c贸digo fuente, que utiliza elementos de teor铆a de compilaci贸n (an谩lisis l茅xico, sint谩ctico) para construir el modelo, el an谩lisis binario utiliza la teor铆a de traducci贸n inversa para desmontar, descompilar y desofuscar el modelo.
Un poco sobre los t茅rminos
Estamos hablando de analizar archivos ejecutables que no tienen informaci贸n de depuraci贸n. Con la informaci贸n de depuraci贸n, la tarea se simplifica enormemente, pero si hay informaci贸n de depuraci贸n, lo m谩s probable es que el c贸digo fuente sea irrelevante.
En este art铆culo, llamamos al an谩lisis de bytecode de Java tambi茅n an谩lisis binario, aunque esto no es del todo correcto. Hacemos esto para simplificar el texto. Por supuesto, la tarea de analizar el bytecode JVM es m谩s simple que analizar el c贸digo binario C / C ++ y Objective-C / Swift. Pero el esquema de an谩lisis general es similar en el caso de bytecode y c贸digo binario. Las principales dificultades descritas en el art铆culo se relacionan espec铆ficamente con el an谩lisis del c贸digo binario.
La descompilaci贸n es el proceso de recuperaci贸n del c贸digo fuente del c贸digo binario. Puede hablar sobre los elementos de la traducci贸n inversa: desmontaje (obtenci贸n del c贸digo del ensamblador a partir de una imagen binaria), traducci贸n del ensamblador a un c贸digo de tres direcciones u otra representaci贸n, restauraci贸n de las construcciones del nivel del c贸digo fuente.
Ofuscaci贸n: transformaciones que preservan la funcionalidad del c贸digo fuente, pero dificultan la descompilaci贸n y la comprensi贸n de la imagen binaria resultante. La desofuscaci贸n es la transformaci贸n inversa. La ofuscaci贸n se puede aplicar tanto a nivel de c贸digo fuente como a nivel de c贸digo binario.
驴C贸mo ver los resultados?
Comencemos un poco desde el final, pero la cuesti贸n de ver los resultados del an谩lisis binario generalmente se hace primero.
Es importante que un especialista analice el c贸digo binario para asignar vulnerabilidades y NDV al c贸digo fuente. Para hacer esto, en la etapa final, el proceso de desofuscaci贸n (desentra帽amiento) se inicia si se aplicaron conversiones confusas, y el c贸digo binario se descompil贸 en la fuente. Es decir, las vulnerabilidades se pueden demostrar en el c贸digo descompilado.
En el proceso de descompilaci贸n, incluso si descompilamos el bytecode de JVM, parte de la informaci贸n no se restaura correctamente, por lo que el an谩lisis en s铆 tiene lugar en una representaci贸n cercana al c贸digo binario. En consecuencia, surge la pregunta: 驴c贸mo, al encontrar vulnerabilidades en el c贸digo binario, localizarlas en la fuente? La soluci贸n al problema para el c贸digo de bytes JVM se describi贸
en nuestro art铆culo sobre la b煤squeda de vulnerabilidades en el c贸digo de bytes Java . La soluci贸n para el c贸digo binario es similar, es decir, una pregunta t茅cnica.
Repitamos la advertencia importante: estamos hablando del an谩lisis de c贸digo binario sin informaci贸n de depuraci贸n. En presencia de informaci贸n de depuraci贸n, la tarea se simplifica enormemente.
La pregunta principal que se nos hace para mostrar los resultados es si el c贸digo descompilado es suficiente para comprender y localizar la vulnerabilidad.
A continuaci贸n se presentan algunos pensamientos sobre este tema.
- Si estamos hablando del c贸digo de bytes JVM, entonces en general la respuesta es "s铆": la calidad de descompilaci贸n del c贸digo de bytes es excelente. Casi siempre puedes descubrir cu谩l es la vulnerabilidad.
- Lo que puede interferir con la localizaci贸n cualitativa de la vulnerabilidad es una simple ofuscaci贸n, como renombrar nombres de clase y funciones. Sin embargo, en la pr谩ctica a menudo resulta que es m谩s importante comprender la vulnerabilidad que determinar en qu茅 archivo se encuentra. La localizaci贸n es necesaria cuando alguien puede corregir la vulnerabilidad, pero en este caso, el desarrollador tambi茅n comprender谩 de d贸nde proviene la vulnerabilidad del c贸digo descompilado.
- Cuando hablamos del an谩lisis del c贸digo binario (por ejemplo, C ++), por supuesto, todo es mucho m谩s complicado. No hay ninguna herramienta que recupere completamente el c贸digo aleatorio de C ++. Sin embargo, la peculiaridad de nuestro caso es que no necesitamos compilar el c贸digo m谩s tarde: necesitamos calidad suficiente para comprender la vulnerabilidad.
- Muy a menudo, puede lograr una calidad de descompilaci贸n suficiente para comprender la vulnerabilidad encontrada. Para hacer esto, debe resolver muchos problemas complejos, pero puede resolverlos (a continuaci贸n, hablaremos brevemente al respecto).
- Para C / C ++, es a煤n m谩s dif铆cil localizar la vulnerabilidad: los nombres de los caracteres se pierden de muchas maneras durante el proceso de compilaci贸n, no puede restaurarlos.
- La situaci贸n en Objective-C es ligeramente mejor: hay nombres de funciones all铆 y es m谩s f谩cil localizar la vulnerabilidad.
- Los problemas de ofuscaci贸n se distinguen. Hay una serie de transformaciones complejas que pueden complicar la descompilaci贸n y el mapeo de vulnerabilidades. En la pr谩ctica, resulta que un buen descompilador puede manejar la mayor铆a de las conversiones confusas (recuerde que necesitamos suficiente calidad de c贸digo para comprender la vulnerabilidad).
Como conclusi贸n, la mayor铆a de las veces muestra la vulnerabilidad para que se pueda entender y verificar.
Complejidades y detalles del an谩lisis binario.
Aqu铆 no hablaremos sobre el bytecode: todas las cosas interesantes sobre 茅l ya se han dicho anteriormente. Lo m谩s interesante es el an谩lisis del c贸digo binario real. Aqu铆 hablaremos sobre el an谩lisis de C / C ++, Objective-C y Swift como ejemplo.
Surgen dificultades significativas incluso cuando se desmonta. La etapa m谩s importante es la divisi贸n de la imagen binaria en subprogramas. Luego, seleccione las instrucciones del ensamblador en las subrutinas, una cuesti贸n t茅cnica. Escribimos sobre esto
en detalle
en un art铆culo para la revista "Issues of Cybersecurity No. 1 (14) - 2016" , aqu铆 describiremos brevemente.
Como ejemplo, hablaremos de la arquitectura x86. Las instrucciones que contiene no tienen una longitud fija. En las im谩genes binarias, no hay una divisi贸n clara en secciones de c贸digo y datos: las tablas de importaci贸n, las tablas de funciones virtuales pueden estar en la secci贸n de c贸digos, las tablas de transici贸n pueden estar en los intervalos entre los bloques de funciones base en la secci贸n de c贸digos. En consecuencia, debe poder separar el c贸digo de los datos y comprender d贸nde comienzan y d贸nde terminan las rutinas.
Los m谩s comunes son dos m茅todos para resolver el problema de determinar las direcciones iniciales de los subprogramas. En el primer m茅todo, las direcciones de los subprogramas est谩n determinadas por el pr贸logo est谩ndar (para la arquitectura x86 es push ebp; mov ebp, esp). En el segundo m茅todo, una secci贸n de c贸digo se atraviesa recursivamente desde el punto de entrada con reconocimiento de instrucciones de llamada de subrutina. La anulaci贸n se realiza reconociendo las instrucciones de ramificaci贸n. Las combinaciones de los m茅todos descritos tambi茅n se utilizan cuando se inicia un recorrido recursivo desde las direcciones de inicio encontradas por el pr贸logo.
En la pr谩ctica, resulta que tales enfoques dan un porcentaje bastante bajo de c贸digo reconocido, ya que no todas las funciones tienen un pr贸logo est谩ndar, y hay llamadas y transiciones indirectas.
Los algoritmos b谩sicos se pueden mejorar mediante las siguientes heur铆sticas.
- En una gran base de prueba de im谩genes, encuentre una lista m谩s precisa de los pr贸logos (nuevos pr贸logos o variaciones de los est谩ndares).
- Puede buscar autom谩ticamente tablas de funciones virtuales y, a partir de ellas, seleccionar las direcciones iniciales de los subprogramas.
- Las direcciones iniciales de subprogramas y algunas otras construcciones se pueden encontrar en base a secciones de c贸digo binario asociadas con el mecanismo de manejo de excepciones.
- Puede verificar las direcciones de inicio buscando estas direcciones en la imagen y reconociendo las instrucciones de llamada.
- Para buscar l铆mites, puede hacer un recorrido recursivo de la subrutina con el reconocimiento de las instrucciones de la direcci贸n de inicio. Hay una dificultad con las transiciones indirectas y las funciones sin retorno. El an谩lisis de la tabla de importaci贸n y el reconocimiento de construcciones de conmutadores pueden ayudar.
Otra cosa importante que debe hacerse durante la traducci贸n inversa, para buscar normalmente una vulnerabilidad m谩s adelante, es reconocer las funciones est谩ndar en una imagen binaria. Las funciones est谩ndar pueden estar vinculadas est谩ticamente a la imagen, o incluso pueden estar en l铆nea. El algoritmo de reconocimiento principal es una b煤squeda por firma con variaciones; para la soluci贸n, puede ofrecer el algoritmo Aho-Korasik adaptado. Para recopilar firmas, debe analizar previamente las im谩genes de la biblioteca recopiladas con diferentes condiciones y seleccionarlas como bytes que no cambian.
Que sigue
En la secci贸n anterior, examinamos la etapa inicial de la traducci贸n inversa de una imagen binaria: el desmontaje. La etapa, de hecho, es inicial, pero determinante. En esta etapa, puede perder parte del c贸digo, lo que tendr谩 un efecto dram谩tico en los resultados del an谩lisis.
Entonces suceden muchas cosas interesantes. Diga brevemente sobre las tareas principales. No hablaremos en detalle: ya sea el conocimiento, sobre el cual no podemos escribir expl铆citamente aqu铆, o no hay soluciones t茅cnicas y de ingenier铆a muy interesantes en los detalles.
- Convertir el c贸digo de ensamblaje en una representaci贸n intermedia en la que se puede realizar el an谩lisis. Puede usar varios bytecodes. Para los lenguajes C, LLVM parece ser una buena opci贸n. LLVM es activamente apoyado y desarrollado por la comunidad, la infraestructura, incluso 煤til para el an谩lisis est谩tico, es actualmente impresionante. En esta etapa, hay una gran cantidad de detalles a los que debe prestar atenci贸n. Por ejemplo, debe detectar qu茅 variables se abordan en la pila para no multiplicar entidades en la vista resultante. Debe configurar la visualizaci贸n 贸ptima de los conjuntos de instrucciones de ensamblador en las instrucciones de bytecode.
- Restaurar estructuras de alto nivel (por ejemplo, bucles, ramas). Cuanto m谩s exactamente sea posible restaurar las construcciones originales del c贸digo del ensamblador, mejor ser谩 la calidad del an谩lisis. La restauraci贸n de tales construcciones se lleva a cabo utilizando elementos de la teor铆a de grafos en CFG (control de flujo) y algunas otras representaciones gr谩ficas del programa.
- Realizaci贸n de algoritmos de an谩lisis est谩tico. Hay detalles. En general, no es muy importante si obtuvimos la representaci贸n interna de la fuente o del binario: todos tambi茅n necesitamos construir CFG, aplicar algoritmos de an谩lisis de flujo de datos y otros algoritmos t铆picos de la est谩tica. Existen algunas caracter铆sticas al analizar la vista obtenida del binario, pero son m谩s t茅cnicas.
Conclusiones
Hablamos sobre c贸mo hacer an谩lisis est谩ticos cuando no hay c贸digo fuente. Seg煤n la experiencia de comunicaci贸n con los clientes, resulta que la tecnolog铆a es muy demandada. Sin embargo, la tecnolog铆a es rara: el problema del an谩lisis binario no es trivial, su soluci贸n requiere algoritmos complejos de alta tecnolog铆a de an谩lisis est谩tico y traducci贸n inversa.
Este art铆culo fue escrito en colaboraci贸n con Anton Prokofiev, analista de Solar appScreener