Glosario – vocabulario de ciberseguridad

En este glosario o vocabulario intentaré definir de forma sencilla y con la exactitud que pueda las palabras usadas comúnmente en el ámbito de la ciberseguridad (seguridad informática) y concretamente en una auditoría de código. En muchas actividades y concretamente cuando elaboramos un informe de auditoría es importante el vocabulario y palabras que usamos.

Si tienes alguna duda o encuentras alguna corrección o mejora por favor contáctame.

Encriptar o cifrar

Ambas palabras se usan para denominar la transcripción de datos mediante una clave. La motivación es ocultar estos datos a toda persona que no disponga de la clave secreta, haciendo por lo tanto un mensaje incomprensible.

Encriptar no significa poner en una cripta. Cripta viene del latín crypta y a su vez viene del griego κρύπτη (kripta) y verbo ‘kriptós’, que significa ocultar. De ahí encriptar en la RAE es transcribir un mensaje que queremos proteger y criptología, según su origen etimológico sería la ciencia de la ocultación.

Este procedimiento de encriptación o cifrado se realiza mediante la elección de un algoritmo criptográfico concreto. Este tiene en cuenta la clave secreta proporcionada para la ocultación de los datos. Todo mensaje cifrado conserva su integridad y puede ser descifrado, aplicando el proceso en forma inversa si dispones de la clave secreta.

Las claves de cifrado y de descifrado pueden ser iguales (criptografía simétrica), distintas (criptografía asimétrica) o de ambos tipos (criptografía híbrida).

Cifrado simétrico

El caso más sencillo, la misma clave secreta cifra y descifra el mensaje. Sí dos personas quieren comunicar datos de esta manera deberían compartir y conocer ambos la clave. Un ejemplo de algoritmo y esquema de cifrado simétrico es Advanced Encryption Standard (AES).

El cifrado simétrico por lo tanto garantiza de forma implícita únicamente confidencialidad. Dando por hecho una adecuada gestión de la clave secreta.

Cifrado asimétrico

La criptografía asimétrica o esquema de clave pública (PKI) describe una infraestructura más compleja que también ofrece más atributos. En ella cada identidad dispone de clave pública y clave privada. Como su propio nombre sugiere una clave podrá ser compartida y la privada deberá protegerse, ya que es el secreto que garantiza la validez del esquema. Un ejemplo es RSA (Rivest, Shamir y Adleman).

Atributos de un esquema de cifrado asimétrico

Dado un par de claves de tu propiedad, clave pública y clave privada, se cumple que:

  • Una no puede conseguirse a partir de la otra. Puedes compartir tu clave pública y la privada se mantendrá secreta.
  • Un mensaje cifrado con una, sólo puede descifrarse con la otra. Es una encriptación de un solo sentido de una clave hacia otra y no es reversible. Es decir, aunque poseas la clave de cifrado, esta no es la clave de descifrado y ni siquiera tú podrías volver atrás. Lo que resulta en:
    • Si cifro un mensaje con tu clave publica, tu y solo tu podrás descifrar este (tu y solo tú dispones de la clave privada), es decir solo tu puedes leer este mensaje. Ni siquiera yo podría descifrar y volver a leer el mensaje a partir del resultado cifrado.
    • Si cifras un mensaje con tu clave privada, solo podemos descifrar y leer el mensaje los que poseamos tu clave pública y además tenemos la certeza de que lo has escrito tu, ya que solo quien posea la clave privada puede hacerlo. Si compartes tu clave pública de forma pública, lo podrá descifrar quien quiera, pero tendremos garantía de autenticidad. Es decir el mensaje no estará protegido a su lectura, pero sí ofrecerá garantía de tu autoría, es lo que se llama firma digital.

El cifrado asimétrico por lo tanto puede usarse para garantizar implícitamente confidencialidad, autenticidad, autenticación y no-repudio. Dando por hecho una adecuada gestión de la clave privada secreta.

Hash

Una función hash es cualquier función que dada una entrada de datos variable, produce una pequeña salida de datos de un formato fijo y que hace referencia de forma inequívoca a esta entrada de datos. La motivación de aplicar esta función es asegurar la integridad de la entrada de datos objeto. Por ejemplo confirmar la autenticidad de un documento sabiendo que su hash actual coincide con su hash original y por lo tanto no ha sido modificado.

Ejemplo, un MD5 resultado de aplicar una función hash a un CD de instalación de debian de 641 megabytes: «3e09869c05b254c45fd6ae44997af2a5»

Atributos de una función hash

