PDA

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


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


https://forum.antichat.xyz/attachments/4927815/img_33c59ff1d8.png

1. Lego

https://forum.antichat.xyz/attachments/4927815/img_136e4d093e.png

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

ACME v2 RFC 8555

Регистрация с помощью центра сертификации

Получение сертификатов, как с нуля, так и с помощью существующего CSR

Перевыпуск сертификата

Отозвать сертификат:
Надежная реализация всех задач ACME

HTTP (http-01)

DNS (dns-01)

TLS (tls-alpn-01)


Поддержка сертификата SAN

Поставляется с несколькими дополнительными провайдерами DNS

Custom challenge solvers

Объединение сертификатов

Вспомогательная функция 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 поддерживается достаточно большое количество DNS провайдеров и вы сами можете выбрать, каким из них пользоваться. Для примеру покажу, как использовать 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 в

/.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.NewProvi derServer("", "5002"))
if err != nil {
log.Fatal(err)
}
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.Ne wProviderServer("", "5001"))
if err != nil {
log.Fatal(err)
}

// New users will need to register
reg, err := client.Registration.Register(registration.Register Options{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
https://forum.antichat.xyz/attachments/4927815/img_7770d262cd.png


Обратите внимание, что 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 не только более производителен, чем аналогичные пакеты структурированного логгирования, но и быстрее, чем стандартная библиотека.

https://forum.antichat.xyz/attachments/4927815/1683289418356.png

3. gosec

https://forum.antichat.xyz/attachments/4927815/img_73f17b4106.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
Это уже порадует безопасников, т.к. каждая проблема соотноситься с CWE (Common Weakness Enumeration), которая описывает уязвимость.

Исключения:
Исключение тестовых файлов и папок при аудите
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

https://forum.antichat.xyz/attachments/4927815/img_b2755dc6f8.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 стула:


Docker - установка займет 5 минут. Гайд тут.

Для настоящих мужчин


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

https://forum.antichat.xyz/attachments/4927815/img_04509f6fca.png

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

Начнем с установки
Установка с помощью brew/linuxbrew

Код:



brew install tfsec


Установка с помощью Chocolatey

Код:



choco install tfsec


Установка с помощью Scoop

Код:



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:

Название образаОбразОписаниеaquasec/tfsecalpineОбычный tfsec образaquasec/tfsec-alpinealpineТочно так же, как aquasec/tfsec, но для тех, кто любит ясность.aquasec/tfsec-cialpinetfsec без entrypoint- полезно для сборок CI, где вы хотите переопределить командуaquasec/tfsec-scratchscratchОбраз, созданный с нуля - ничего лишнего, просто работает 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_
11.05.2023, 20:31
Спасибо за тулы, будет полезно людям которые только начинают в golang и имеют опыт в иб

szybnev
11.05.2023, 22:59
katok_ сказал(а):

Спасибо за тулы, будет полезно людям которые только начинают в golang и имеют опыт в иб


Спасибо за коммент) Если интересно, то могу сделать похожие статьи про другие языки.