Статья Программирование. Кибербезопасность + Go = ❤️

Всем привет! Подготовил для вас материал по топу библиотек на Golang, которые необходимы вам при безопасной разработке приложений. Топ будет составлен лично по моему мнению, а я не являюсь сеньором-помидором Go разработчиком, так что не кидайтесь гнилыми тапками.

banner.jpg

1. Lego

lego.png


Данная библиотека выполняет функцию клиента Let's Encrypt'а и библиотеки ACME.

Возможности библиотеки:

  • ACME v2
  • Регистрация с помощью центра сертификации
  • Получение сертификатов, как с нуля, так и с помощью существующего CSR
  • Перевыпуск сертификата
  • Отозвать сертификат:
    • Надежная реализация всех задач ACME
    • HTTP (http-01)
    • DNS (dns-01)
    • TLS (tls-alpn-01)
  • Поддержка сертификата SAN
  • Поставляется с несколькими дополнительными
  • Объединение сертификатов
  • Вспомогательная функция OCSP
Установка:
  • Из исполняемого файла
  • Docker
    • Bash:
      docker run goacme/lego -h
  • Пакетные менеджеры
    • Arch Linux -
      Bash:
      pacman -S lego
    • ArchLinux (AUR) -
      Bash:
      yay -S lego-bin
    • Debian -
      Bash:
      sudo apt install -y lego
  • Из сорцов
    • Bash:
      go install github.com/go-acme/lego/v4/cmd/lego@latest
    • Bash:
      git clone git@github.com:go-acme/lego.git
      cd lego
      make        # tests + doc + build
      make build  # only build

Данная библиотека имеет 2 варианта использования:​

1. CLI

Далее я расскажу вам, как использовать Lego для выпуска сертификатов:

Использовать встроенный веб-сервер
Bash:
lego --email="you@example.com" --domains="example.com" --http run

Вы найдете ваш сертификат в текущей рабочей директории, в папке .lego
Bash:
$ ls -1 ./.lego/certificates
example.com.crt
example.com.issuer.crt
example.com.json
example.com.key
[maybe more files for different domains...]

Разбор значений файлов:
  • example.com.crt - сертификат сервера (включая сертификат УЦ)
  • example.com.key - закрытый ключ, необходимый для сертификата сервера
  • example.com.issuer.crt - сертификат удостоверяющего центра
  • example.com.json - содержит некоторую метаинформацию в кодировке JSON

Использовать DNS провайдеров
Если вы не можете использовать веб сервер, то у вас есть возможность использовать DNS провайдеров. В Lego и вы сами можете выбрать, каким из них пользоваться. Для примеру покажу, как использовать Cloudflare для вашего домена:
Bash:
CLOUDFLARE_EMAIL="you@example.com" \
CLOUDFLARE_API_KEY="yourprivatecloudflareapikey" \
lego --email "you@example.com" --dns cloudflare --domains "example.org" run

Использовать кастомный запрос на подпись сертификата
Первый шаг в процессе получения сертификатов включает в себя создание запроса на подписание. Этот CSR содержит различную информацию, включая имя (имена) домена и открытый ключ. По умолчанию lego скроет от вас этот шаг, но если у вас уже есть CSR, вы можете легко использовать его повторно:
Bash:
lego --email="you@example.com" --http --csr="/path/to/csr.pem" run
Lego сделает вывод о доменах, подлежащих проверке, на основе содержимого CSR, поэтому убедитесь, что общее имя CSR и необязательные SubjectAltNames установлены правильно.

Использовать уже существующий веб сервер
Если у вас уже есть работающий веб сервер на 80 порту, вам нужно добавить --http.webroot к аргументу --http. Это действие просто записывает токен вызова http-01 в указанный каталог в папку .well-known/acme-challenge и не запускает сервер. Для завершения проверки, директория должна быть / и доступна публично. Далее Lego запишет файл токенов с ключом авторизации HTTP-01 challenge в <webroot>/.well-known/acme-challenge/. Для этого выполните следующую команду:
Bash:
lego --accept-tos --email you@example.com --http --http.webroot /path/to/webroot --domains example.com run

