С ростом сообщества Go все больше и больше пакетов с открытым ПО становились причиной возникновения уязвимостей безопасности. Такая тенденция вызвала озабоченность официальных представителей Go, вследствие чего в сентябре 2022 года был представлен инструмент сканирования безопасности Go Vulnerability Check (Проверка уязвимостей Go) — govulncheck
.
Если вы заинтересовались данным инструментом, то просто продолжайте изучение материала: далее мы проанализируем его внутреннюю логику и в полной мере воспользуемся его преимуществами.
Применение инструмента для проверки уязвимостей Go (govulncheck)
Приступаем к испытанию данного инструмента.
Устанавливаем (поддерживается только с версии Go 1.18):
go install golang.org/x/vuln/cmd/govulncheck@latest
Запускаем в каталоге проекта, в котором находится файл go.mod
:
govulncheck ./...
В качестве демо воспользуемся одним из моих проектов Kubernetes Operator. В отчете отображены две уязвимости.
- Сканирование зависимостей с известными уязвимостями. Речь идет об уязвимостях в коде проекта, например в текущей версии Go. Такого рода проблемы решаются путем обновления Go.
Сканирование зависимостей с известными уязвимостями. Обнаружено 3 известных уязвимости.
Уязвимость # 1: GO-2022–0236
Вредоносный HTTP-сервер или клиент способны нарушить работу net/http
клиента или сервера и сгенерировать панику (англ. panic). ReadRequest
и ReadResponse
могут привести к необратимой панике при чтении слишком длинного заголовка, превышающего 7 МБ на 64-битных архитектурах или 4 МБ на 32-битных. Transport
и Client
уязвимы, и вредоносный сервер может вызвать дисфункцию программы. По умолчанию сервер не является уязвимым, но может таким стать, если переопределить максимальный размер заголовка по умолчанию в 1 МБ, установив более высокое значение для Server.MaxHeaderBytes
. В этом случае сбой программы может быть вызван вредоносным клиентом. Это также затрагивает golang.org/x/net/http2/h2c
и HeaderValuesContaintsToken
в golang.org/x/net/http/httpguts
.
- Нижеследующие уязвимости содержатся в импортируемых пакетах. Они представляют собой уязвимости в зависимостях проекта и устраняются путем обновления соответствующих зависимостей пакетов.
Нижеследующие уязвимости содержатся в импортируемых пакетах, однако каких-либо вызовов уязвимых функций в коде не наблюдается. Возможно, вам не потребуется предпринимать каких-либо действий. Более подробная информация предоставлена по указанной ссылке.
Уязвимость # 1: GO-2022–0969
Соединения сервера HTTP/2 могут надолго зависнуть в ожидании чистого закрытия системы, прерванного критической ошибкой. Этим состоянием может воспользоваться вредоносный клиент, чтобы спровоцировать отказ в работе сервиса.
В обоих случаях выводятся следующие сведения об уязвимостях:
- количество обнаруженных уязвимостей;
- точная информация по каждой уязвимости, включая дату предоставления данных, подробное описание и ссылка на соответствующие отчеты;
- конкретный код, где обнаружена уязвимость, например с указанием метода и строки;
- версия, содержащая уязвимость, и исправленная версия.
Запуск govulncheck в CI/CD
Для большей эффективности следует интегрировать инструмент в конвейер CI/CD. С этой целью экспортируем результат файла JSON
и задействуем флаг -json
:
govulncheck -json ./...
Файл JSON
— это подробный вывод, включающий процесс и результаты сканирования, а также записи вызовов:
Calls
— проверка, связанная с нативным кодом; Imports
— проверка зависимостей; Vulns
— проверка результатов.
Для jq '.Vulns | length'
устанавливаем != 0
. Для текущего оператора помещаем соответствующую оболочку bash
в Makefile
и запускаем в CI/CD.
vuln
также поддерживает тестирование двоичных файлов, заменяя ./…
на имя нужного файла. Кроме того, при интеграции в CI/CD vuln
применяется для обнаружения уязвимостей в проектах Go, содержащих только Docker-образы.
Проверка тестового кода
vuln
не проверяет тестовый код по умолчанию. Однако просканировать тестовые файлы можно с помощью:
-test flag govulncheck -test pkg/test/*
Внутренний механизм govulncheck
Инструмент vuln
запускает инструмент командной строки и считывает базу данных vuln
для анализа файла go.mod
и кода Go. Таким образом, он в основном состоит из двух частей:
- разработка инструмента командной строки
vuln
; - обслуживание базы данных
vulndb
.
Инструмент командной строки Vuln
Как правило, чтение кода инструмента командной строки начинается с места определения командной строки. Процесс простой и включает в себя 5 шагов для проверки исходного кода:
- чтение и настройка клиента базы данных;
- загрузка конфигурации;
- чтение исходного кода и последовательности;
- обнаружение;
- обработка результатов.
Основу составляет метод vulncheck.source()
:
Source
обнаруживает уязвимости в пакетах. Результат включает:
ImportGraph
, связанный с импортом пакета, который содержит известные уязвимости.RequireGraph
, связанный с требованием модуля, который включает пакет с известными уязвимостями.CallGraph
, приводящий к использованию известной уязвимой функции или методу.
Следует создать графы import
и require
по отдельности, затем выполнить сканирование. import
нужен для того, что используется в текущем коде, тогда как require
связан с зависимыми пакетами, которые не задействуются напрямую.
База данных Vuln
vulndb
содержит всю информацию об уязвимостях, синхронизирует ряд других библиотек уязвимостей с открытым ПО и включает уязвимости, обнаруженные сообществом, с тикетами от пользователей. Посмотреть все интересующие вас уязвимости можно по этой ссылке.
Подробное описание каждой уязвимости состоит из 6 атрибутов.
Организованный набор данных. Команда безопасности Go Security активно обслуживает базу данных, поэтому она предоставляет согласованные метаданные и единообразный анализ выявленных уязвимостей, обеспечивая возможность не только обнаружения, но и точной оценки последствий.
Основные метаданные. Записи включают уникальный идентификатор базы данных для уязвимости, диапазон затронутых пакетов и версий, приблизительную степень серьезности и по необходимости
GOOS
/GOARCH
. Уязвимости также присваивается номер CVE (англ. Common Vulnerabilities and Exposures, т.е. известные уязвимости и дефекты безопасности).
Целевые метаданные. Каждая запись базы данных включает метаданные, достаточные для обнаружения затронутых нисходящих приложений с низким уровнем ложноположительных срабатываний. Например, такая запись содержит затронутые символы (функции, методы, типы, переменные…), позволяя с помощью статического анализа определить незатронутые объекты-получатели.
Веб-страницы. Каждая уязвимость содержит ссылку на веб-страницу с описанием уязвимости, инструкциями по устранению и дополнительными ссылками.
Единый источник истины. База данных обслуживается как публичный git-репозиторий, по аналогии с другими репозиториями Go. Записи базы данных доступны через устоявшийся протокол. Содержимое самого репозитория находится во внутреннем формате, который может меняться без уведомления.
Процесс отбора. Потенциальные записи поступают из существующих потоков (таких как база данных CVE и списки рассылки по безопасности), а также из материалов, предоставляемых сообществом. Для обеспечения согласованности метаданных и анализа все полученные сведения обрабатываются командой. Специалистам по обслуживанию настоятельно рекомендовано сообщать об уязвимостях, обнаруженных в своих модулях.
В процессе реализации vulndb
также предоставляет набор команд cmd
для обслуживания базы данных, онлайн-верификации и т.д. Например, команда worker
локально запускает сервер и сканирует файлы в Git:
Команда cve
запрашивает и обновляет данные об уязвимости, вызывая HTTP-запросы для получения соответствующей информации.
Мы можем скачать код vulndb
и командой git clone
клонировать этот репозиторий, после чего протестировать и локально выполнить все эти команды через скрипт в devtools
.
Альтернативные варианты
vuln
— это официальный продукт Go, который по прогнозам приобретет популярность в ближайшем будущем. Тем не менее отметим ряд его недостатков.
vuln
— это всего лишь экспериментальный инструмент.- Он поддерживает проверки двоичного кода, только начиная с версии Go
1.18
и выше. vuln
обнаруживает уязвимости только в текущей версии Go. Например, если вы обновляете Go до последней версии1.19
, то перестаете получать отчеты об уязвимостях зависимостей в версии1.18
.- Ограниченный метод вывода. Вывод
JSON
отличается чрезмерной сложностью, аtext
предназначен только для локальной среды. Например, формат итогового вывода в исходном коде поддерживает только среду разработки и тестирования. vuln
возвращает ложноположительные и неточные отчеты стека при сканировании интерфейсов и указателей на функции.
Не стоит зацикливаться на vuln
. Почему бы не рассмотреть другие инструменты сканирования безопасности зависимостей Go в ожидании его улучшения? В настоящее время наиболее известные из них — это Github security dependency scan (Сканирование зависимостей на уязвимости безопасности GitHub) и gosec.
Инструмент сканирования безопасности зависимостей GitHub
Применительно к Go-проектам с открытым исходным кодом на GitHub мы можем выполнять регулярные сканирования зависимостей, активируя в настройках Dependabot alerts
:
Инструмент сканирования безопасности GitHub поддерживает ежедневные и еженедельные отчеты о сканировании по электронной почте и в уведомлениях GitHub. Он также предоставляет горячие клавиши для исправлений одним кликом, что идеально подходит для Go-проектов с открытым исходным кодом.
Инструмент gosec
Инструмент gosec
очень похож на vuln
. Они оба являются инструментами командной строки и сканируют уязвимости Go по схожим правилам.
Действующие правила
- G101: Поиск жестко заданных учетных данных.
- G102: Привязка ко всем интерфейсам.
- G 103: Аудит использования небезопасного блока.
- G 104: Аудит непроверенных ошибок.
- G 106: Аудит использования
ssh.InsecureIgnoreHostKey
. - G 107: Url, указанный в HTTP-запросе в качестве “зараженных” (англ. taint) входных данных.
- G 108: Конечная точка профилирования, автоматически отображаемая в /debug/pprof.
- G 109: Потенциальное целочисленное переполнение, вызванное преобразованием результата
strconv.Atoi
вint16/32
. - G 110: Потенциальная DoS-уязвимость через декомпрессионную бомбу.
- G 111: Потенциальный обход каталога.
- G 112: Потенциальная атака
slowloris
. - G 113: Использование
Rat.SetString
вmath
/big
c переполнением (CVE-2022–23772). - G 114: Использование функции
serve
пакетаnet/http
, которая не поддерживает установку тайм-аутов. - G 201: Построение SQL-запроса с использованием формата
string
. - G 202: Построение SQL-запроса с использованием конкатенации строк.
- G 203: Применение неэкранированных данных в HTML- шаблонах.
- G 204: Аудит использования выполнения команд.
- G 301: Некорректные права доступа к файлам, применяемые для создания каталогов.
- G 302: Некорректные права доступа к файлам, применяемые с
chmod
. - G 303: Создание временного файла с использованием прогнозируемого пути.
- G 304: Путь к файлу, предоcтавляемый в качестве “зараженных” входных данных.
- G 305: Обход файлов при распаковке архива
zip
/tar
. - G 306: Некорректные права доступа к файлам при записи в новый файл.
- G 307: Откладывание метода, который возвращает ошибку.
- G 401: Обнаружение случаев применения DES, RC4, MD5 , SHA1.
- G 402: Поиск некорректных настроек TLS-соединений.
- G 403: Обеспечение минимальной длины ключа RSA в 2048 бит.
- G 404: Небезопасный генератор случайный чисел (
rand
). - G 501: Импорт списка блокировки: crypto/md5.
- G 502: Импорт списка блокировки: crypto/des.
- G 503: Импорт списка блокировки: crypto/rc4.
- G 504: Импорт списка блокировки: net/http/cgi.
- G 505: Импорт списка блокировки: crypto/sha1.
- G 601: Неявные конфликты в доступе к элементам в памяти из инструкции
range
.
Но gosec
поддерживает все версии Go и предоставляет больше вариантов операций, например сканирование определенных правил, сканирование конфигурационных файлов и выходные отчеты в разных форматах, таких как JSON
, YAML
, CSV
.
Скажем так, на данный момент gosec
более разработан по сравнению с vuln
, которому есть куда совершенствоваться.
Заключение
С развитием Go и возросшим числом проблем безопасности актуальным становится тщательный отбор зависимостей и их систематическое обновление. Однако реализация этой задачи представляет определенную сложность при необходимости регулярных обновлений пул-реквестов и слияния (англ. merge), которые игнорируются некоторыми пользователями. Решение заключается в сканировании зависимостей, которое вынуждает пользователей проводить обновления в результате сбоя сборки непосредственно в CI/CD.
Что касается инструмента vuln
, его ждет дальнейшая оптимизация и усовершенствование.
Читайте также:
- Go: стратегия встраивания и ограничение
- 5 причин грядущего господства Go в мире программирования
- Структурированное логирование JSON в приложениях на Golang
Читайте нас в Telegram, VK и Дзен
Перевод статьи Stefanie Lai: Secure Your Go Code With Vulnerability Check Tool