A las funciones hash también se les llama funciones resumen o funciones digest y realizan su computación con un algoritmo concreto. Un algoritmo matemático de reducción criptográfica hash ofrece los siguientes atributos:

  • La misma entrada siempre producirá la misma salida. Debe confirmar de forma inequívoca que un archivo, es el archivo auténtico referenciado.
  • Múltiples entradas dispares no deberían producir la misma salida.
  • No debería ser posible pasar de la salida a la entrada.
  • Cualquier modificación de una entrada dada debería dar como resultado un cambio drástico en el hash

El resultado de la aplicación de una función hash, comúnmente también llamado hash (detalle que puede causar algo de incertidumbre), nos sirve para confirmar la integridad de unos datos. Esto no quiere decir que proteja la integridad de estos datos, sencillamente nos servirá para comprobar y poder garantizar si estos datos mantienen su integridad o no.

Por otra parte un producto hash es unidireccional y no reversible. Es decir, con el hash puedes confirmar si un documento sigue igual, pero no podrás leer el documento solo a partir del pequeño hash. Tampoco ocultaras nada, para esa necesidad necesitas criptología.

Crackear un hash

El password cracking o recuperación de contraseña a partir de su hash, consiste en encontrar qué contraseña original en texto plano fue la empleada para generar el hash disponible. Esto ocurre a causa de que las contraseñas, no suelen almacenarse en sistemas informáticos en texto plano y lo que si se almacena siempre es un hash.

Un hash es el resultado de una función de computación de un único sentido y no puede revertirse, es decir a partir de un hash no podemos calcular su contraseña en texto plano original. Aunque no pueda calcularse de forma directa, sí puede conseguirse esta con otras aproximaciones como la fuerza bruta, haciendo uso de diccionarios y tablas simples o tablas rainbow como se explica en este articulo del blog «Rainbow tables, como se crean y usan las tablas de cracking de hash más potentes (explicado fácil, o casi fácil)».

Codificar

Transformar datos para que puedan ser consumidos y explotados de forma correcta por otro sistema. Formatos de codificación de caracteres habituales son ASCII y UTF8. Un ejemplo habitual es codificar un archivo binario en base64 siguiendo la especificación MIME al enviar este por correo electrónico, sencillamente para que este archivo pueda contenerse dentro del texto que conforma el correo electrónico cumpliendo su formato de codificación sin dar problemas.

En este proceso la motivación no es ocultar el mensaje, si no todo lo contrario, facilitar su usabilidad. Por lo tanto no existe clave secreta y el mensaje es siempre legible, este puede ser codificado en un formato u otro, y vuelto a codificar de vuelta, simplemente eligiendo el esquema requerido.

Usando la codificación con motivación maliciosa

En un contexto de hacking ético, cuando queremos explotar una vulnerabilidad es posible que el payload usado para tal fin este registrado en bases de datos de IOCs como malicioso. Por lo tanto un sistema de protección como un firewall, antivirus, IDS, etc… Puede llegar a detectarlo y responder.

Para saltarse este tipo de protección, puede modificarse el payload con varias técnicas, una de ellas es codificación. Realizando cambios de codificación sobre el payload a usar, evitamos detección de malware por patrón o signature e incluso puede complicarse la detección por heurística. Un ejemplo de aplicación es el comando msfencode del framework Metasploit.

Ofuscar

La ofuscación consiste en dificultar la posibilidad de entendimiento de unos datos o de un componente software sin afectar a su funcionalidad. Habitualmente usada en desarrollo de software, complica la legibilidad del código fuente y la realización de ingeniería inversa sobre el código objeto para impedir u obstaculizar su entendimiento.

La ofuscación no debe ser confundida con la minificación, aunque el código resultante pueda parecer similar. El proceso de minificación que se describe como siguiente término, no busca dificultar el entendimiento de un software si no reducir su tamaño y por la tanto su eficiencia sobre todo en ejecuciones que requieren de transmisión por red como habitualmente ocurre con el código javascript.

Aplicaciones de la ofuscación

La ofuscación puede tener las siguientes aplicaciones:

  • Impedir la copia de software por motivos comerciales, protegiendo una propiedad intelectual de la ingeniería inversa cuando este software debe ser distribuido.
  • Proteger un sistema mediante seguridad por oscuridad, complicando el conocimiento del sistema y la exposición de posibles vulnerabilidades a un agente de amenaza.
  • Modificar un payload para evitar su detección, de la misma manera que puede emplearse la codificación, como se describe en el apartado de usando la codificación con motivación maliciosa.
  • Ocultar funcionalidad maliciosa dentro de un software aparentemente legítimo.

Minificar

