Как стать автором
Обновить
63.77
Swordfish Security
Информационная безопасность, DevSecOps, SSDL

Инструкция по SCA: генерация SBOM, инструменты, отличия

Время на прочтение11 мин
Количество просмотров2.9K

Вступление

Анализ сторонних компонентов ПО становится всё более актуальным в свете увеличения числа уязвимостей в открытом исходном коде. Популярные репозитории содержат более 20 тысяч потенциально опасных пакетов, в широко используемых библиотеках часто обнаруживаются уязвимости, которые делают небезопасным весь программный продукт.

С вами Вера Багно, AppSec-инженер компании Swordfish Security. Сегодня мы поговорим о спецификации SBOM (Software Bill of Material) и как она может помочь решить проблему отслеживания уязвимостей в исходном коде сторонних библиотек. Также обсудим, в каких сферах используется SBOM, какими форматами представлен и какое применение находит в информационной безопасности, в частности, в рамках SCA-анализа.

Эта статья будет интересна как специалистам ИБ, так и разработчикам, желающим сделать свой продукт безопаснее.

SBOM: библиотеки, их лицензии и уязвимости

Библиотеки с открытым исходным кодом – это ПО, исходный код которого можно свободно изучать, распространять и изменять (если нет ограничения лицензии компонента – об этом расскажем в будущих статьях). Создают их как энтузиасты, так и специалисты крупных корпораций. Они выкладывают такие библиотеки на Github или в официальные репозитории, например, maven или npm. Разработчики часто используют это решение, чтобы сэкономить время и деньги компании. Они импортируют библиотеки в свой код и применяют их функции для решения проектных задач.

В то же время применение ПО с открытым исходным кодом несет определенные риски. Помимо вредоносного кода, заведомо внедренного в библиотеку для нанесения ущерба во время сборки и эксплуатации, такое ПО может содержать код, в котором не использовались практики безопасной разработки (например, фильтрация и валидация данных). Это может привести к различным проблемам безопасности. Один из ярких примеров – уязвимость Log4shell, которая была обнаружена (причем несколько раз) в популярной библиотеке для логирования в Java – Log4j. Из-за этого множество приложений и организаций оказались скомпрометированы, поскольку они так или иначе использовали ее в своем составе или периметре. Компаниям важно следить за библиотеками, применяемыми при разработке программных продуктов, а также иметь актуальную информацию о проблемах безопасности, которые в них находят. В этом поможет формирование файла SBOM.

SBOM – это файл в формате JSON или XML, который включает в себя инвентаризационный список всех компонентов (пакетов, библиотек), используемых в разрабатываемом приложении или необходимых для его работы.

Существуют и другие файлы манифестов, которые можно создавать и поддерживать самостоятельно в разных форматах. Большинство компаний используют CycloneDX, SPDX (Software Packet Data Exchange) и SWID (Software Identification). В этой статье мы поговорим о CycloneDX.

SBOM состоит из нескольких блоков. Перечислим основные:

  1. Метаданные самого файла SBOM: спецификация, уникальный номер, время генерации (метка времени);

  2. Перечень компонентов;

  3. Описание источника SBOM (блок externalReferences);

  4. Описание связей между компонентами (блок dependencies).

Спецификация SBOM достаточно обширная и гибкая, в ней можно увидеть дополнительные секции, а также добавить собственные.

