Mostrando entradas con la etiqueta Virtualización. Mostrar todas las entradas
Mostrando entradas con la etiqueta Virtualización. Mostrar todas las entradas

martes, diciembre 24, 2024

Cómo montar tu propio servidor de Inteligencia Artificial: Modelos Open Source, Parámetros y Hardware NVIDIA

La privacidad es algo que nos preocupa (y cada vez más) en general, y en el ámbito de la Inteligencia Artificial en particular, también es importante para las personas y las organizaciones. Cada vez que escribimos un prompt y lo enviamos a servicios en la nube como ChatGPT o Claude, estamos compartiendo datos que, potencialmente, pueden almacenarse y reutilizarse.

Esto es particularmente preocupante cuando la información enviada es sensible, ya que existe el riesgo de que termine en un Data-leak, afectando tanto a empresas como a individuales.  Además, algunos modelos en la nube utilizan los datos recibidos para mejorar sus sistemas mediante re-entrenamientos, lo que podría provocar que esa información apareciera inesperadamente si alguien realiza las preguntas adecuadas en el futuro. 

Figura 1: Cómo montar tu propio servidor de Inteligencia Artificial.
Modelos Open Source, Parámetros y Hardware NVIDIA

Por otro lado, está, cómo no, el factor económico. Los servicios de IA en la nube suelen cobrar por uso, basándose en la cantidad de tokens procesados por cada consulta o interacción. Para desarrolladores o pequeñas empresas que quieren integrar IA en sus aplicaciones, estos costos pueden acumularse rápidamente y convertirse en una barrera complicada. En este artículo - que tiene dos partes - veremos un recorrido sobre diferentes opciones para esto. 

Figura 2: Libro de Machine Learning aplicado a Ciberseguridad de
Carmen TorranoFran Ramírez, Paloma Recuero, José Torres y Santiago Hernández

Sin embargo, no todo está perdido: los modelos LLM de código abierto ofrecen una alternativa asequible. Estas soluciones nos permiten desplegar IA de forma local (on-premise), eliminando la dependencia de terceros y ofreciendo un control total sobre los datos y los costes (básicamente, el precio de la luz eléctrica). Algo que muchos hechos hecho también para entrenar nuestros modelos de Machine Learning, con lo que para investigadores es una solución perfecta.

Está claro que, el rendimiento de estas alternativas, dependerá del hardware disponible, pero con la infraestructura adecuada, es posible construir entornos locales que pueden ejecutar proyectos de gran complejidad sin poner en peligro nuestra privacidad y tampoco quedarnos sin fondos. Pero vayamos por partes.

Los modelos LLM Open Source

Un modelo LLM (Large Language Model) de código abierto es un modelo de IA entrenado con grandes cantidades de texto para realizar tareas de procesamiento de lenguaje natural (NLP), como generación de texto, traducción, clasificación, entre muchas otras. Al ser de código abierto, los pesos del modelo, el código fuente y, en muchos casos, los datos o el proceso de entrenamiento están disponibles públicamente, permitiendo a cualquiera personalizar, adaptar o reutilizar el modelo para sus propios proyectos. 
La gran mayoría de estos modelos se basan en arquitecturas de Transformers, que ya conocemos bien, que fueron introducidas por Vaswani et al. en 2017, y que utilizan mecanismos de autoatención para analizar el contexto global de las palabras en una secuencia, capturando relaciones complejas entre términos en largos rangos de texto.

El funcionamiento de un LLM se divide en dos fases principales: preentrenamiento y ajuste fino (fine-tuning). En el preentrenamiento, el modelo aprende patrones lingüísticos generales a partir de grandes corpus de texto no supervisados, utilizando tareas como predicción de palabras “enmascaradas” (BERT) o predicción autoregresiva (GPT).

Posteriormente, en el fine-tunning, el modelo es adaptado a tareas concretas mediante conjuntos de datos etiquetados, lo que mejora su precisión en dominios específicos. Estos tienen una escalabilidad exponencial (el rendimiento tiende a mejorar con el aumento del tamaño del modelo y los datos de entrenamiento), capacidades multi-idioma, y flexibilidad para realizar múltiples tareas con el mismo modelo base.

Los “Billions” son la clave …

Es importante dejar claro un tema antes de continuar: los “Billions”. Los “billions” son esa “B” que podemos ver cuando se describe cada modelo. La “B” en los modelos LLM, como 7B13B o 70B, nos muestra la cantidad de billones (americanos) de parámetros que tiene el modelo, donde un parámetro es un coeficiente ajustable aprendido durante el entrenamiento.

Estos parámetros determinan cómo el modelo procesa la entrada (texto) y genera la salida (respuesta), y esto es clave para su capacidad de comprensión y generación de lenguaje natural. En términos técnicos y simplificando mucho, los parámetros son los pesos y sesgos de las capas de la arquitectura Transformer, ajustados a lo largo de millones de iteraciones de entrenamiento para minimizar la pérdida en tareas como predicción de texto. Un mayor número de parámetros permite al modelo capturar patrones más complejos y sutiles en los datos de entrenamiento, mejorando su rendimiento en tareas más complejas.


Pero claro, el aumento en el número de parámetros tiene implicaciones directas en el rendimiento, el coste y la infraestructura necesaria. Modelos más grandes, como uno de 70B, requieren una cantidad exponencialmente mayor de memoria GPU (mínimo aproximadamente 40 GB por GPU para inferencia eficiente) y un mayor tiempo de cómputo, tanto para entrenamiento como para inferencia (no os preocupéis de momento por esto, lo veremos en el siguiente apartado).