El proceso de minificación se realiza sobre código fuente o lenguajes de marcado y busca reducir el tamaño de este y por lo tanto aumentar la eficiencia, sobre todo en contextos en los que la ejecución o uso de este implica transmisión por red, como es habitual con el javascript, JSON o XML.

El minificado se consigue eliminando todos los caracteres prescindibles sin afectar a la funcionalidad,es decir sin afectar a la ejecución o integridad de los datos. Los caracteres prescindibles funcionalmente hablando son los introducidos para facilitar la lectura e interpretación humana. Un código minificado puede parecerse a uno ofuscado confundiendo habitualmente estos, sin embargo estos procesos y su resultado son muy diferentes. La ofuscación también se describe en este glosario.

La minificación puede realizarse sobre un payload para evitar su detección, de la misma manera que puede emplearse la codificación, como se describe en el apartado de usando la codificación con motivación maliciosa.

Código fuente

El código fuente o source code en inglés hace referencia al conjunto de líneas de texto escritas en un lenguaje de programación que describe las instrucciones que conforman la lógica de un futuro componente software. Se trata de código legible y modificable por un ser humano y es la forma inicial del software previa a su procesamiento y ejecución. Usualmente puede hacerse referencia al código fuente indistintamente del lenguaje de programación en el que está escrito, como por ejemplo código java o C#.

Métodos de transformación del código para su ejecución

Este código fuente inicial tiene como objetivo ser transformado a código objeto y finalmente transformarse a código ejecutable, pudiendo ejecutar su lógica. Para las transformaciones o traducción anteriormente descrita principalmente existen dos métodos:

  • Compilación: Un compilador es un tipo de traductor que transforma una unidad de código fuente a código objeto, produciendo una unidad de código objeto resultante. El código objeto resultado habitualmente es código máquina ejecutable, aunque también puede ser traducido a un código intermedio (bytecode) o a texto. 
  • Interpretación: Un intérprete o interpretador es un traductor que transforma dinámicamente y a medida que sea necesario, típicamente traduce instrucción por instrucción, código fuente a código objeto, ejecutando este como parte del proceso. Como resultado se obtiene la ejecución directa del código objeto producido, sin almacenar este.
Diagrama proceso transformación código fuente, objeto y ejecutable

Código objeto y código ejecutable

El código objeto es el conjunto de instrucciones descritas en el código fuente, como producto traducido a un lenguaje máquina o bytecode para una plataforma específica de ejecución. Es decir es un código traducido ya a lenguaje máquina, este puede ser entendido y escrito o modificado de forma directa aunque no es lo habitual a causa de su complicada estructura de bajo nivel.

En un entorno de desarrollo habitual, el desarrollador se abstrae de la diferencia entre código objeto y código ejecutable. Esto ocurre por que la propia plataforma se encarga de esta operativa. Para obtener un código ejecutable se han de enlazar todos los archivos de código objeto requeridos, con un programa llamado enlazador (linker).

Este linker descrito en el párrafo anterior, enlaza todas las instrucciones propias del código fuente y otras adicionales necesarias, además de los datos estáticos como variables y constantes. Finalmente conforma un contenedor final ejecutable, como por ejemplo produciendo un formato de salida de archivo ejecutable «.exe».

Código inútil u obsoleto

El código fuente de un componente software puede tener partes de código innecesarias para su función y problemáticas para este. Este tipo de código que es resultado de deficiencias de calidad, causa un consumo de recursos inútil y pueden llegar a causar errores de la aplicación.

Además de lo anterior, no es menos importante el problema de mantenibilidad del sistema que supone, principalmente al suponer una incertidumbre en la lectura y modificación del código del proyecto. Una auditoría de código es una actividad en la que por ejemplo este tipo de código supone una molestia.

A continuación dividiremos este tipo de código en dos tipos.

Código muerto

El tipo más indeseable, consiste en código que es ejecutado pero cuya salida no es utilizada, consume recursos para nada. Es producto de deficiencias de calidad y debe ser revisado y eliminado.

Código inalcanzable

Este código no llega a ejecutarse en ninguna casuística y se encuentra en el repositorio porque algún día si se usó y ha quedado desfasado actualmente o por que forma parte de un conjunto de utilidades entre las cuales otras si son requeridas.

Por lo tanto este tipo de código no es necesario y es residual. Se recomienda eliminarlo, ya que existe el remoto, pero posible riesgo de que se vuelvan a incluir en el proyecto por error, pudiendo causar problemas de seguridad. También es recomendable eliminarlo por motivos de mantenibilidad y simplificación del código.

Referencias y recursos para profundizar más en el tema

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

error: