stringtranslate.com

código shell

En hacking , un shellcode es un pequeño fragmento de código que se utiliza como carga útil en la explotación de una vulnerabilidad de software . Se llama "shellcode" porque normalmente inicia un shell de comandos desde el cual el atacante puede controlar la máquina comprometida, pero cualquier fragmento de código que realice una tarea similar puede denominarse shellcode. Debido a que la función de una carga útil no se limita simplemente a generar un shell, algunos han sugerido que el nombre shellcode es insuficiente. [1] Sin embargo, los intentos de reemplazar el término no han obtenido una amplia aceptación. Shellcode se escribe comúnmente en código de máquina .

Al crear shellcode, generalmente es deseable hacerlo pequeño y ejecutable, lo que permite utilizarlo en la mayor variedad de situaciones posible. [2] Escribir un buen código shell puede ser tanto un arte como una ciencia. [3] En código ensamblador, la misma función se puede realizar de multitud de formas y existe cierta variedad en la longitud de los códigos de operación que se pueden utilizar para este propósito; Los buenos escritores de shellcode pueden utilizar estos pequeños códigos de operación para crear un shellcode más compacto. [4] Algunos han alcanzado el tamaño más pequeño posible manteniendo la estabilidad. [5]

Tipos de código shell

Shellcode puede ser local o remoto , dependiendo de si le da al atacante control sobre la máquina en la que se ejecuta (local) o sobre otra máquina a través de una red (remota).

Local

Un atacante que tiene acceso limitado a una máquina utiliza el shellcode local , pero puede aprovechar una vulnerabilidad, por ejemplo un desbordamiento del búfer , en un proceso con mayores privilegios en esa máquina. Si se ejecuta con éxito, el shellcode proporcionará al atacante acceso a la máquina con los mismos privilegios superiores que el proceso objetivo.

Remoto

El shellcode remoto se utiliza cuando un atacante quiere apuntar a un proceso vulnerable que se ejecuta en otra máquina en una red local , intranet o red remota . Si se ejecuta con éxito, el código shell puede proporcionar al atacante acceso a la máquina objetivo a través de la red. Los shellcodes remotos normalmente utilizan conexiones de socket TCP/IP estándar para permitir que el atacante acceda al shell en la máquina de destino. Dicho shellcode se puede clasificar en función de cómo se configura esta conexión: si el shellcode establece la conexión, se denomina "shell inverso" o shellcode de conexión porque el shellcode se conecta nuevamente a la máquina del atacante. Por otro lado, si el atacante establece la conexión, el código shell se llama bindshell porque el código shell se vincula a un determinado puerto en la máquina de la víctima. Hay un código shell peculiar llamado puerto aleatorio bindshell que omite la parte vinculante y escucha en un puerto aleatorio puesto a disposición por el sistema operativo . Debido a esto, el puerto aleatorio de bindshell se convirtió en el código de shell de bindshell estable más pequeño para x86_64 disponible hasta la fecha. Un tercer tipo, mucho menos común, es el código shell de reutilización de sockets . Este tipo de shellcode se utiliza a veces cuando un exploit establece una conexión con el proceso vulnerable que no se cierra antes de ejecutar el shellcode. Luego, el código shell puede reutilizar esta conexión para comunicarse con el atacante. La reutilización del código shell por socket es más elaborada, ya que el código shell necesita descubrir qué conexión reutilizar y la máquina puede tener muchas conexiones abiertas. [6]

Se puede utilizar un firewall para detectar conexiones salientes realizadas mediante shellcode de conexión, así como conexiones entrantes realizadas mediante bindshells. Por lo tanto, pueden ofrecer cierta protección contra un atacante, incluso si el sistema es vulnerable, al impedir que el atacante se conecte al shell creado por el código shell. Una de las razones por las que a veces se utiliza el código shell de reutilización de sockets es que no crea nuevas conexiones y, por lo tanto, es más difícil de detectar y bloquear.

Descargar y ejecutar

Descargar y ejecutar es un tipo de código shell remoto que descarga y ejecuta algún tipo de malware en el sistema de destino. Este tipo de código shell no genera un shell, sino que indica a la máquina que descargue un determinado archivo ejecutable de la red, lo guarde en el disco y lo ejecute. Hoy en día, se usa comúnmente en ataques de descarga no autorizada , donde una víctima visita una página web maliciosa que a su vez intenta ejecutar dicha descarga y ejecutar shellcode para instalar software en la máquina de la víctima. Una variación de este tipo de shellcode descarga y carga una biblioteca . [7] [8] Las ventajas de esta técnica son que el código puede ser más pequeño, que no requiere que el shellcode genere un nuevo proceso en el sistema de destino y que el shellcode no necesita código para limpiar el proceso de destino como esto lo puede hacer la biblioteca cargada en el proceso.