Использовать скрипты
Вы можете легко подключиться к процессу получения сертификата, указав путь к скрипту:
Bash:
lego --email="you@example.com" --domains="example.com" --http run --run-hook="./myscript.sh"
И давайте объясню используемые переменные:
  • LEGO_ACCOUNT_EMAIL - электронная почта аккаунта
  • LEGO_CERT_DOMAIN - основной домен сертификата
  • LEGO_CERT_PATH - путь к сертификату
  • LEGO_CERT_KEY_PATH - путь к ключу сертификата

Теперь я вам расскажу вам как пользоваться ей для обновления сертификатов:

Использовать встроенный веб сервер
По умолчанию и в соответствии с классической практикой сертификат обновляется только в том случае, если срок его действия истекает менее чем через 30 дней.
Bash:
lego --email="you@example.com" --domains="example.com" --http renew

Если сертификат нужно перевыпустить ранее, вы можете указать количество дней за сколько выпустить его.
Bash:
lego --email="you@example.com" --domains="example.com" --http renew --days 45

Использовать DNS провайдера
Ранее я уже освещал о возможностях Lego в этом направлении, если что-то не понятно, то советую перечитать информацию выше)
Bash:
CLOUDFLARE_EMAIL="you@example.com" \
CLOUDFLARE_API_KEY="yourprivatecloudflareapikey" \
lego --email "you@example.com" --dns cloudflare --domains "example.org" renew

Использовать скрипты
Bash:
lego --email="you@example.com" --domains="example.com" --http renew --renew-hook="./myscript.sh"

Автоматический перевыпуск сертификата:
Очень заманчиво создать таск в cron (или таймер systemd) для автоматического обновления всех ваших сертификатов.
При этом следует учитывать, что некоторые настройки cron по умолчанию будут создавать ощутимую нагрузку на инфраструктуру провайдера ACME. В частности, задания @daily запускаются в полночь.

Пример оптимизированного таска для cron
Bash:
# avoid:
#@daily      /usr/bin/lego ... renew
#@midnight   /usr/bin/lego ... renew
#0 0 * * *   /usr/bin/lego ... renew

# instead, use a randomly chosen time:
35 3 * * *  /usr/bin/lego ... renew

Если вы используете systemd, то вот пример конфиг файла для вас:
Bash:
[Unit]
Description=Renew certificates

[Timer]
Persistent=true
# avoid:
#OnCalendar=*-*-* 00:00:00
#OnCalendar=daily

# instead, use a randomly chosen time:
OnCalendar=*-*-* 3:35
# add extra delay, here up to 1 hour:
RandomizedDelaySec=1h

[Install]
WantedBy=timers.target

2. Второй вариант использования Lego, напрямую как библиотеки

Правильный, но неполный пример использования пакета acme:

Код:
package main

import (
    "crypto"
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "fmt"
    "log"

    "github.com/go-acme/lego/v4/certcrypto"
    "github.com/go-acme/lego/v4/certificate"
    "github.com/go-acme/lego/v4/challenge/http01"
    "github.com/go-acme/lego/v4/challenge/tlsalpn01"
    "github.com/go-acme/lego/v4/lego"
    "github.com/go-acme/lego/v4/registration"
)

// You'll need a user or account type that implements acme.User
type MyUser struct {
    Email        string
    Registration *registration.Resource
    key          crypto.PrivateKey
}

func (u *MyUser) GetEmail() string {
    return u.Email
}
func (u MyUser) GetRegistration() *registration.Resource {
    return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
    return u.key
}

