325 lines
14 KiB
Go
Executable file
325 lines
14 KiB
Go
Executable file
package infosecmodules
|
||
|
||
import (
|
||
"rubric/utils"
|
||
)
|
||
|
||
var AuthnModule = Module{
|
||
Key: "authn",
|
||
Aliases: []string{"auth", "mfa", "jwt", "oauth"},
|
||
Title: "Аутентификация и авторизация",
|
||
Description: "MFA, JWT, OAuth2, OIDC, RBAC, LDAP/AD, управление доступом",
|
||
Run: showAuthn,
|
||
}
|
||
|
||
func showAuthn() {
|
||
utils.Header("InfoSec — Аутентификация и авторизация")
|
||
|
||
utils.Section("Основные понятия")
|
||
utils.Code(`Authentication (AuthN) — кто ты? Проверка идентичности.
|
||
Authorization (AuthZ) — что тебе можно? Проверка прав.
|
||
|
||
Факторы аутентификации:
|
||
Something you know — пароль, PIN, секретный вопрос
|
||
Something you have — токен, телефон, смарт-карта
|
||
Something you are — биометрика (отпечаток, лицо)
|
||
Somewhere you are — геолокация, IP (дополнительный фактор)
|
||
|
||
MFA (Multi-Factor Authentication) — два и более фактора.
|
||
2FA — два фактора (подмножество MFA).
|
||
|
||
Типы MFA (от слабого к сильному):
|
||
SMS OTP — уязвим к SIM-swap, SS7 атакам
|
||
TOTP — RFC 6238, Google Authenticator (лучше SMS)
|
||
HOTP — счётчик, менее популярен
|
||
Push Auth — Duo, Microsoft Authenticator
|
||
FIDO2/WebAuthn — аппаратные ключи, phishing-resistant (лучший вариант)`)
|
||
|
||
utils.Section("Пароли и хранение")
|
||
utils.Code(`Правила паролей (NIST SP 800-63B — актуальные рекомендации):
|
||
- Минимальная длина: 8+ символов (лучше 12-14+)
|
||
- НЕ требовать обязательную смену (только при компрометации)
|
||
- НЕ требовать сложность (но и не запрещать)
|
||
- Проверять по словарю скомпрометированных паролей
|
||
- Разрешать пробелы и Unicode
|
||
- Показывать пароль при вводе (опционально)
|
||
- Поддерживать менеджеры паролей (не ограничивать длину)
|
||
|
||
Хранение паролей:
|
||
❌ Открытый текст
|
||
❌ Обратимое шифрование
|
||
❌ MD5 / SHA-1 без соли
|
||
✓ bcrypt (cost ≥ 12), Argon2id, scrypt
|
||
|
||
Проверка скомпрометированных паролей:
|
||
Have I Been Pwned API — проверить hashed пароль
|
||
k-Anonymity: отправить первые 5 символов хэша
|
||
https://api.pwnedpasswords.com/range/{hash_prefix}
|
||
|
||
Account Lockout:
|
||
Блокировать после N неудачных попыток (3-5)
|
||
Экспоненциальная задержка между попытками
|
||
Уведомлять пользователя о неудачных попытках`)
|
||
|
||
utils.Section("TOTP — Time-based One-Time Password")
|
||
utils.Code(`RFC 6238. Основан на HMAC-SHA1 + временном счётчике.
|
||
|
||
Как работает:
|
||
1. Общий секрет (seed) обменивается один раз (QR-код)
|
||
2. Counter = floor(UnixTime / 30) # меняется каждые 30 сек
|
||
3. OTP = HOTP(secret, counter) — 6-8 цифр
|
||
4. Сервер проверяет OTP ± 1 временной шаг
|
||
|
||
Уязвимости:
|
||
- Фишинг в реальном времени (attacker-in-the-middle)
|
||
- Не защищает от SIM-swap (только SMS)
|
||
- Потеря устройства = потеря доступа
|
||
|
||
# Python реализация:
|
||
import pyotp
|
||
secret = pyotp.random_base32()
|
||
totp = pyotp.TOTP(secret)
|
||
print(totp.now()) # текущий OTP
|
||
print(totp.verify("123456")) # проверить
|
||
|
||
# Provisioning URI для QR-кода:
|
||
uri = totp.provisioning_uri("alice@example.com", issuer_name="MyApp")`)
|
||
|
||
utils.Section("FIDO2 / WebAuthn — беспарольная аутентификация")
|
||
utils.Code(`FIDO2 = WebAuthn (W3C) + CTAP (Client-to-Authenticator Protocol)
|
||
Phishing-resistant: ключ привязан к origin (домену).
|
||
|
||
Аутентификаторы:
|
||
Platform — встроенный в устройство (Touch ID, Windows Hello)
|
||
Roaming — внешний ключ (YubiKey, Titan Key)
|
||
|
||
Как работает:
|
||
Регистрация:
|
||
1. Сервер отправляет challenge
|
||
2. Аутентификатор создаёт пару ключей для этого origin
|
||
3. Публичный ключ сохраняется на сервере
|
||
4. Приватный ключ НИКОГДА не покидает устройство
|
||
|
||
Аутентификация:
|
||
1. Сервер отправляет challenge
|
||
2. Аутентификатор подписывает challenge приватным ключом
|
||
3. Сервер верифицирует подпись публичным ключом
|
||
|
||
Атака фишингом НЕВОЗМОЖНА: ключ не работает на evil.com
|
||
|
||
Паспорты (Passkeys):
|
||
= FIDO2 ключи, синхронизируемые через облако (iCloud, Google, 1Password)
|
||
Удобство ключей + синхронизация устройств`)
|
||
|
||
utils.Section("JWT — JSON Web Token")
|
||
utils.Code(`JWT — компактный токен для передачи claims между сторонами.
|
||
Используется для stateless аутентификации (API, микросервисы).
|
||
|
||
Структура: header.payload.signature
|
||
|
||
# Header (base64url):
|
||
{"alg": "HS256", "typ": "JWT"}
|
||
|
||
# Payload (base64url):
|
||
{
|
||
"sub": "1234567890", # subject (user ID)
|
||
"name": "Alice Smith",
|
||
"iat": 1516239022, # issued at
|
||
"exp": 1516242622, # expiration
|
||
"jti": "uuid", # JWT ID (для revocation)
|
||
"iss": "https://auth.example.com", # issuer
|
||
"aud": "https://api.example.com" # audience
|
||
}
|
||
|
||
# Signature:
|
||
HMAC-SHA256(base64(header) + "." + base64(payload), secret)
|
||
|
||
Типы алгоритмов:
|
||
Симметричные (один ключ):
|
||
HS256, HS384, HS512 — HMAC-SHA
|
||
Асимметричные (ключевая пара):
|
||
RS256 — RSA + SHA256 (рекомендуется для распределённых систем)
|
||
ES256 — ECDSA + SHA256 (компактнее)
|
||
EdDSA — Ed25519 (современный)
|
||
|
||
Уязвимости JWT:
|
||
alg=none — КРИТИЧНО, проверяй алгоритм!
|
||
Атака: изменить alg на "none", удалить подпись
|
||
RS256→HS256 подмена
|
||
Атака: использовать публичный RSA ключ как HMAC секрет
|
||
Слабый секрет — поддаётся брутфорсу
|
||
Отсутствие exp — токен не истекает
|
||
Хранение в localStorage — доступен XSS атаке
|
||
|
||
Лучшие практики:
|
||
- Короткий TTL (access token: 15 мин, refresh: 7 дней)
|
||
- Использовать RS256 или ES256 (не HS256 в распределённых системах)
|
||
- Хранить в HttpOnly cookie (не localStorage!)
|
||
- Проверять iss, aud, exp
|
||
- Реализовать token revocation (Redis blacklist или jti)`)
|
||
|
||
utils.Section("OAuth2 и OpenID Connect")
|
||
utils.Code(`OAuth2 — фреймворк делегированной авторизации (не аутентификации!).
|
||
OIDC (OpenID Connect) — слой аутентификации поверх OAuth2.
|
||
|
||
OAuth2 Roles:
|
||
Resource Owner — пользователь
|
||
Client — приложение (запрашивает доступ)
|
||
Resource Server — API с защищёнными данными
|
||
Authorization Server — выдаёт токены
|
||
|
||
OAuth2 Grant Types (потоки):
|
||
Authorization Code — для веб-приложений (РЕКОМЕНДУЕТСЯ)
|
||
1. Redirect → Auth Server с code_challenge (PKCE)
|
||
2. Пользователь авторизуется
|
||
3. Redirect обратно с code
|
||
4. Обмен code на tokens (server-side)
|
||
|
||
Client Credentials — сервис-к-сервису (без пользователя)
|
||
|
||
Device Authorization — умные устройства, CLI
|
||
|
||
❌ Implicit Flow — устаревший, уязвим (токен в URL)
|
||
❌ Resource Owner Password — только для доверенных приложений
|
||
|
||
PKCE (Proof Key for Code Exchange):
|
||
Защита от перехвата authorization code.
|
||
Обязателен для публичных клиентов (SPA, мобильные).
|
||
code_verifier = random()
|
||
code_challenge = base64url(sha256(code_verifier))
|
||
|
||
Токены OAuth2:
|
||
Access Token — краткоживущий, доступ к API
|
||
Refresh Token — долгоживущий, получение нового access token
|
||
ID Token — OIDC, JWT с данными пользователя
|
||
|
||
OIDC Scopes:
|
||
openid — обязательный для OIDC, возвращает ID Token
|
||
profile — имя, аватар, locale
|
||
email — email и верификация
|
||
address — адрес
|
||
phone — телефон`)
|
||
|
||
utils.Section("RBAC, ABAC и управление доступом")
|
||
utils.Code(`DAC (Discretionary Access Control):
|
||
Владелец решает кто имеет доступ (Linux chmod, ACL)
|
||
|
||
MAC (Mandatory Access Control):
|
||
Системная политика (SELinux, AppArmor)
|
||
|
||
RBAC (Role-Based Access Control):
|
||
Права назначаются ролям, роли — пользователям.
|
||
Пример: admin, editor, viewer
|
||
Kubernetes RBAC: Role → RoleBinding → ServiceAccount/User
|
||
|
||
ABAC (Attribute-Based Access Control):
|
||
Решения на основе атрибутов (пользователь, ресурс, контекст)
|
||
Пример: OPA (Open Policy Agent), AWS IAM
|
||
|
||
ReBAC (Relationship-Based Access Control):
|
||
Права через отношения между объектами
|
||
Пример: Google Zanzibar, SpiceDB, OpenFGA
|
||
|
||
Принцип наименьших привилегий:
|
||
Давать только необходимые права
|
||
Just-in-Time (JIT) доступ — временное повышение привилегий
|
||
Privileged Access Management (PAM):
|
||
CyberArk, HashiCorp Vault, AWS IAM Identity Center
|
||
|
||
# OPA — Open Policy Agent (пример Rego политики):
|
||
package authz
|
||
|
||
default allow = false
|
||
|
||
allow if {
|
||
input.method == "GET"
|
||
input.path == ["api", "public"]
|
||
}
|
||
|
||
allow if {
|
||
input.user.role == "admin"
|
||
}`)
|
||
|
||
utils.Section("LDAP и Active Directory")
|
||
utils.Code(`LDAP (Lightweight Directory Access Protocol):
|
||
Протокол доступа к каталогам (пользователи, группы, ресурсы).
|
||
|
||
Active Directory — Microsoft LDAP + Kerberos + DNS.
|
||
|
||
LDAP структура:
|
||
DC=example,DC=com — домен
|
||
OU=Users — организационная единица
|
||
CN=Alice Smith — объект (пользователь)
|
||
|
||
Полный DN: CN=Alice Smith,OU=Users,DC=example,DC=com
|
||
|
||
# ldapsearch — поиск в LDAP:
|
||
ldapsearch -H ldap://dc.example.com \
|
||
-D "CN=binduser,DC=example,DC=com" \
|
||
-w password \
|
||
-b "DC=example,DC=com" \
|
||
"(sAMAccountName=alice)"
|
||
|
||
# Атаки на LDAP/AD:
|
||
Pass-the-Hash — использование хэша NTLM без пароля
|
||
Pass-the-Ticket — использование Kerberos билета
|
||
Kerberoasting — получение хэшей service tickets
|
||
AS-REP Roasting — атака на аккаунты без Kerberos preauth
|
||
DCSync — имитация контроллера домена (миллионы хэшей)
|
||
LDAP Injection — инъекция в LDAP-запросы
|
||
|
||
# Защита:
|
||
- Kerberos AES вместо NTLM/RC4
|
||
- Protected Users группа (не кэшировать credentials)
|
||
- Отключить NTLMv1, ограничить NTLMv2
|
||
- LAPS (Local Admin Password Solution)
|
||
- Tiered Administration Model`)
|
||
|
||
utils.Section("Secrets Management")
|
||
utils.Code(`НЕ хранить секреты в:
|
||
❌ Git / исходном коде
|
||
❌ Docker image / Dockerfile
|
||
❌ Environment variables (видны в /proc)
|
||
❌ Логах
|
||
|
||
Инструменты управления секретами:
|
||
HashiCorp Vault — де-факто стандарт:
|
||
Динамические секреты (генерация по запросу)
|
||
Lease и автообновление
|
||
Аудит всех обращений
|
||
|
||
AWS Secrets Manager / Parameter Store
|
||
GCP Secret Manager
|
||
Azure Key Vault
|
||
Kubernetes Secrets (base64, не зашифровано по умолчанию!)
|
||
+ Sealed Secrets (Bitnami) — зашифрованные секреты в Git
|
||
+ External Secrets Operator — синхронизация с Vault/AWS
|
||
|
||
# HashiCorp Vault — основные операции:
|
||
vault server -config=vault.hcl
|
||
vault operator init # инициализация (ключи разуплотнения)
|
||
vault operator unseal # разуплотнение
|
||
vault login
|
||
|
||
vault secrets enable kv-v2
|
||
vault kv put secret/myapp db_password=s3cret api_key=abc123
|
||
vault kv get secret/myapp
|
||
vault kv get -field=db_password secret/myapp
|
||
|
||
# Динамические секреты PostgreSQL:
|
||
vault secrets enable database
|
||
vault write database/config/mydb \
|
||
plugin_name=postgresql-database-plugin \
|
||
connection_url="postgresql://{{username}}:{{password}}@db:5432/mydb" \
|
||
allowed_roles="my-role"
|
||
vault write database/roles/my-role \
|
||
db_name=mydb \
|
||
creation_statements="CREATE ROLE..." \
|
||
default_ttl="1h" max_ttl="24h"
|
||
|
||
# Получить временные credentials:
|
||
vault read database/creds/my-role
|
||
# → username: v-root-xyz123, password: A1B2C3..., lease_duration: 1h`)
|
||
|
||
utils.Footer()
|
||
}
|