Escenificado

Cuando la cantidad de datos que un atacante puede inyectar en el proceso de destino es demasiado limitada para ejecutar un código shell útil directamente, es posible ejecutarlo por etapas. Primero, se ejecuta una pequeña parte del código shell (etapa 1). Luego, este código descarga una pieza más grande de código shell (etapa 2) en la memoria del proceso y lo ejecuta.

Búsqueda de huevos

Esta es otra forma de código shell preparado , que se utiliza si un atacante puede inyectar un código shell más grande en el proceso pero no puede determinar en qué parte del proceso terminará. Se inyecta un pequeño código de cáscara de búsqueda de huevos en el proceso en una ubicación predecible y se ejecuta. Luego, este código busca en el espacio de direcciones del proceso el código de cáscara más grande (el huevo ) y lo ejecuta. [9]

Tortilla

Este tipo de código de cáscara es similar al código de cáscara de búsqueda de huevos , pero busca múltiples bloques pequeños de datos ( huevos ) y los recombina en un bloque más grande (la tortilla ) que se ejecuta posteriormente. Esto se utiliza cuando un atacante solo puede inyectar una cantidad de pequeños bloques de datos en el proceso. [10]

Estrategia de ejecución de Shellcode

Un exploit comúnmente inyectará un código shell en el proceso de destino antes o al mismo tiempo que explota una vulnerabilidad para obtener control sobre el contador del programa . El contador del programa se ajusta para que apunte al código shell, después de lo cual se ejecuta y realiza su tarea. La inyección del código shell a menudo se realiza almacenándolo en datos enviados a través de la red al proceso vulnerable, proporcionándolo en un archivo que es leído por el proceso vulnerable o a través de la línea de comando o el entorno en el caso de exploits locales.

Codificación de código shell

Debido a que la mayoría de los procesos filtran o restringen los datos que se pueden inyectar, a menudo es necesario escribir shellcode para permitir estas restricciones. Esto incluye hacer que el código sea pequeño, libre de nulos o alfanumérico . Se han encontrado varias soluciones para sortear dichas restricciones, entre ellas:

Dado que la detección de intrusiones puede detectar firmas de códigos shell simples que se envían a través de la red, a menudo se codifica, se autodescifra o es polimórfica para evitar la detección.

Codificación porcentual

Los exploits que se dirigen a los navegadores comúnmente codifican shellcode en una cadena JavaScript usando codificación porcentual , codificación de secuencia de escape " \uXXXX " o codificación de entidad . [11] Algunos exploits también ofuscan aún más la cadena codificada del código shell para evitar la detección por parte de IDS .

Por ejemplo, en la arquitectura IA-32 , así es como NOPse verían dos instrucciones (sin operación), primero sin codificar:

90 NOP90 NOP

Esta instrucción se utiliza en diapositivas NOP .

Código shell libre de nulos

La mayoría de los shellcodes se escriben sin el uso de bytes nulos porque están destinados a ser inyectados en un proceso de destino a través de cadenas terminadas en nulo . Cuando se copia una cadena terminada en nulo, se copiará hasta el primer nulo inclusive, pero los bytes posteriores del shellcode no se procesarán. Cuando se inyecta de esta manera un código shell que contiene valores nulos, solo se inyecta una parte del código shell, lo que impide que se ejecute correctamente.

Para producir un código shell libre de nulos a partir de un código shell que contiene bytes nulos , se pueden sustituir las instrucciones de máquina que contienen ceros por instrucciones que tengan el mismo efecto pero que estén libres de nulos. Por ejemplo, en la arquitectura IA-32 se podría reemplazar esta instrucción:

B8 01000000 MOV EAX,1 // Establece el registro EAX en 0x00000001

que contiene ceros como parte del literal ( 1se expande a 0x00000001) con estas instrucciones:

33C0 XOR EAX,EAX // Establece el registro EAX en 0x0000000040 INC EAX // Aumentar EAX a 0x00000001

que tienen el mismo efecto pero requieren menos bytes para codificar y están libres de valores nulos.

Shellcode alfanumérico e imprimible