func main() {

    // Create a user. New accounts need an email and private key to start.
    privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    if err != nil {
        log.Fatal(err)
    }

    myUser := MyUser{
        Email: "you@yours.com",
        key:   privateKey,
    }

    config := lego.NewConfig(&myUser)

    // This CA URL is configured for a local dev instance of Boulder running in Docker in a VM.
    config.CADirURL = "http://192.168.99.100:4000/directory"
    config.Certificate.KeyType = certcrypto.RSA2048

    // A client facilitates communication with the CA server.
    client, err := lego.NewClient(config)
    if err != nil {
        log.Fatal(err)
    }

    // We specify an HTTP port of 5002 and an TLS port of 5001 on all interfaces
    // because we aren't running as root and can't bind a listener to port 80 and 443
    // (used later when we attempt to pass challenges). Keep in mind that you still
    // need to proxy challenge traffic to port 5002 and 5001.
    err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "5002"))
    if err != nil {
        log.Fatal(err)
    }
    err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "5001"))
    if err != nil {
        log.Fatal(err)
    }

    // New users will need to register
    reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
    if err != nil {
        log.Fatal(err)
    }
    myUser.Registration = reg

    request := certificate.ObtainRequest{
        Domains: []string{"mydomain.com"},
        Bundle:  true,
    }
    certificates, err := client.Certificate.Obtain(request)
    if err != nil {
        log.Fatal(err)
    }

    // Each certificate comes back with the cert bytes, the bytes of the client's
    // private key, and a certificate URL. SAVE THESE TO DISK.
    fmt.Printf("%#v\n", certificates)

    // ... all done.
}

Далее описывать функции библиотеки = переписать документацию. .


2. zap

zap_logger.jpg

Обратите внимание, что zap поддерживает только две последние версии Go.
Zap - сверхбыстрое, структурированное, уровневое логгирование в Go

Установка​

Bash:
go get -u go.uber.org/zap

Использование​

В ситуациях, когда производительность важна, но не критична, используйте SugaredLogger. Он в 4-10 раз быстрее других пакетов структурированного протоколирования и включает в себя как структурированный, так и printf-стиль API.
Код:
logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
  // Structured context as loosely typed key-value pairs.
  "url", url,
  "attempt", 3,
  "backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", url)

Если важны производительность и безопасность типов, используйте Logger. Он даже быстрее, чем SugaredLogger, и выделяет гораздо меньше ресурсов, но поддерживает только структурированное логгирование.
Код:
logger, _ := zap.NewProduction()
defer logger.Sync()
logger.Info("failed to fetch URL",
  // Structured context as strongly typed Field values.
  zap.String("url", url),
  zap.Int("attempt", 3),
  zap.Duration("backoff", time.Second),
)

Для приложений, которые ведут журнал realtime, сериализация на основе отражения и форматирование строк непомерно дороги - они сильно нагружают процессор и делают много небольших выделений. Другими словами, использование encoding/json и fmt.Fprintf для регистрации тонн interface{}s делает ваше приложение непростительно медленным.
Zap использует другой подход. Он включает кодировщик JSON без отражений, с нулевым распределением, а базовый логгер стремится избегать накладных расходов на сериализацию и выделения, где это возможно. Создавая на этой основе высокоуровневый SugaredLogger, zap позволяет пользователям выбирать, когда им нужно считать каждое выделение, а когда они предпочитают более привычный, свободно типизированный API.

По оценкам собственного пакета бенчмарков, zap не только более производителен, чем аналогичные пакеты структурированного логгирования, но и быстрее, чем стандартная библиотека.
1683289418356.png


3. gosec

gosec.png


Данная библиотека проверяет исходный код на наличие проблем безопасности путем сканирования Go AST (Abstract Syntax Tree).

Установка порадует DevSecOps


CI установка

Bash:
curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $(go env GOPATH)/bin vX.Y.Z

curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s vX.Y.Z

# для Alpine Linux, где по умолчанию нет curl
wget -O - -q https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s vX.Y.Z

gosec --help

GitHub Action

Git:
name: Run Gosec
on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master
jobs:
  tests:
    runs-on: ubuntu-latest
    env:
      GO111MODULE: on
    steps:
      - name: Checkout Source
        uses: actions/checkout@v3
      - name: Run Gosec Security Scanner
        uses: securego/gosec@master
        with:
          args: ./...

Локальная установка

Go 1.16+​

Код:
go install github.com/securego/gosec/v2/cmd/gosec@latest

Go version < 1.16​

Код:
go get -u github.com/securego/gosec/v2/cmd/gosec

Использование

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