Формат CycloneDX представляет собой файл JSON или XML. Выглядит он примерно так (JSON, инструмент cdxgen):

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "serialNumber": "urn:uuid:53b800be-812c-4d28-aca4-9a492cedd258",
  "version": 1,
  "metadata": {
    "timestamp": "2023-10-12T10:51:41.885Z",
    "tools": [
      {
        "vendor": "cyclonedx",
        "name": "cdxgen",
        "version": "8.6.0"
      }
    ],
    "authors": [
      {
        "name": "Prabhu Subramanian",
        "email": "prabhu@appthreat.com"
      }
    ],
    "component": {
      "author": "",
      "publisher": "",
      "group": "com.appsecco",
      "name": "dvja",
      "version": "1.0-SNAPSHOT",
      "description": "",
      "licenses": [],
      "purl": "pkg:maven/com.appsecco/dvja@1.0-SNAPSHOT?type=war",
      "type": "library",
      "bom-ref": "pkg:maven/com.appsecco/dvja@1.0-SNAPSHOT?type=war"
    }
  },
  "components": [
    {
      "author": "",
      "publisher": "Apache Software Foundation",
      "group": "org.apache.struts",
      "name": "struts2-core",
      "version": "2.3.30",
      "description": "Apache Struts 2",
      "scope": "required",
      "hashes": [
        {
          "alg": "MD5",
          "content": "e775580415dfa3a77e92f0ce6229268d"
        },
        {
          "alg": "SHA-1",
          "content": "0d2281c1a99f65b1ab19a5efd83a00a00995166d"
        },
        {
          "alg": "SHA-256",
          "content": "21161cc0b5056f34e0afca1feb42ebcc4bbcba0e2b075aa241c9be76b890fc65"
        },
        {
          "alg": "SHA-512",
          "content": "3a3c4083e8b0947f760f5f3d216450a62b7048247bc705939f255203ab721e343cd68d52233fb2240db3d8066435d922acf32a10c6cb28d132194c97d4025895"
        },
        {
          "alg": "SHA-384",
          "content": "ef2df3a2388461c384e842ee90eb4eabf562596aada15a784d7fc0c2ffc3b38915dd4cd1f2c896226501760b88e4ad64"
        },
        {
          "alg": "SHA3-384",
          "content": "655ee6e71047b5403957ab0c063b83a39294bae20cbe5cd72599d9c5371a03e05d6eabca5ae1a14a6d0e5eb08f00831c"
        },
        {
          "alg": "SHA3-256",
          "content": "46aaa149a8f9f0e2de483bb49c7932b9bd44d6416d3c572e46f89cc2d19a8c4f"
        },
        {
          "alg": "SHA3-512",
          "content": "1b39134ed5c8df0adffb610113b46c7b7fa51eeb1a9bad1159c16670f27931c772ca6e05576742c2dfd8f77a1e5940517adb194376811f2d7b97569fdb20c034"
        }
      ],
      "licenses": [
        {
          "license": {
            "id": "Apache-2.0"
          }
        }
      ],
      "purl": "pkg:maven/org.apache.struts/struts2-core@2.3.30?type=jar",
      "type": "framework",
      "bom-ref": "pkg:maven/org.apache.struts/struts2-core@2.3.30?type=jar"
    },
"dependencies": [
    {
      "ref": "pkg:maven/org.apache.struts/struts2-core@2.3.30?type=jar",
      "dependsOn": [
        "pkg:maven/org.apache.struts.xwork/xwork-core@2.3.30?type=jar",
        "pkg:maven/org.freemarker/freemarker@2.3.22?type=jar",
        "pkg:maven/ognl/ognl@3.0.19?type=jar",
        "pkg:maven/commons-fileupload/commons-fileupload@1.3.2?type=jar",
        "pkg:maven/commons-io/commons-io@2.2?type=jar"
      ]
    },
    {
      "ref": "pkg:maven/org.apache.commons/commons-lang3@3.2?type=jar",
      "dependsOn": []
    },
"externalReferences": [
    {
      "type": "other",
      "url": ".",
      "comment": "Base path"
    },
    {
      "type": "other",
      "url": "/home/kali/Downloads/dvja/pom.xml",
      "comment": "Package file"
    }
  ]
}

В components SBOM указывается автор пакета, purl (Package URL), лицензия, хэш библиотеки, CPE (Common Platform Enumeration) и другие компоненты.

Блок dependencies содержит название пакета из исходного кода и его зависимости, то есть пакеты, которые необходимы ему для работы. С помощью данных dependencies и названий библиотек можно построить граф зависимостей, в том числе транзитивных.

Это поле выглядит так (у первого компонента две зависимости, у второго – ни одной из-за отсутствия поля dependsOn):

{
      "ref": "pkg:npm/config-chain@1.1.13",
      "dependsOn": [
        "pkg:npm/ini@1.3.8",
        "pkg:npm/proto-list@1.2.4"
      ]
    },
    {
      "ref": "pkg:npm/core-util-is@1.0.2"
    },

Не все зависимости, описанные в файле манифеста, включаются в артефакт сборки. Одни нужны только для сборки пакета, другие – для теста. А третьи доступны в среде запуска приложения, но не становятся его частью.

Зачем SBOM нужен в сфере ИБ?

SBOM позволяет решить две связанные задачи:

  1. Инвентаризировать все использованные в продукте (исходном коде, артефакте, операционной системе) компоненты;

  2. Автоматизировать анализ их безопасности с помощью инструментов SCA (Software Composition Analysis). Политики безопасности могут включать в себя проверку этих компонентов на уязвимости и на лицензионную чистоту, а также на дату публикации, имя автора и другие элементы.

Решение обеих задач позволит снизить риск атаки на цепочку поставок ПО.

Практика SCA используется для анализа безопасности сторонних Open Source компонентов в приложении. Есть два подхода в работе инструментов SCA. В первом они самостоятельно сканируют исходный код, артефакт и файлы манифеста, перечень компонентов получают в виде SBOM или проприетарного формата (Dependency-Check). Во втором случае для работы инструментов SCA требуется уже собранный SBOM-файл (Dependency-Track).

С помощью инструментов SCA происходит поиск информации об уязвимостях в открытых базах данных по одному из двух идентификаторов библиотеки – CPE или purl. Если они сформированы некорректно, это может спровоцировать ложное срабатывание (False Positive) или его отсутствие (False Negative). Также анализируется хэш библиотеки, если есть опасения, что ее могут подменить или внести корректировки в исходный код. Данные из приведенных выше полей позволяют найти все актуальные уязвимости в открытых источниках.

Стоит отметить, что наличие уязвимой библиотеки в составе ПО еще не говорит о присутствии уязвимости, которую могли бы эксплуатировать злоумышленники. Для этого уязвимая функция должна быть достижима из кода, и никакие дополнительные меры безопасности не могут быть применены к данным, которые в такую функцию попадают. Большинство инструментов SCA не отвечают на вопрос о возможности эксплуатации, здесь требуется ревью AppSec-инженера или разработчика. Однако сейчас некоторые из инструментов уже начинают анализировать совместно и код, и набор библиотек, чтобы снизить количество False Positive срабатываний и объем ручной работы по их нахождению.

Какой инструмент выбрать для своих задач?

Для выбора инструмента, с которым вы будете работать, важно учесть следующие особенности проекта:

  1. Язык программирования, на котором написан ваш продукт;

  2. Файлы с транзитивными зависимостями, которые может сканировать каждый из инструментов (одни могут сканировать только файлы манифестов, такие как pom.xml или requirements.txt, другие – искать зависимости в большем числе файлов);

  3. Объект сканирования: репозиторий с исходным кодом, артефакт, Docker-образ, файловая система;

  4. Окружение: какой SCA-инструмент используется для сканирования, какой формат SBOM (CycloneDX, SPDX) и тип файла (XML, JSON) он может принять на вход;

  5. Цели: нужно искать зависимости только проекта или требуется также подтягивать сборочные и другие зависимости.

Как сформировать SBOM для исходного кода?

Существуют несколько инструментов генерации SBOM, подробнее со всеми можно ознакомиться на GitHub. Мы разберем самые популярные – Cdxgen, Trivy и Syft.

Инструмент

Cdxgen 10.1.0

Trivy 0.47

Syft 0.104.0

Ссылка

Cdxgen

Trivy

Syft

Написан на языке программирования

JavaScript

Go

Go

Информация о поддержке ЯП

Ссылка

Ссылка

Ссылка

Отслеживание лицензий

+

+

+

Создание дерева зависимостей

+

+

+

Формат SBOM

CycloneDX

CycloneDX, SPDX, KBOM in CycloneDX format

CycloneDX, SPDX, Syft’s
own format

Apk

-

-

+

C / C++

+/+

+/+

+/+

Clojure

+

-

-

Dart

+

+

+

Debian

+

-

+

.NET

+

+

+

Objective-C

+

-

+

Elixir

+

+

+

Erlang

-

-

+

Go

+

+

+

Haskell

+

-

+

Java

+

+

+

JavaScript

+

+

+

Perl

+

-

+

PHP

+

+

+

Python

+

+

+

R

-

-

+

Ruby

+

+

+

Rust

+

+

+

Swift

+

+

+

Docker

+

+

+

Cdxgen: установка и работа

Cdxgen – CLI-инструмент, написанный на JavaScript. Он позволяет собирать зависимости как определенного языка программирования, так и всего проекта. Cdxgen отличается тем, что умеет сканировать не только файлы манифестов, но и некоторые файлы исходного кода – это делает список найденных компонентов более обширным.

Источник – SBOM Benchmark
Источник – SBOM Benchmark

Бенчмарк указывает следующие недостатки по категориям требований:

  • NTIA-Minimum-Elements: отсутствует метка времени создания самого файла SBOM;

  • Quality: нет основной цели компонента и информации об истекших или неактуальных лицензиях;

  • Semantic: не всегда есть контрольные суммы компонентов;

  • Sharing: отсутствует информация о лицензии, под которой распространяется SBOM.

Установка cdxgen:

sudo npm install -g @cyclonedx/cdxgen

Запуск cdxgen для локального репозитория:

cdxgen -t <language> -o <output-file> --spec-version 1.4

-t (--type) – язык программирования репозитория (если не указывать этот параметр, то инструмент соберет вообще все зависимости, которые сможет. Взять можно здесь: https://github.com/CycloneDX/cdxgen#supported-languages-and-package-format);

-o (--output) – файл, в который нужно сохранить SBOM (в форматах XML, JSON);

--spec-version 1.4 – версия SBOM, с которой работают большинство инструментов;

--required-only – можно использовать для исключения сборочных зависимостей.

Включение cdxgen на запущенной операционной системе (в этом режиме найдет все пакеты ОС):

cdxgen -t os -o <output-file>

Запуск cdxgen для артефактов war:

cdxgen -t java app.war -o <output-file>

Таблица файлов, с которыми работает cdxgen версии 10.1.0:

Language/ Platform

Package format

Transitive dependencies

Node.js

npm-shrinkwrap.json, package-lock.json, pnpm-lock.yaml, yarn.lock, rush.js, bower.json, .min.js

Да, кроме .min.js

Java

maven (pom.xml), gradle (build.gradle, .kts), scala (sbt), bazel

Да, кроме случаев когда pom.xml парсится вручную из-за недоступности maven или ошибок

Android

apk, aab

PHP

composer.lock

Да

Python

pyproject.toml, setup.py, requirements.txt, Pipfile.lock, poetry.lock, pdm.lock, bdist_wheel, .whl, .egg-info

Да, при использовании автоматического pip install/freeze. Если отключено, только для Pipfile.lock и poetry.lock

Go

binary, go.mod, go.sum, Gopkg.lock

Да, кроме бинарных файлов

Ruby

Gemfile.lock, gemspec

Только для Gemfile.lock

Rust

binary, Cargo.toml, Cargo.lock

Только для Cargo.lock

.NET

.csproj, packages.config, project.assets.json, packages.lock.json, .nupkg, paket.lock

Только для project.assets.json, packages.lock.json, paket.lock

Dart

pubspec.lock, pubspec.yaml

Только для pubspec.lock

Haskell

cabal.project.freeze

Да

Elixir

mix.lock

Да

C/C++/ Objective C

conan.lock, conanfile.txt, *.cmake, CMakeLists.txt, meson.build, кодовые базы без пакетных менеджеров!

Да, только для conan.lock. Лучше всего для cmake без номеров версий.

Clojure

Clojure CLI (deps.edn), Leiningen (project.clj)

Да, если файлы не парсятся вручную из-за недостатков clojure cli или команды Leiningen

Swift

Package.resolved, Package.swift (swiftpm)

Да

Trivy: установка и работа

Trivy – CLI-инструмент, написанный на Go. Преимущество Trivy в том, что его можно скомпилировать в виде бинарного файла и запустить на любых системах и агентах CI/CD без дополнительных зависимостей. Инструмент работает как с удаленными git-репозиториями и файловыми системами, так и с Docker-образами, Kubernetes, виртуальными машинами и AWS.

Trivy может выводить информацию в виде SBOM или таблицы зависимостей с уязвимостями, поэтому важно указывать правильные параметры на вход для этого инструмента.

Источник – SBOM Benchmark
Источник – SBOM Benchmark

Бенчмарк указывает следующие недостатки по категориям требований:

  • NTIA-Minimum-Elements: отсутствует метка времени;

  • Quality: нет информации об истекших или неактуальных лицензиях, а также основной цели компонента;

  • Semantic: не всегда присутствуют контрольные суммы компонентов;

  • Sharing: нет информации о лицензии, под которой распространяется SBOM.

Установка Trivy из apt репозитория:

sudo apt-get install trivy

Больше информации по установке Trivy в зависимости от окружения можно найти на GitHub.  

Запуск Trivy для сканирования docker-образа:

trivy image --format cyclonedx --output <output-file> <image>

--format – формат SBOM;

--output – название файла SBOM.

Запуск Trivy для сканирования папки:

trivy fs --format cyclonedx --output <output-file> </path/to/dir>

Запуск Trivy для репозитория (локального или по URL):

Вывод в виде таблицы, в которой указаны только те зависимости, которые имеют уязвимости:

trivy repository -t json <url>

Создание файла в формате SBOM:

trivy repo --list-all-pkgs --format cyclonedx --output <output-file> <repository> 

--list-all-pkgs – параметр, который выводит все зависимости, несмотря на наличие уязвимостей. Подробнее на GitHub.

Таблица файлов, с которыми работает Trivy версии 0.47:

Language

File

Image

Rootfs

Filesystem

Repository

Ruby

Gemfile.lock

-

-

+

+

Gemspec

+

+

-

-

Python

Pipfile.lock

-

-

+

+

poetry.lock

-

-

+

+

requirements.txt

-

-

+

+

egg package

+

+

-

-

wheel package

+

+

-

-

conda package

+

+

-

-

PHP

composer.lock

+

+

+

+

Node.js

package-lock.json

-

-

+

+

yarn.lock

-

-

+

+

pnpm-lock.yarn

-

-

+

+

package.json

+

+

-

-

.NET

packages.lock.json

+

+

-

-

packages.config

+

+

+

+

.deps.json

+

+

+

+

Java

JAR/WAR/PAR/EAR

+

+

-

-

pom.xml

-

-

+

+

*gradle.lockfile

-

-

+

+

Go

Binaries built by Go

+

+

-

-

go.mod

-

-

+

+

Rust

Cargo.lock

+

+

+

+

Binaries built with cargo-auditable

+

+

-

-

C/C++

conan.lock

-

-

+

+

Elixir

mix.lock

-

-

+

+

Dart

pubspec.lock

-

-

+

+

Swift

Podfile.lock

-

-

+

+

Package.resolved

-

-

+

+

Syft: установка и работа

Syft – CLI-инструмент для создания SBOM. Он может сканировать как файловые системы, так и образы контейнеров.

Источник – SBOM Benchmark
Источник – SBOM Benchmark

Бенчмарк указывает следующие недостатки по категориям требований:

  • NTIA-Minimum-Elements: отсутствует метка времени;

  • Quality: закрыто почти полностью за счет множества CPE для одного пакета и отдельного поля evidence;

  • Semantic: не всегда присутствуют контрольные суммы компонентов, структура SBOM не совсем удобна;

  • Sharing: нет информации о лицензии, под которой распространяется SBOM.

Установка Syft из apt репозитория:

sudo apt-get install syft

Запуск Syft на docker-образе:

syft --output cyclonedx-json=<output-file.json> <image>

--output - формат вывода и название генерируемого SBOM-файла;

Запуск Syft для .tar-архива docker-образа:

syft --output cyclonedx-json=<output-file.json> <path/to/image>.tar

Запуск Syft для .sif контейнера:

syft --output cyclonedx-json=<output-file.json> <path/to/image>.sif

Запуск Syft для репозитория в папке:

syft --output cyclonedx-json==<output-file.json> dir:<path/to/dir>

Таблица файлов, с которыми работает Syft версии 0.104.0:

Language/Platform

Image

Directory

Node.js

javascript-package

javascript-lock

Java

apkdb

java

graalvm-native-image

Java

java-pom

java-gradle-lockfile

graalvm-native-image

PHP

php-composer-installed

php-composer-lock

Python

python-package

python-index

python-package

Go

Alpmdb

go-module-binary

Alpmdb

go-mod-file

go-module-binary

Ruby

ruby-gemspec

ruby-gemfile

Rust

-

rust-cargo-lock

cargo-auditable-binary (non-default)

.NET

dotnet-deps

dotnet-deps

Dart

-

dartlang-lock

Haskell

-

Haskell

Elixir

-

elixir-mix-lock

Erlang

-

erlang-rebar-lock

C/C++/Objective C

-

cocoapods, conan

Swift

-

swift-package-manager

Other

apkdb

binary

linux-kernel

nix-store

sbom

rpm-db

portage

dpkgdb

apkdb

binary

dpkgdb

linux-kernel

nix-store

rpm-db

rpm-file

portage

sbom

Заключение

Спецификация ПО играет важную роль в практике SCA. SBOM контролирует все компоненты, которые используются в исходном коде, и автоматизирует проверку их защищенности – это позволяет разработчикам быстрее обнаруживать и устранять проблемы безопасности. Поэтому создавать и поддерживать SBOM сегодня полезно всем компаниям.

Надеемся, что эта статья поможет выбрать инструмент генерации SBOM под ваши нужды и благодаря этому повысить безопасность ваших продуктов.

Теги:
Хабы:
Всего голосов 4: ↑3 и ↓1+4
Комментарии1

Публикации

Информация

Сайт
swordfish-security.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
SwordfishTeam