Un código shell alfanumérico es un código shell que consta de caracteres ASCII o Unicode completamente alfanuméricos , como del 0 al 9, AZ y az, o se ensambla a sí mismo durante la ejecución. [12] [13] Este tipo de codificación fue creado por piratas informáticos para ocultar el código de máquina funcional dentro de lo que parece ser texto. Esto puede ser útil para evitar la detección del código y permitir que el código pase a través de filtros que eliminan caracteres no alfanuméricos de las cadenas (en parte, dichos filtros fueron una respuesta a exploits de shellcode no alfanuméricos). Un tipo similar de codificación se llama código imprimible y utiliza todos los caracteres imprimibles (0-9, AZ, az, !@#%^&*(), etc.). Una variante igualmente restringida es el código ECHOable que no contiene ningún carácter que no sea aceptado por el comando ECHO . Se ha demostrado que es posible crear un código shell que parezca texto normal en inglés. [14] Escribir código alfanumérico o imprimible requiere una buena comprensión de la arquitectura del conjunto de instrucciones de las máquinas en las que se ejecutará el código. Se ha demostrado que es posible escribir código alfanumérico que sea ejecutable en más de una máquina, [15] constituyendo así código ejecutable de arquitectura múltiple .

En determinadas circunstancias, un proceso de destino filtrará cualquier byte del código shell inyectado que no sea un carácter alfanumérico o imprimible . En tales circunstancias, la gama de instrucciones que se pueden utilizar para escribir un código shell se vuelve muy limitada. Rix publicó una solución a este problema en Phrack 57 [12] en la que demostró que era posible convertir cualquier código en código alfanumérico. Una técnica que se utiliza a menudo es crear código automodificable, porque esto permite que el código modifique sus propios bytes para incluir bytes fuera del rango normalmente permitido, ampliando así el rango de instrucciones que puede usar. Con este truco, se puede crear un decodificador automodificable que inicialmente utilice solo bytes en el rango permitido. El código principal del shellcode está codificado y también utiliza solo bytes en el rango permitido. Cuando se ejecuta el código shell de salida, el decodificador puede modificar su propio código para poder utilizar cualquier instrucción que necesite para funcionar correctamente y luego continúa decodificando el código shell original. Después de decodificar el código shell, el decodificador le transfiere el control, por lo que puede ejecutarse normalmente. Se ha demostrado que es posible crear un código shell arbitrariamente complejo que parece texto normal en inglés. [14]

Código shell a prueba de Unicode

Los programas modernos utilizan cadenas Unicode para permitir la internacionalización del texto. A menudo, estos programas convertirán cadenas ASCII entrantes a Unicode antes de procesarlas. Las cadenas Unicode codificadas en UTF-16 utilizan dos bytes para codificar cada carácter (o cuatro bytes para algunos caracteres especiales). Cuando una cadena ASCII ( Latin-1 en general) se transforma en UTF-16, se inserta un byte cero después de cada byte en la cadena original. Obscou demostró en Phrack 61 [13] que es posible escribir código shell que pueda ejecutarse exitosamente después de esta transformación. Existen programas que pueden codificar automáticamente cualquier código shell en código shell alfanumérico a prueba de UTF-16, basados ​​en el mismo principio de un pequeño decodificador automodificable que decodifica el código shell original.

Plataformas

La mayor parte del shellcode está escrito en código de máquina debido al bajo nivel en el que la vulnerabilidad que se explota le da al atacante acceso al proceso. Por lo tanto, Shellcode a menudo se crea para apuntar a una combinación específica de procesador , sistema operativo y paquete de servicios , llamada plataforma . Para algunos exploits, debido a las restricciones impuestas al shellcode por el proceso de destino, se debe crear un shellcode muy específico. Sin embargo, no es imposible que un código shell funcione para múltiples exploits, service packs, sistemas operativos e incluso procesadores. [16] [17] [18] Esta versatilidad se logra comúnmente creando múltiples versiones del código shell que apuntan a las distintas plataformas y creando un encabezado que se bifurca a la versión correcta para la plataforma en la que se ejecuta el código. Cuando se ejecuta, el código se comporta de manera diferente para diferentes plataformas y ejecuta la parte correcta del código shell para la plataforma en la que se ejecuta.

Análisis de código shell

Shellcode no se puede ejecutar directamente. Para analizar lo que intenta hacer un shellcode, se debe cargar en otro proceso. Una técnica de análisis común es escribir un pequeño programa en C que contenga el código de shell como un búfer de bytes y luego usar un puntero de función o usar un ensamblador en línea para transferirle la ejecución. Otra técnica es utilizar una herramienta en línea, como shellcode_2_exe, para incrustar el código shell en una cáscara ejecutable prefabricada que luego puede analizarse en un depurador estándar. También existen herramientas especializadas de análisis de shellcode, como el proyecto iDefense sclog que se lanzó originalmente en 2005 como parte del Malcode Analyst Pack. Sclog está diseñado para cargar archivos shellcode externos y ejecutarlos dentro de un marco de registro API. También existen herramientas de análisis de shellcode basadas en emulación, como la aplicación sctest que forma parte del paquete libemu multiplataforma. Otra herramienta de análisis de shellcode basada en emulación, construida alrededor de la biblioteca libemu, es scdbg, que incluye un shell de depuración básico y funciones de generación de informes integradas.

Ver también

Referencias

  1. ^ Fomentar, James C.; Precio, Mike (12 de abril de 2005). Sockets, Shellcode, portabilidad y codificación: exploits de ingeniería inversa y codificación de herramientas para profesionales de la seguridad. Libros de ciencia y tecnología de Elsevier. ISBN 1-59749-005-9.
  2. ^ Anley, Chris; Koziol, Jack (2007). El manual del shellcoder: descubrimiento y explotación de agujeros de seguridad (2 ed.). Indianápolis, Indiana, UA: Wiley. ISBN 978-0-470-19882-7. OCLC  173682537.
  3. ^ Gupta, Sunil (2019), "Ataque de desbordamiento de búfer", Hacking ético: orquestación de ataques , Berkeley, California, EE. UU.: Apress, doi :10.1007/978-1-4842-4340-4_12, ISBN 978-1-4842-4340-4, S2CID  235938447
  4. ^ Foster, James C. (2005). Ataques de desbordamiento de búfer: detectar, explotar, prevenir . Rockland, MA, EE.UU.: Syngress. ISBN 1-59749-022-9. OCLC  57566682.
  5. ^ "Tiny Execve sh - Lenguaje ensamblador - Linux/x86". GitHub . Consultado el 1 de febrero de 2021 .
  6. ^ BHA (6 de junio de 2013). "Shellcode/Reutilización de sockets" . Consultado el 7 de junio de 2013 .
  7. ^ SkyLined (11 de enero de 2010). "Descargar y cargar el código shell de Biblioteca publicado". Archivado desde el original el 23 de enero de 2010 . Consultado el 19 de enero de 2010 .
  8. ^ "Descargar y cargar el código shell de Biblioteca para Windows x86". 2010-01-11 . Consultado el 19 de enero de 2010 .
  9. ^ Skape (9 de marzo de 2004). "Proceso de búsqueda segura en el espacio de direcciones virtuales" (PDF) . no iniciar sesión . Consultado el 19 de marzo de 2009 .
  10. ^ SkyLined (16 de marzo de 2009). "Código de cáscara de tortilla w32 SEH". Skypher.com. Archivado desde el original el 23 de marzo de 2009 . Consultado el 19 de marzo de 2009 .
  11. ^ "Se detectó una gran cantidad de patrones sin escape en JavaScript". Archivado desde el original el 3 de abril de 2015.
  12. ^ abreviatura (11 de agosto de 2001). "Escribir códigos shell alfanuméricos ia32". Phrack . Phrack Inc. 0x0b (57). #0x0f de 0x12. Archivado desde el original el 8 de marzo de 2022 . Consultado el 26 de mayo de 2022 .
  13. ^ ab obscou (13 de agosto de 2003). "Construcción de códigos Shell IA32 'a prueba de Unicode'". Phrack . Phrack Inc. 11 (61). #0x0b de 0x0f. Archivado desde el original el 26 de mayo de 2022 . Consultado el 29 de febrero de 2008 .
  14. ^ ab Mason, Josué; Pequeño, Sam; Monrose, Fabián; MacManus, Greg (noviembre de 2009). Código Shell en inglés (PDF) . Actas de la 16ª conferencia ACM sobre seguridad informática y de las comunicaciones. Nueva York, NY, Estados Unidos. págs. 524–533. Archivado (PDF) desde el original el 26 de mayo de 2022 . Consultado el 10 de enero de 2010 .(10 páginas)
  15. ^ "Explicación del código shell alfanumérico de 64 bits y multiarquitectura (x86)". Academia Blackhat. Archivado desde el original el 21 de junio de 2012.
  16. ^ eugene (11 de agosto de 2001). "Arquitectura que abarca Shellcode". Phrack . Phrack Inc. #0x0e de 0x12. Archivado desde el original el 9 de noviembre de 2021 . Consultado el 29 de febrero de 2008 .
  17. ^ Nemo (13 de noviembre de 2005). "OSX: código shell de múltiples arcos". La divulgación completa . Archivado desde el original el 26 de mayo de 2022 . Consultado el 26 de mayo de 2022 .
  18. ^ Cha, Sang Kil; Pak, Brian; Brumley, David ; Lipton, Richard Jay (8 de octubre de 2010) [4 de octubre de 2010]. Programas independientes de la plataforma (PDF) . Actas de la 17ª conferencia ACM sobre seguridad informática y de las comunicaciones (CCS'10). Chicago, Illinois, EE.UU.: Universidad Carnegie Mellon , Pittsburgh, Pensilvania, EE.UU. / Instituto de Tecnología de Georgia , Atlanta, Georgia, EE.UU. págs. 547–558. doi :10.1145/1866307.1866369. ISBN 978-1-4503-0244-9. Archivado (PDF) desde el original el 26 de mayo de 2022 . Consultado el 26 de mayo de 2022 .[1] (12 páginas) (Ver también: [2])

enlaces externos