Доступные правила аудита

  • G101: Look for hard coded credentials
  • G102: Bind to all interfaces
  • G103: Audit the use of unsafe block
  • G104: Audit errors not checked
  • G106: Audit the use of ssh.InsecureIgnoreHostKey
  • G107: Url provided to HTTP request as taint input
  • G108: Profiling endpoint automatically exposed on /debug/pprof
  • G109: Potential Integer overflow made by strconv.Atoi result conversion to int16/32
  • G110: Potential DoS vulnerability via decompression bomb
  • G111: Potential directory traversal
  • G112: Potential slowloris attack
  • G113: Usage of Rat.SetString in math/big with an overflow (CVE-2022-23772)
  • G114: Use of net/http serve function that has no support for setting timeouts
  • G201: SQL query construction using format string
  • G202: SQL query construction using string concatenation
  • G203: Use of unescaped data in HTML templates
  • G204: Audit use of command execution
  • G301: Poor file permissions used when creating a directory
  • G302: Poor file permissions used with chmod
  • G303: Creating tempfile using a predictable path
  • G304: File path provided as taint input
  • G305: File traversal when extracting zip/tar archive
  • G306: Poor file permissions used when writing to a new file
  • G401: Detect the usage of DES, RC4, MD5 or SHA1
  • G402: Look for bad TLS connection settings
  • G403: Ensure minimum RSA key length of 2048 bits
  • G404: Insecure random number source (rand)
  • G501: Import blocklist: crypto/md5
  • G502: Import blocklist: crypto/des
  • G503: Import blocklist: crypto/rc4
  • G504: Import blocklist: net/http/cgi
  • G505: Import blocklist: crypto/sha1
  • G601: Implicit memory aliasing of items from a range statement

Выбор правил аудита

По умолчанию gosec будет выполнять все правила по указанным путям к файлам. Однако можно выбрать группы правил для запуска с помощью флага -include= или указать группы правил для явного исключения с помощью флага -exclude=.
Bash:
# Запуситить конкретные правила
$ gosec -include=G101,G203,G401 ./...

# Использовать все правила, кроме G303
$ gosec -exclude=G303 ./...

CWE Mapping

Это уже порадует безопасников, т.к. каждая проблема соотноситься с , которая описывает уязвимость.

Исключения:

Исключение тестовых файлов и папок при аудите

gosec будет игнорировать тестовые файлы всех пакетов и любых зависимостей в вашем каталоге.
Сканирование тестовых файлов может быть включено с помощью следующего флага:
Код:
gosec -tests ./...
Также можно исключить дополнительные папки следующим образом:
Код:
gosec -exclude-dir=rules -exclude-dir=cmd ./...

Исключение сгенерированных файлов

gosec может игнорировать сгенерированные go-файлы с комментарием сгенерированного кода по умолчанию.

// Code generated by some generator DO NOT EDIT.
Код:
gosec -exclude-generated ./...

Сохранение результатов

В настоящее время gosec поддерживает форматы вывода text, json, yaml, csv, sonarqube, JUnit XML, html и golint. По умолчанию результаты выводятся на stdout(т.е. в консоль), но также могут быть записаны в файл. Формат вывода контролируется флагом -fmt, а имя файла устанавливается флагом -out следующим образом:
Bash:
# Запись результатов в json в файл results.json
$ gosec -fmt=json -out=results.json *.go
Также вы можете сохранить результат и в файлы, и вывести в консоль:
Bash:
$ gosec -fmt=json -out=results.json -stdout *.go

4. Hydra

hydra_oauth.png


Ory Hydra - это усиленный, сертифицированный OpenID OAuth 2.0 сервер и провайдер OpenID Connect, оптимизированный для низкой задержки, высокой пропускной способности и низкого потребления ресурсов. Ory Hydra не является провайдером идентификации (регистрация пользователя, вход пользователя, поток сброса пароля), а подключается к существующему провайдеру идентификации через приложение для входа и согласия.
Ory Hydra может использовать Ory Kratos в качестве сервера идентификации.