Esto impacta en la calidad de las respuestas, especialmente en contextos complejos, pero también introduce latencia y un consumo energético. En cambio, modelos más pequeños como 7B son más rápidos y pueden ejecutarse en hardware más asequible, como un Mac M1 con 16 GB de RAM o una GPU de consumo medio como una NVIDIA RTX 3060 con 12GB de VRAM. Pero mejor vamos a centramos en el hardware para ver qué necesitaremos.

El hardware: Opción NVIDIA

Ya sabemos las restricciones y características que nos ofrecen los modelos de código abierto, ahora necesitamos la electrónica para poder ejecutarlos. Aquí es donde debemos tener en cuenta varias variables. La primera es tener clara la inversión que vamos a hacer y la segunda decidir la posible arquitectura base (x86 vs ARM o dicho de otra manera, NVIDIA vs Apple Silicon). Como todo en la vida, a más dinero mejor ;) pero vamos a ver algunas que no sean una locura de inversión. Cada una de ellas tiene sus ventajas y sus problemas.

Si seleccionamos una arquitectura clásica basada en NVIDIA y x86, el primer paso es tener un buen ordenador. Los ordenadores tipo “gaming” son una gran opción ya que estos suelen llevar una buena configuración de hardware de base. Es importante que tengamos un buen microprocesador de arquitectura x86 ya sea Intel o AMD pero seguro que esto lo vemos mejor con un ejemplo. ¡Ojo!, por supuesto hay más opciones y más sencillas, esto es sólo una recomendación basada en mi experiencia.
Y nada mejor mi que mi caso concreto ;) que es un buen equipo para empezar. Mi servidor de IA también lo utilizo para otras tareas más genéricas (virtualización) y es un AMD Ryzen 9 3900X, con 64GB de RAM y 3TB de disco duro. La tarjeta gráfica que tengo es una RTX 4070 con 12GB de VRAM (estoy esperando a las nuevas 5090 que salen a principios de 2025). La pegatina de Alan Turing también es importante ponerla ;)

Figura 7: Mi servidor local de IA y VMs, con la pegatina de Alan Turing.

Como he comentado antes, esta configuración no la tengo exclusivamente para IA, ya que quiero aprovechar el hardware. Por eso tengo instalado Proxmox como hipervisor (consejo de mi gran amigo Rafael Troncoso, alias "Tuxotron"). La ventaja es que me sirve para gestionar máquinas virtuales y usando la característica “GPU Passthrough” puedo conectar la tarjeta gráfica a la VM que necesite ejecutar IA en local.  De esta forma puedo estar levantando y apagando las VM con diferentes sistemas operativos (eso sí, sólo una VM puede gestionar la gráfica a la vez).

Figura 8: NVidia A100

Esta configuración es más que suficiente para levantar modelo 7B y alguno más a una velocidad decente de ejecución. Aquí la clave está en la memoria VRAM de la tarjeta gráfica, ya que es lo que te permitirá levantar y hacer inferencias a modelos grandes.

El problema de esta configuración x86 basada en NVIDIA, como podéis haber imaginado, es el precio. Una 4090 con 24GB de VRAM está alrededor de los 2.000€ aunque es posible que el precio baje cuando salgan las nuevas 5090. De todas formas, hay soluciones decentes 3090 TI con 24GB a buen precio e incluso podrías conectarlas usado NVLink o SLI y así aumentar la VRAM y su potencia que te permitiría hasta ejecutar modelos de 70B, como puedes ver en el vídeo siguiente.

Figura 9: INSANE! 2 Nvidia RTX 3090 on ONE 850W Power Supply!

Ya si queremos opciones más profesionales como una A100 por ejemplo con 80GB de VRAM ya estamos hablando de precios que oscilan entre los 10.000 y 20.000€ aproximadamente. Pero hay otras opciones, y hay más cosas que tener en cuenta para montar tu propio servidor de Inteligencia Artificial, lo vemos en la siguiente parte que tienes aquí mismo: "Cómo montar tu propio servidor de Inteligencia Artificial: Apple Silicon, Ollama, LMStudio & Pinockio".

Happy Hacking Hackers!!! 

Autor: Fran Ramírez, es investigador de seguridad y miembro del equipo de Ideas Locas en CDO en Telefónica, co-autor del libro "Microhistorias: Anécdotas y Curiosidades de la historia de la informática (y los hackers)", del libro "Docker: SecDevOps", también de "Machine Learning aplicado a la Ciberseguridad” además del blog CyberHades. Puedes contactar con Fran Ramirez en MyPublicInbox.

 Contactar con Fran Ramírez en MyPublicInbox

miércoles, abril 20, 2022

Docker: Lista de Materiales de Software o Software Bill Of Materials (SBOM)

Software Bill Of Materials (SBOM), es un inventario de los componentes de software y dependencias de un sistema, información de dichos componentes y la relación entre ellos. Este inventario se mantiene en un formato que es fácilmente legible por máquinas. Últimamente se han visto muchas vulnerabilidades relacionadas con la cadena de suministro de dependencias, una de las más sonadas el famoso log4shell entre otras. Cuando aparece una vulnerabilidad de este tipo, la pregunta es ¿Estamos afectado por dicha vulnerabilidad? ¿Alguno de nuestros sistemas usa la librería X? Y Docker nos puede ayudar.

Figura 1: Docker. Lista de Materiales de Software
o Software Bill Of Materials (SBOM)

La única forma de poder responder a este tipo de preguntas con cierta confianza es manteniendo el inventario, actualizado, de los componentes y dependencias que nuestros sistemas usan. Hay que tener en cuenta también que dicho inventario no sólo contenga los componentes y dependencias usadas directamente en nuestros sistemas, sino también las dependencias heredadas por dichos componentes y dependencias, también conocidas como dependencias transitivas.