Ory Hydra - это серверная реализация системы авторизации OAuth 2.0 и OpenID Connect Core 1.0. Существующие реализации OAuth2 обычно поставляются в виде библиотек или SDK, таких как node-oauth2-server или Ory Fosite, или в виде полнофункциональных решений идентификации с управлением пользователями и пользовательскими интерфейсами, таких как Keycloak. Внедрение и использование OAuth2 без понимания всей спецификации является сложной задачей и чревато ошибками, даже если используются SDK. Основная цель Ory Hydra - сделать OAuth 2.0 и OpenID Connect 1.0 более доступными.
Самых крупные компании, использующие Hydra вы можете увидеть здесь.

Начнём с установки. Есть 2 стула:


  1. Docker - установка займет 5 минут. Гайд .
  2. Для настоящих мужчин

Bash:
# Linux
bash <(curl https://raw.githubusercontent.com/ory/meta/master/install.sh) -b . ory
sudo mv ./ory /usr/local/bin/

# MacOS
brew install ory/tap/cli

Далее создаем проект:
Код:
ory create project --name "Ory Hydra 2.0 Example"
project_id="{set to the id from output}"

OAuth 2.0 Client Credentials / Machine-to-Machine

Создайте клиент OAuth 2.0 и запустите процесс OAuth 2.0 Client Credentials:
Bash:
ory create oauth2-client --project $project_id \
    --name "Client Credentials Demo" \
    --grant-type client_credentials
client_id="{set to client id from output}"
client_secret="{set to client secret from output}"

ory perform client-credentials --client-id=$client_id --client-secret=$client_secret --project $project_id
access_token="{set to access token from output}"

ory introspect token $access_token --project $project_id

OAuth 2.0 Authorize Code + OpenID Connect

Bash:
ory create oauth2-client --project $project_id \
    --name "Authorize Code with OpenID Connect Demo" \
    --grant-type authorization_code,refresh_token \
    --response-type code \
    --redirect-uri http://127.0.0.1:4446/callback
code_client_id="{set to client id from output}"
code_client_secret="{set to client secret from output}"

ory perform authorization-code \
    --project $project_id \
    --client-id $code_client_id \
    --client-secret $code_client_secret
code_access_token="{set to access token from output}"

ory introspect token $code_access_token --project $project_id

5. TFSec

tfsec.png


tfsec использует статический анализ кода terraform для выявления возможных мисконфигов.

Начнем с установки

Установка с помощью
Код:
brew install tfsec

Установка с помощью
Код:
choco install tfsec

Установка с помощью
Код:
scoop install tfsec

Установка в Linux:
Код:
curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash

Также вы можете скачать бинарь с releases page.

Также вы можете установить из исходников с помощью Go:
Код:
go install github.com/aquasecurity/tfsec/cmd/tfsec@latest

Использование

Тут довольно всё просто) tfsec будет сканировать указанный каталог. Если каталог не указан, будет использоваться текущий рабочий каталог.
Bash:
tfsec .

Использовать через Docker

В качестве альтернативы установке и запуску tfsec на вашей системе, вы можете запустить tfsec в контейнере Docker:

Название образаОбразОписание
alpineОбычный tfsec образ
alpineТочно так же, как aquasec/tfsec, но для тех, кто любит ясность.
alpinetfsec без entrypoint- полезно для сборок CI, где вы хотите переопределить команду
scratchОбраз, созданный с нуля - ничего лишнего, просто работает tfsec

Bash:
docker run --rm -it -v "$(pwd):/src" aquasec/tfsec /src

Использование через Github Actions

Git:
name: tfsec-pr-commenter
on:
  pull_request:
jobs:
  tfsec:
    name: tfsec PR commenter
    runs-on: ubuntu-latest

    permissions:
      contents: read
      pull-requests: write

    steps:
      - name: Clone repo
        uses: actions/checkout@master
      - name: tfsec
        uses: aquasecurity/tfsec-pr-commenter-action@v1.2.0
        with:
          github_token: ${{ github.token }}


Я надеюсь вам будет полезна эта статья. Если вас больше интересного контента от меня, то предлагаю подписаться на мой канал в telegram Дневник Безопасника 🛡
 
Последнее редактирование модератором:

katok_

Green Team
19.06.2019
44
11
BIT
7
Спасибо за тулы, будет полезно людям которые только начинают в golang и имеют опыт в иб
 
  • Нравится
Реакции: szybnev
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!