Aunque SBOM no es algo nuevo, se puso muy de moda el año pasado cuando la Casa Blanca lanzó una orden ejecutiva en la requería que cualquier empresa que hiciera negocios con el gobierno norteamericano (venta de software, desarrollo o venta de licencias de uso) fuera capaz de proveer de esta lista de materiales con todos los componentes del software. De esta forma han sido muchas de las empresas que han incluido la posibilidad de la creación de SBOMs en sus herramientas, entre ellas Docker, dentro de su producto Docker Desktop

En la versión 4.7.0, justo después de la publicación de la segunda la edición de nuestro libro Docker: SecDevOps, Docker añadió un plugin por defecto que permite la generación de ficheros SBOM y de los que vamos a ver algunos ejemplos, que ya hemos visto un poco qué es SBOM y por qué es importante. 

Una cosa para recalcar, como se comentó antes, esto no es algo nuevo, y además tampoco es un estándar, por lo que existen varias iniciativas y formatos. Aunque no son los únicos que existen, los siguientes son los formatos que más fuerza o repercusión tienen actualmente:
Sin entrar en más detalles sobre dichos formatos, vamos a ver cómo se puede generar la lista de componentes y dependencias de una imagen de Docker.

Como comenté anteriormente, en la versión 4.7.0, Docker añadió una opción nueva (realmente un plugin) al comando *docker* llamada *sbom*. Este plugin usa por detrás un proyecto de Anchore llamado [syft](https://github.com/anchore/syft). Éste analiza las capas de la imagen y extrae la información sobre que comoponentes hay en cada capa. Si ejecutamos dicho comando obtendremos la siguiente salida:
    $ docker sbom

    Usage:  docker sbom [OPTIONS] COMMAND

    View the packaged-based Software Bill Of Materials (SBOM) for an image.

    EXPERIMENTAL: The flags and outputs of this command may change.
    Leave feedback on https://github.com/docker/sbom-cli-plugin.
    Examples:

    docker sbom alpine:latest                                    a summary of discovered packages
    docker sbom alpine:latest --format syft-json                 show all possible cataloging details
    docker sbom alpine:latest --output sbom.txt                  write report output to a file
    docker sbom alpine:latest --exclude /lib --exclude '**/*.db' ignore one or more paths/globs in the image

    Options:
    -D, --debug                 show debug logging
        --exclude stringArray   exclude paths from being scanned using a glob expression
        --format string         report output format, options=[syft-json cyclonedx-xml cyclonedx-json
                                github-0-json spdx-tag-value spdx-json table text] (default "table")
        --layers string         [experimental] selection of layers to catalog, options=[squashed all] (default
                                "squashed")
    -o, --output string         file to write the default report output to (default is STDOUT)
        --platform string       an optional platform specifier for container image sources (e.g. 'linux/arm64',
                                'linux/arm64/v8', 'arm64', 'linux')
        --quiet                 suppress all non-report output
    -v, --version               version for sbom

    Commands:
    version     Show Docker sbom version information

    Run 'docker sbom COMMAND --help' for more information on a command.
    an image argument is required
Dicho plugin permite la generación de ficheros SBOM en formato SPDX y CycloneDX. Veamos a continuación la salida por defecto que se produciría sobre una imagen Alpine:
    $ docker sbom alpine
    Syft v0.43.0
    ✔ Loaded image
    ✔ Parsed image
    ✔ Cataloged packages      [14 packages]

    NAME                    VERSION      TYPE
    alpine-baselayout       3.2.0-r16    apk
    alpine-keys             2.3-r1       apk
    apk-tools               2.12.7-r0    apk
    busybox                 1.33.1-r3    apk
    ca-certificates-bundle  20191127-r5  apk
    libc-utils              0.7.2-r3     apk
    libcrypto1.1            1.1.1l-r0    apk
    libretls                3.3.3p1-r2   apk
    libssl1.1               1.1.1l-r0    apk
    musl                    1.2.2-r3     apk
    musl-utils              1.2.2-r3     apk
    scanelf                 1.3.2-r0     apk
    ssl_client              1.33.1-r3    apk
    zlib                    1.2.11-r3    apk
En este caso se puede ver la lista de los componentes de la imagen *alpine:latest*. Ahora veamos el mismo ejemplo, pero en formato SPDX:
    $ docker sbom --format spdx alpine
    Syft v0.43.0
    ✔ Loaded image
    ✔ Parsed image
    ✔ Cataloged packages      [14 packages]

    SPDXVersion: SPDX-2.2
    DataLicense: CC0-1.0
    SPDXID: SPDXRef-DOCUMENT
    DocumentName: alpine-latest
    DocumentNamespace: https://anchore.com/syft/image/alpine-latest-b478dc4d-bced-406a-adf9-6f7b7ea6d231
    LicenseListVersion: 3.16
    Creator: Organization: Anchore, Inc
    Creator: Tool: syft-[not provided]
    Created: 2022-04-15T20:19:57Z

    ##### Package: alpine-baselayout

    PackageName: alpine-baselayout
    SPDXID: SPDXRef-Package-apk-alpine-baselayout-ed18f2a986e77aab
    PackageVersion: 3.2.0-r16
    PackageDownloadLocation: NOASSERTION
    FilesAnalyzed: false
    PackageLicenseConcluded: GPL-2.0-only
    PackageLicenseDeclared: GPL-2.0-only
    PackageCopyrightText: NOASSERTION
    ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*
    ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*
    ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine_baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*
    ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine_baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*
    ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*
    ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*
    ExternalRef: PACKAGE_MANAGER purl pkg:alpine/alpine-baselayout@3.2.0-r16?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.14.2

    ##### Package: alpine-keys
    ...
La salida es mucho más larga, pero a modo de ejemplo se puede ver uno de los componentes encontrados, con nombre, licencia, referencias externas, etcétera. También es posible generar la salida en formato *json*:
    $ docker sbom --format spdx-json alpine
    Syft v0.43.0
    ✔ Loaded image
    ✔ Parsed image
    ✔ Cataloged packages      [14 packages]

    {
        "SPDXID": "SPDXRef-DOCUMENT",
        "name": "alpine-latest",
        "spdxVersion": "SPDX-2.2",
        "creationInfo": {
        "created": "2022-04-15T21:15:23.057754Z",
        "creators": [
        "Organization: Anchore, Inc",
        "Tool: syft-[not provided]"
    ],
        "licenseListVersion": "3.16"
    },
        "dataLicense": "CC0-1.0",
        "documentNamespace": "https://anchore.com/syft/image/alpine-latest-2ea1fa9e-099e-4939-bdd8-d41fab29f1b0",
        "packages": [
        {
        "SPDXID": "SPDXRef-ed18f2a986e77aab",
    ...
Para ver la salida en formato CycloneDX:
    $ docker sbom --format cyclonedx alpine
    Syft v0.43.0
    ✔ Loaded image
    ✔ Parsed image
    ✔ Cataloged packages      [14 packages]

    [0000]  WARN unable to convert relationship from CycloneDX 1.3 JSON, dropping:
    {From:Pkg(name="musl" version="1.2.2-r3" type="apk" id="304c2239a7d1d6b7")
     To:Location<RealPath="/lib/ld-musl-x86_64.so.1" 

    ...

    <?xml version="1.0" encoding="UTF-8"?>
    <bom xmlns="http://cyclonedx.org/schema/bom/1.4"
           serialNumber="urn:uuid:faaf4f40-e332-4f0e-8acc-3fadcae62d25" version="1">
    <metadata>
        <timestamp>2022-04-15T17:17:00-04:00</timestamp>
        <tools>
        <tool>
            <vendor>anchore</vendor>
            <name>syft</name>
            <version>[not provided]</version>
        </tool>
        </tools>
        <component bom-ref="e33e1cadf7cfbd1e" type="container">
        <name>alpine:latest</name>
        <version>sha256:a2f19fdc3f78ddc201c5bb37e302fed8b3487695056215b5577113d3938196bf</version>
        </component>
    </metadata>
    <components>
        <component type="library">
        <publisher>Natanael Copa <ncopa@alpinelinux.org></publisher>
        <name>alpine-baselayout</name>
        <version>3.2.0-r16</version>
        <description>Alpine base dir structure and init scripts</description>
        <licenses>
            <license>
            <id>GPL-2.0-only</id>
            </license>
        </licenses>
        <cpe>cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*</<pe>
        <purl>pkg:alpine/alpine-baselayout@3.2.0-r16?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.14.2</purl>
        <externalReferences>
            <reference type="distribution">
            <url>https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout</url>
            </reference>
        </externalReferences>
        <properties>
            <property name="syft:package:foundBy">apkdb-cataloger</property>
            <property name="syft:package:metadataType">ApkMetadata</property>
            <property name="syft:package:type">apk</property>
            <property name="syft:cpe23">cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
            <property name="syft:cpe23">cpe:2.3:a:alpine_baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
            <property name="syft:cpe23">cpe:2.3:a:alpine_baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
            <property name="syft:cpe23">cpe:2.3:a:alpine:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
            <property name="syft:cpe23">cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
            <property name="syft:location:0:layerID">sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68</property>
            <property name="syft:location:0:path">/lib/apk/db/installed</property>
            <property name="syft:metadata:gitCommitOfApkPort">8a8c96a0ea2fcd824c361aa4438763fa33ee8ca0</property>
            <property name="syft:metadata:installedSize">413696</property>
            <property name="syft:metadata:originPackage">alpine-baselayout</property>
            <property name="syft:metadata:pullChecksum">Q1UJtB9cNV4r+/VbxySkEei++qbho=</property>
            <property name="syft:metadata:pullDependencies">/bin/sh so:libc.musl-x86_64.so.1</property>
            <property name="syft:metadata:size">20716</property>
        </properties>
        </component>
        ...
    ...
Como se pueden ver los campos generados son distintos que SPDX y el formato, por defecto, es XML, pero al final la información que se recolecta es prácticamente la misma. También es posible la generación en formato *json*:
    $ docker sbom --format cyclonedx-json alpine
    Syft v0.43.0
    ✔ Loaded image
    ✔ Parsed image
    ✔ Cataloged packages      [14 packages]

    [0000]  WARN unable to convert relationship from CycloneDX 1.3 JSON, dropping: {From:Pkg(name="musl" version="1.2.2-r3" type="apk" id="304c2239a7d1d6b7") To:Location<RealPath="/lib/ld-musl-x86_6
    ...

    {
    "bomFormat": "CycloneDX",
    "specVersion": "1.4",
    "serialNumber": "urn:uuid:95cef6a2-edcb-4b82-91a4-3ed026f1670f",
    "version": 1,
    "metadata": {
        "timestamp": "2022-04-15T17:21:34-04:00",
        "tools": [
            {
                "vendor": "anchore",
                "name": "syft",
                "version": "[not provided]"
            }
            ],
                "component": {
            "bom-ref": "e33e1cadf7cfbd1e",
            "type": "container",
            "name": "alpine:latest",
            "version": "sha256:a2f19fdc3f78ddc201c5bb37e302fed8b3487695056215b5577113d3938196bf"
        }
    },
    "components": [
        {
            "type": "library",
            "publisher": "Natanael Copa \u003cncopa@alpinelinux.org\u003e",
            "name": "alpine-baselayout",
            "version": "3.2.0-r16",
            "description": "Alpine base dir structure and init scripts",
            "licenses": [
                {
                    "license": {
                        "id": "GPL-2.0-only"
                }
                }
        ],
            "cpe": "cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*",
            "purl": "pkg:alpine/alpine-baselayout@3.2.0-r16?arch=x86_64\u0026upstream=alpine-baselayout\u0026distro=alpine-3.14.2",
            "externalReferences": [
                {
                    "url": "https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout",
                    "type": "distribution"
            }
        ],
        "properties": [
            {
                "name": "syft:package:foundBy",
                "value": "apkdb-cataloger"
            },
            {
                "name": "syft:package:metadataType",
    ...
La lista de los formatos soportados actualmente son:
* syft-json
* cyclonedx-xml
* cyclonedx-json
* github-0-json 
* spdx-tag-value 
* spdx-json 
* table (formato por defecto)
* text
Si en vez mandar el contenido del fichero a la consola o salida estándar, queréis que se guarde en un fichero, se puede usar la opción -o o --output:
    $ docker sbom --format spdx-json -o alpine.json alpine
    Syft v0.43.0
    ✔ Loaded image
    ✔ Parsed image
    ✔ Cataloged packages      [14 packages]
La inclusión de este plugin en Docker está en modo experimental y puede que en futuras versiones éste cambie. Si tienes que generar SBOMs en entornos de producción, se podría usar la herramienta syft directamente. Esta herramienta es mucho más completa que lo que ofrece actualmente el plugin de Docker.

Happy Hacking!

viernes, abril 08, 2022

Nuevo libro "Docker: SecDevOps (& SecDevOps)" 2ª Edición de @0xWord

Hoy estamos de estreno en 0xWord, ya que tenemos la 2ª Edición de uno de los libros más vendidos y mejor valorados de nuestra editorial. Tenemos la segunda edición del libro de Docker:SecDevOps escrito por Rafael Troncoso, Elias Grande y Fran Ramírez, que ya tienes disponible a la venta en la web de 0xWord.
A través de este libro se profundizará en la tecnología de contenedores Docker, la cual es la más extendida a día de hoy en el sector de IT. Entre otros temas, se abordarán tanto buenas prácticas a la hora de construir las imágenes Docker así como buenas prácticas de seguridad a aplicar a nivel del host en el que se ejecutan dichos contenedores. Desde el propio demonio de Docker al resto de componentes que conforman su pila tecnológica.
Además de las buenas prácticas se tratarán temas como las redes en Docker, la orquestación de contenedores a través de distintas máquinas host mediante una introducción a Docker Swarm, y como no podía ser menos, la utilización de Docker Compose para la creación de aplicaciones multi-contenedores y su despliegue tanto en servidores individuales como en entornos Swarm

Figura 3: Índice del libro "Docker : SecDevOps" 2ª Edición de 0xWord

Por otro lado, y una vez comprendida la tecnología Docker, se realizará una recomendación sobre cómo un perfil de seguridad debería intervenir dentro de los flujos de “DevOps” para añadir el “Sec” sin bloquear la entrega continua de software que dicha filosofía persigue. Además, dentro de dicha recomendación, se abordarán los temas del análisis estático de vulnerabilidades sobre imágenes Docker, la firma de dichas imágenes y su posterior publicación en un Docker Registry
Finalmente, se realizará un repaso al conjunto de los proyectos más importantes dentro del abanico ofrecido por el Proyecto Moby, como son los proyectos: InfraKit, LinuxKit, BuildKit, Containerd y RunC, y SwarmKi. Y si tienes dudas, puedes contactar con los autores en su perfiles públicos de MyPublicInbox. El libro lleva también 100 Tempos gratis para todos los compradores.

¡Saludos Malignos!

Autor: Chema Alonso (Contactar con Chema Alonso)  


sábado, diciembre 07, 2019

[Write UP]. Solución del Primer Reto Hacker para aprender

En el siguiente artículo muestro todos los pasos que he realizado hasta dar con la solución del Primer del Reto Hacker de este curso que nos ha propuesto por Amador Aparicio y que se publicó hace poco en este blog.

Figura 1: [Write UP]. Solución del Primer Reto Hacker para aprender.

En primer lugar, he procedido a descargar y montar una máquina virtual en VirtualBox a partir del fichero .OVA entregado en el enunciado del Reto Hacker:

Figura 2: Recursos necesarios para la resolución del Reto Hacker.

Creación del Entorno de Pruebas

La configuración para el adaptador de red de la máquina virtual será “modo Red Interna”. A efectos prácticos, cualquier otra máquina virtual con el adaptador de red en “modo Red Interna” estaría en el mismo segmento de red pero sin conexión con otras redes.

Figura 3: Configuración de los adaptadores de red de las máquinas virtuales sobre VirtualBox.

Utilizaré también una máquina virtual Kali Linux para realizar las pruebas necesarias. La dirección IP de esta otra máquina estará dentro de la red 1.0.0.0/24.

Comunicación con “matrix”, la máquina objetivo

Al intentar comunicarnos con la máquina “matrix” a través de peticiones de tipo ICMP (8), vemos que ésta no nos responde. Hacemos un escaneo rápido de tipo SYS con nmap a todos los puertos TCP de la máquina objetivo, “matrix”, y vemos que los resultados son negativos.

Figura 4: Configuración IPv4 de la máquina Kali Linux. Resultados del escaneo de tipo SYS.

Esto nos da a entender que las conexiones a primera vista están bloqueadas por algún tipo de firewall en la máquina “matrix”, muy posiblemente con IPTables. Regla de oro básica en el Hardening de servidores GNU/Linux.

Figura 5: Libro de Hardening de servidores GNU/Linux 3ª Edición.

Vamos a analizar el archivo .pcap con Wireshark para ver si llegamos a alguna conclusión de lo que está sucediendo. Para ello utilizaré el filtro “ip.addr==1.0.0.1” para ver con qué direcciones IPv4 se ha comunicado “tokio”.

Figura 6: Conexión TCP al puerto 22/TCP desde la máquina 1.0.0.254.

Como podemos ver, la maquina ha recibido una conexión TCP al puerto 22/TCP desde otra máquina cuya dirección IP era la 1.0.0.254. Esto nos da a entender que al menos tiene que permitir conexiones al puerto 22/TCP si ponemos esa dirección IPv4 a nuestra máquina. Cambiamos la dirección IPv4 de la máquina Kali Linux asignándole la dirección 1.0.0.254/24 y realizamos las pruebas anteriores.

Figura 7: Cambio de IP en Kali Linux. Nuevo escaneo de tipo SYN.

En efecto, como podemos ver ahora, la maquina objetivo tiene el puerto 22/TCP (servicio SSH) abierto.

Pruebas de acceso a la máquina objetivo, matrix.

Puesto que ya sabemos un nombre de usuario (“tokio”) de esa máquina que tiene permitido el acceso por SSH, realizaremos un ataque de fuerza bruta basado en diccionario desde nuestra máquina de ataque basada en Kali Linux.

Figura 8: Libro de Pentesting con Kali Linux en 0xWord

Para poder realizar un ataque de fuerza bruta lo que se necesita es la herramienta que lo realice, NCrack, y un diccionario de contraseñas para que el programa pueda probar continuamente hasta que dé con una contraseña valida. Como diccionario he utilizado el mismo que usa la herramienta JohnTheRipper.

Figura 9: Diccionario usado por la herramienta JohnTheRipper con 3651 palabras.

En mi caso, el diccionario lo he obtenido de la web https://wiki.skullsecurity.org/Passwords. Con el diccionario ya en nuestro poder podemos proceder a realizar un ataque de fuerza bruta sobre la contraseña sobre el usuario “tokio” del servicio SSH.

Figura 10: Ataque de fuerza bruta con diccionario sobre el servicio SSH para el usuario "tokio".

Sorprendentemente vemos que ha funcionado y nos ha dicho que la contraseña valida es “qwerty”. Hay que decir que, en esta parte, al principio había usado el diccionario de Cain&Abel, que es muchísimo mas grande, pensando que la clave sería más rara, pero tras 5 minutos y solo avanzar un 2% decidí probar paralelamente el diccionario de JohnTheRipper y en 1 minuto dio resultado. A veces  Con el acceso al servidor conseguido procedemos a entrar por SSH:

Figura 11: Acceso al servicio SSH con el usuario tokio.

Ya que estamos dentro y, por mera curiosidad, vamos a ver qué reglas de firewall tiene aplicadas iptables en la configuración de seguridad del tráfico de red.

Figura 12: Reglas de iptables en la máquina matrix.

Efectivamente, por defecto las políticas del firewall bloquean cualquier conexión que no venga de localhost o de la dirección IPv4 1.0.0.254. Por eso en un principio no pudimos conectarnos con otra dirección IP.

En búsqueda de la tabla de la base de datos

Bueno, vamos al lio, y revisar qué encontramos en la base de datos MySQL que tiene instalado el servidor. Vamos a ver si podemos conectarnos con las mismas credenciales.

Figura 13: Conexión al SGBD con un cliente MySQL.

Vemos que se nos permite realizar la conexión con este usuario, así que podemos analizar qué bases de datos tenemos disponibles en este servidor MySQL.

Figura 14: Base de datos disponible para usuario 'tokio'.

Como se puede observar, el usuario tokio no ha creado ninguna base de datos, ya que sólo tiene disponible el diccionario de datos del SGBD. Esto nos quiere decir que este usuario no ha sido el que ha creado la base de datos con la tabla que se propone en el enunciado del reto, pero al menos no la base de datos.

Figura 15: Libro de Linux Exploiting

Aquí he estado atascado un tiempo, hasta que me dio por ver si podía entrar con el usuario root a ver si el tenia otras tablas. Pero para ello habría que conseguir la credencial del usuario root, o bien buscando una vulnerabilidad explotable o bien realizando un ataque de diccionario al usuario root tal y como se ha hecho a tokio. Estando en local, tal vez es posible acceder a inicio de sesión con root.

Escalada de privilegios

Ya que el usuario “tokio” no ha creado ninguna tabla vamos a ver si “root” nos muestra algo diferente, y, el error que nos encontramos es que el usuario tokio y el usuario root comparten la misma contraseña. Probablemente el administrador (root) creo a tokio y no tenía ganas de aprenderse otra contraseña. Un error muy común cuando una persona tiene que gestionar muchas credenciales y no utiliza un gestor de contraseñas - o tiene un 2FA - para protegerlas.

Figura 16: Con su y probando la misma password (password guessing) entramos.

Vemos que el usuario “root” tiene la misma contraseña que el usuario “tokio”, lo cual es muy conveniente para un atacante como yo. Y como he dicho, que no tenga un 2FA ayuda mucho más. Menos mal que no tenían configurado SSH en Paranoid Mode. Vamos a ver si nos deja conectarnos a MySQL para inspeccionar qué bases de datos hay disponibles.

Figura 17: Conexión con el usuario “root” al SGBD.

Interesante, nos deja entrar con el usuario “root” y además vemos que hay una base de datos que se llama “reto1”. Veamos que hay en ella:

Figura 18: Contenido de la tabla "flag".

Bueno bueno, pues vemos que hemos encontrado la “información sensible”. Se ve que esta gente estaba esperando a que alguien entrara a husmear.

Conclusiones

Decir que al principio perdí algo de tiempo pensando que había que descodificar la contraseña de algún modo por la información entregada en el dump del fichero .pcap, pero llegue a la conclusión de que SSHv2 es un protocolo bastante seguro ya que cifra la comunicación entre el cliente y servidor. Cuando ya me dio por probar “a entrar” utilizando fuerza bruta, ya todo empezó a tomar forma, aunque hasta que no conseguí la clave no pensé que fuera ese el método que quería Amador.

Una vez conseguida la contraseña, también me llevo un rato llegar a la conclusión de cambiar al usuario “root”. Pero lo mejor de todo, es que tuve que probar diferentes estrategias y utilizar distintas herramientas de configuración, del sistema y de ataque.

Autor: Rodrigo Díez Fernández (https://diezrofer.es/), estudiante de Administrador de Sistemas Informáticos en Red en Salesianos Villamuriel.

jueves, mayo 14, 2015

VENOM: Un bug en entornos virtuales para llegar al host

El nuevo nombre molón para un bug es VENOM, acrónimo que viene de Virtual Environment Neglected Operations Manipulation que me ha sonado a como nosotros construimos FOCA, que venía de Fingerprinting Organizations with Collected Archives. En este caso, el bug está en el software de gestión de los floppy disks (sí, de disquetes) que utilizan los principales hypervisores de máquinas virtuales.

Figura 1: Venom vulnerability

El bug en sí es muy peligroso en su concepto, ya que permite que el dueño de una máquina virtual pase a poder ejecutar código en la máquina host anfitriona y de ahí pasar, por ejemplo a otras partes de la red. El gráfico que se publica en la página web que se ha creado para recoger la información de VENOM lo explica muy bien.

Figura 2: Riesgo de explotación de VENOM en una organización vulnerable

El software afectado por esta vulnerabilidad, que se le ha dado el CVE-2015-3456 es el Virtual Floppy Disk Controller (FDC) de QEMU, que está presente en las plataformas de XEN Project, en KVM de RedHat y en el software de Citrix. Hay que recalcar que ni VMWare ni Microsoft Hyper-V se ven afectados por este fallo.

Amazon Web Services y VENOM

Existen muchas plataformas de nube pública y nube privada que se ven afectadas por este bug, e incluso Amazon ha tenido que explicar las medidas para su plataforma de cloud, pero por ahora no se ha filtrado el exploit y parece que nadie ha visto una explotación del vulnerabilidad en ningún sistema por ahora. Según un portavoz de Amazon:
"Customer security is our top priority, and AWS takes extraordinary 'defense in depth' measures in constructing systems that do not rely solely upon any single component, such as the hypervisor, to protect customers."
Para evitar que este tipo de bugs puedan afectar a redes virtuales en sistemas de misión crítica o de alta seguridad, existen soluciones de hardening de redes que virtualizan y cifran todos los contenedores, evitando que un fallo en uno de estos sistemas permita al escalada hacia hosts anfitriones u otras partes de la red, que probablemente sean las medidas de contención y defensa en profundidad que desde Amazon argumentan.

Saludos Malignos!

martes, marzo 04, 2014

Emular una Máquina Virtual y evitar infección de malware

Con el actual crecimiento exponencial de malware circulando por la red, las empresas de antivirus se ven obligadas a buscar nuevas formas para detectar y evadir estas amenazas. Además de usar las tradicionales bases de datos de firmas para buscar coincidencias con los ficheros, también hacen uso de complejas técnicas de heurística para detectar pro-activamente amenazas, basándose en el comportamiento de los ejecutables, accesos a memoria y analizando el código que se ejecuta en nuestro ordenador.

Si bien es cierto que estas técnicas funcionan bastante bien, los desarrolladores de malware siguen saliéndose con la suya y consiguen infectar miles de equipos a diario. Para evitar que sus programas maliciosos sean estudiados por los investigadores, una característica que los creadores de estos incluyen en su malware, es la detección de máquinas virtuales o de las herramientas de debugging, técnica que les permite detectar si su ejecutable está ejecutándose en una VM o dentro de una sandbox. De esta forma, si intentamos ejecutar una muestra de malware en una máquina virtual, esta probablemente no hará nada o actuará de forma benigna, intentando así pasar desapercibida en un entorno propicio para ser analizada.

Figura 1: Software de protección como Themida detecta las VM

Pero… ¿podríamos usar esta característica del malware a nuestro favor? Si los desarrolladores intentan evitar la ejecución de sus programas en máquinas virtuales, ¿por qué no replicar la configuración de una VM en un equipo físico y así evadir infecciones? El objetivo final sería conseguir aplicar una característica defensiva del malware para obtener un punto más de fortificación de sistemas Microsoft Windows contra precisamente malware.

A principio de octubre, Jordi Serra me propuso presentar un artículo en la ronda europea de Cyber Security for the Next Generation, una conferencia estudiantil organizada por Kaspersky Academy. Me decanté por hacer una herramienta que emulara máquinas virtuales para evadir infecciones de malware o, por lo menos, una parte de los programas maliciosos. La idea consistía principalmente en estudiar a fondo una VM, inicialmente Virtual Box, y tratar de replicar al máximo sus características en un equipo físico.

Dentro del registro de Windows hay numerosas llaves que delatan un entorno virtual. A diferencia de un equipo físico, donde el disco duro y lector de DVD puede ser de cualquier fabricante, en una VM estos dispositivos virtuales tienen un nombre genérico. En el caso de Virtual Box los nombres son tan llamativos como “VBOX HARDDISK” o “VBOX CD-ROM”, hallados en varios “values” del registro.

Otros valores llamativos dentro del registro son los que hacen referencia a la BIOS, concretamente en las claves SystemBiosVersion y VideoBiosVersion dentro de la ruta “HKLM\Hardware\DESCRIPTION\System”. De esta forma, haciendo un par de búsquedas en el registro con las cadenas de texto “vbox” y “Virtual Box” encontraremos decenas de resultados.

Figura 2: Carpetas y claves de registro específicos para Virtual Box

Además de las numerosas carpetas y keys que se crean por defecto en el registro de Windows al instalarlo bajo Virtual Box, existen también varios archivos y librerías propios de Virtual Box Guest Additions. Aunque basarse en éstos para detectar una máquina virtual no es lo más adecuado, hay malware que, además de comprobar el registro, busca estos archivos o intenta cargar alguna DLL específica.

Figura 3: Archivos creados al instalar Virtual Box Guest Addition Tools

Conociendo todas la keys del registro y archivos que se pueden usar para detectar un sistema virtualizado con Virtual Box, “solo” nos queda crear un script que replique esta configuración en un equipo físico y probar si realmente funciona. Para desarrollar el script usé Python, principalmente por ser un lenguaje muy amigable. El código no hace nada más que crear/modificar llaves y valores del registro, crear archivos y descargar algunas librerías de Internet para registrarlas en el sistema.

Figura 4: Parte del código utilizado

Aunque esto es solo una parte del código, el resto de líneas son principalmente más modificaciones en el registro y la creación del resto de archivos comentados anteriormente. Con el script ya creado, solo queda ejecutarlo, en este caso sobre una instalación limpia de Windows XP (sistema para el que está optimizado el código) y comprobar su funcionamiento. Para probarlo, además de una muestra real de malware, podemos usar herramientas como Pafish de Albert Ortega. Esta herramienta implementa 5 comprobaciones para detectar un sistema virtualizado con Virtual Box, 4 de ellas las realiza sobre el registro de Windows y la última buscando el driver VboxMouse.sys.

Figura 5: Resultado con la herramienta Pafish

Los resultados antes y después de la ejecución del script nos muestran que éste funciona bien o, por lo menos, consigue engañar a Pafish. Para realizar una prueba con malware real, usé el gusano Net-Worm.Win32.Kolab.wwh, del que podéis ver un amplio análisis en el blog de Secure list. Esta versión concreta implementa un sistema anti-debugging bastante extenso, que comprueba desde el registro de Windows hasta la ruta en la que se encuentra en el momento de su ejecución, pasando por el nombre del equipo y los procesos que se están ejecutando. Cuando una de sus comprobaciones da positivo se elimina por completo, evitando así ser analizado.

Figura 6: Análisis del guano Net-Worm.Win32.Kolab.wwh

Si probáis a ejecutarlo en una máquina virtual veréis que tras su ejecución, desaparece como por arte de magia. En nuestro caso, al iniciarlo en el equipo de pruebas antes de modificarlo con el script, el gusano se instala como está programado, pero si lo ejecutamos en un sistema modificado para parecer una máquina virtual, cree que se encuentra en una VM y se autodestruye.

Aunque sea un método poco ortodoxo para evadir infecciones de malware, lo cierto es que funciona. Basándonos en esta técnica, es posible que se puedan evitar infecciones de malware aún desconocido que implemente estas técnicas de ocultación. No obstante, como prueba de concepto es válida y tanto Jordi Serra como yo, estamos trabajando duro para publicar pronto una versión estable y más compleja de la herramienta. Por ahora, si os ha gustado, podéis ver las diapositivas de la presentación que que preparé para la International Student Conference de Kaspersky celebrada en Milán el pasado mes de Diciembre, donde tuve el honor de dar mi primera charla fuera de España y compartir unos días con el estupendo equipo de Kaspersky Academy.

By Jordi Vázquez (@jordisk)

viernes, noviembre 15, 2013

Un examen con chuleta

Ayer me llegó por parte de un amigo un examen que la gente de RedHat, Intel y HP habían publicado en la web para regalar premios si eres un Experto en Virtualización. La gracia de hacer esta campaña de marketing como si fuera un examen es, que por medio de 15 sencillas preguntas sobre virtualización, puedas ir poniendo los mensajes comerciales en que estás interesado dentro de la cabeza de los clientes.

Figura 1: "Examen" para saber si eres un experto en virtualización

La idea es buena, más si cabe cuando en las propias bases del concurso dice que para obtener las cazadoras era necesario responder al menos a 11 preguntas correctamente de las 15 totales, por lo que algo habría que saber sobre el tema. Este truco de hacer que se tengan que responder correctamente 11 hace que se garanticen que el marketing y los premios van dirigidos a las personas que a ellos les interesan, es decir, a las que tienen algunos skills básicos que los hacen público objetivo de su campaña.

Figura 2: Condiciones para aprobar

Las preguntas luego son bastante evidentes, ya que sin saber la respuesta, teniendo en cuenta quién está detrás de la campaña, cualquier puede hacerse una "ligera" idea de cuál es la respuesta. ¿A que se te ha ocurrido que tal vez, pudiera ser, a lo mejor, con alguna más probabilidad que las demás respuestas, solo por deducción y reducción al absurdo, que la respuesta correcta es la tercera?.

Figura 3: La pregunta 1

Pero si te quedan dudas, de que esto es una campaña de marketing y no un examen, solo tienes que ver las medidas de seguridad que se han implementado para evitar que copies o te chiven, ya que basta con dar a ver el código fuente y ver las respuestas de todas las preguntas.

Figura 4: La respuesta de la pregunta 1

Esto que en este caso es un caso muy evidente de marketing, aparece sin embargo en otros entornos en los que no es una campaña de marketing, sobre todo en aquellos en los que usan cosas en Flash o Applets Java, así que si alguna vez te preguntan algo mira a ver qué pistas hay en el código fuente y decompila los SWF y los Applet Java solo por si el examen viniera con chuleta.

Saludos Malignos!

Entrada destacada

+300 referencias a papers, posts y talks de Hacking & Security con Inteligencia Artificial

Hace un mes comencé a recuperar en un post mi interés en los últimos años, donde he publicado muchos artículos en este blog , y he dejado mu...

Entradas populares