Перейти к содержимому

Threat Modeling, STRIDE, OWASP, Security Hardening

Зачем знать на Middle 3: на этом уровне инженер не реактивно патчит уязвимости, а проактивно проектирует системы с учётом моделей угроз. Threat modeling — обязательная часть design review в FAANG, банках, медтехе. STRIDE даёт системный язык, DREAD — оценку. OWASP Top 10 / API Top 10 — must-know. И всё это применяется к Go-сервису через конкретный hardening checklist.

  1. Концепция
  2. Глубже: STRIDE, DREAD, DFD, OWASP 2021, OWASP API
  3. Gotchas / Best practices
  4. Real cases
  5. Вопросы (20)
  6. Practice
  7. Источники

Threat modeling — структурированный процесс выявления угроз на этапе проектирования. Целевая аудитория ответов:

  • Что мы строим? (DFD, диаграммы потоков данных)
  • Что может пойти не так? (применяем STRIDE)
  • Что мы делаем с этим? (mitigations)
  • Хорошо ли мы это сделали? (verification)

Цикл: design → model → mitigate → verify → review.

Шесть категорий угроз:

БукваУгрозаЧто нарушаетПример
Spoofingподмена identityAuthenticationукраденный JWT, фишинг
Tamperingмодификация данныхIntegrityMITM, изменение БД
Repudiationотказ от действийNon-repudiation”я не делал этот платёж”
Information disclosureутечка данныхConfidentialityexposed .git, log с PII
Denial of serviceнедоступностьAvailabilitySYN flood, Slow Loris
Elevation of privilegeповышение правAuthorizationIDOR, sudo exploit
БукваЧтоШкала 1-10
Damageнасколько серьёзно1=минимально, 10=катастрофа
Reproducibilityлегко повторить1=сложно, 10=на лету
Exploitabilityлегко эксплуатировать1=PhD нужен, 10=скрипт-кидди
Affected usersсколько затронуто1=один, 10=все
Discoverabilityлегко найти1=скрыто, 10=на главной

Average → risk score. Сегодня чаще CVSS используют вместо DREAD.

DFD — основа threat modeling. Элементы:

  • External entity (квадрат) — пользователь, внешний сервис.
  • Process (круг) — наш код.
  • Data store (две параллельные линии) — БД, файл, кеш.
  • Data flow (стрелка) — поток данных.
  • Trust boundary (пунктир) — граница доверия (Internet/intranet, namespace, container).

STRIDE применяется per element type:

  • External entity → S, R.
  • Process → STRIDE (всё).
  • Data store → T, I, D, R.
  • Data flow → T, I, D.

+---------+ HTTPS +---------+ gRPC +---------+
| Browser | ----------> | API | ---------> | Payments|
+---------+ <---------- | Gateway | <--------- | Service |
+---------+ +---------+
| |
| trust boundary |
v v
+---------+ +---------+
| Redis | | Postgres|
| cache | | DB |
+---------+ +---------+
Internet | Cluster boundary | Database boundary

Применяем STRIDE:

ElementSTRIDE
Browser→GatewayTLS + JWTTLSrequest_idTLSrate limitRBAC
Gateway→PaymentsmTLS (SPIFFE)mTLSaudit logmTLStimeoutscope
Payments→PostgresDB user + certTLSDB auditencryption at restconn poolleast priv
RedispasswordTLSTLSmaxmem policyACL

A01: Broken Access Control

  • IDOR (Insecure Direct Object Reference): /orders/123 доступен без проверки owner.
  • Mitigation: RBAC/ABAC; subject (user) + resource (object) + action (verb).
  • Patterns: middleware с authz.Allow(user, "read", order).
  • ABAC: атрибуты + политика (OPA Rego, Cedar).
  • ⚠️ Go: писать собственный AuthZ — путь в production with bugs. Используй Casbin / Open Policy Agent.
// Пример: проверка через context
func ordersHandler(w http.ResponseWriter, r *http.Request) {
userID := r.Context().Value(ctxUserID).(string)
orderID := mux.Vars(r)["id"]
order, err := db.GetOrder(r.Context(), orderID)
if err != nil { http.Error(w, "not found", 404); return }
if order.OwnerID != userID && !hasRole(userID, "admin") {
http.Error(w, "forbidden", 403)
return
}
// ...
}

A02: Cryptographic Failures

  • Использование MD5/SHA1 для passwords (вместо argon2id).
  • AES-ECB вместо GCM.
  • Hardcoded key.
  • TLS 1.0/1.1 (deprecated).
  • Mitigation: argon2id / bcrypt для passwords; AES-GCM или ChaCha20-Poly1305 для шифрования; TLS 1.3.
import "golang.org/x/crypto/argon2"
func hashPassword(pass string, salt []byte) []byte {
// recommended: time=1, memory=64MiB, threads=4, keyLen=32
return argon2.IDKey([]byte(pass), salt, 1, 64*1024, 4, 32)
}

A03: Injection

  • SQL: используй db.QueryContext(ctx, "SELECT ... WHERE id=$1", id), никогда fmt.Sprintf.
  • Command injection: exec.Command("sh", "-c", userInput) — НЕТ. exec.Command(bin, args...) — args отдельно.
  • LDAP, XPath, NoSQL — те же принципы.
  • Template injection: Go html/template авто-escape. Не используй text/template для HTML.
// Wrong
db.Query(fmt.Sprintf("SELECT * FROM users WHERE name='%s'", name))
// Right
db.Query("SELECT * FROM users WHERE name=$1", name)

A04: Insecure Design

  • Отсутствие threat modeling на старте.
  • Mitigation: STRIDE per feature; security stories в backlog.

A05: Security Misconfiguration

  • Дефолтные пароли (Mongo без auth, Elasticsearch open).
  • Debug endpoints в проде (pprof, /debug).
  • CORS * для credentialed endpoints.
  • Mitigation: CIS benchmarks; IaC review; production lint (kube-bench, kube-score).
// Не выставляй pprof наружу
mux := http.NewServeMux()
mux.HandleFunc("/api/...", apiHandler)
// Отдельный listener только на localhost для pprof
go http.ListenAndServe("127.0.0.1:6060", nil) // standard net/http/pprof

A06: Vulnerable and Outdated Components

  • См. файл 39 (Supply Chain). govulncheck + SBOM.

A07: Identification and Authentication Failures

  • Weak password policy.
  • No MFA.
  • Predictable session IDs.
  • Mitigation: passkey/FIDO2; argon2id; randomness 256-bit для session.

A08: Software and Data Integrity Failures

  • Auto-update без signature verification.
  • Insecure deserialization (Gob, JSON в неверной структуре, YAML).
  • Mitigation: cosign + SLSA; не deserialize в interface{} без strict schema.

A09: Security Logging and Monitoring Failures

  • Нет audit log.
  • Log без timestamp/correlation.
  • Логирование PII (нарушение GDPR).
  • Mitigation: structured logs (zap, zerolog); SIEM (Splunk, Datadog, ELK); redact PII.

A10: Server-Side Request Forgery (SSRF)

  • Сервис принимает URL от юзера, делает HTTP запрос.
  • Атака: http://169.254.169.254/latest/meta-data/ (AWS IMDS) → утечка credentials.
  • Mitigation: whitelist hosts; block private IP ranges; IMDSv2 (требует session token).
import "net"
func isPrivate(ip net.IP) bool {
privateBlocks := []string{
"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16",
"127.0.0.0/8", "169.254.0.0/16", "::1/128", "fc00::/7",
}
for _, cidr := range privateBlocks {
_, block, _ := net.ParseCIDR(cidr)
if block.Contains(ip) { return true }
}
return false
}
func safeFetch(rawURL string) (*http.Response, error) {
u, err := url.Parse(rawURL)
if err != nil { return nil, err }
ips, _ := net.LookupIP(u.Hostname())
for _, ip := range ips {
if isPrivate(ip) { return nil, errors.New("private IP blocked") }
}
// ⚠️ DNS rebinding: проверяем IP в Dialer too
cl := &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
host, port, _ := net.SplitHostPort(addr)
ips, _ := net.LookupIP(host)
for _, ip := range ips {
if isPrivate(ip) { return nil, errors.New("blocked") }
}
return (&net.Dialer{}).DialContext(ctx, network, addr)
},
},
Timeout: 5 * time.Second,
}
return cl.Get(rawURL)
}

API-specific риски:

  1. BOLA (Broken Object Level Auth) — IDOR.
  2. Broken Authentication — слабая JWT валидация.
  3. Broken Object Property Level Auth — overposting (юзер шлёт is_admin=true в PUT).
  4. Unrestricted Resource Consumption — нет rate limit, pagination.
  5. BFLA (Broken Function Level Auth) — нет проверки role per endpoint.
  6. Unrestricted Access to Sensitive Business Flows — auto-checkout без CAPTCHA.
  7. SSRF.
  8. Security Misconfiguration.
  9. Improper Inventory Management — забытые legacy /v1.
  10. Unsafe Consumption of APIs — слепое доверие сторонним.

Code level:

  • Read-only filesystem где можно (/tmp writable).
  • Run as non-root: USER 65532:65532 в Dockerfile.
  • Drop capabilities: securityContext.capabilities.drop: ["ALL"].
  • AppArmor/SELinux profile.
  • gosec lint в CI.
  • govulncheck в CI.
  • staticcheck, go vet.

TLS:

  • TLS 1.3 only где возможно.
  • HSTS header.
  • mTLS internal.

HTTP:

  • Secure headers (CSP, X-Frame-Options, X-Content-Type-Options).
  • Rate limit (token bucket per IP + per user).
  • Request size limit (http.MaxBytesReader).
  • Timeouts: ReadHeaderTimeout, ReadTimeout, WriteTimeout, IdleTimeout.
srv := &http.Server{
Addr: ":8443",
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
MaxHeaderBytes: 1 << 20, // 1 MB
Handler: secureHeaders(rateLimiter(handler)),
}

Logging:

  • Structured (JSON).
  • Correlation ID per request.
  • No secrets/PII (redact).
  • Audit log (separate stream, immutable).

Configuration:

  • Secrets через Vault / env (не git).
  • Feature flags для emergency disable.
  • Health/readiness отдельно от business endpoints.

Container:

  • Distroless / scratch.
  • Pin by digest.
  • Sign + verify (cosign).
  • Resource limits (CPU, memory).
  • Network policy (deny by default).
  • Read-only root FS, writable emptyDir для cache.

Kubernetes:

  • runAsNonRoot: true.
  • allowPrivilegeEscalation: false.
  • readOnlyRootFilesystem: true.
  • PodSecurityStandards “restricted”.
  • PSA (Pod Security Admission) enforce.
  • Microsoft Threat Modeling Tool (Windows, бесплатный).
  • OWASP Threat Dragon (open-source, web).
  • IriusRisk (enterprise).
  • ThreatSpec — Go-friendly, threats в комментариях кода:
// @threat ssrf:SSRF "Server-Side Request Forgery"
// @control validate_url:strictUrlValidator
// @asset internal_metadata "EC2 instance metadata"
func fetchURL(url string) ([]byte, error) {
// ...
}

⚠️ CORS Access-Control-Allow-Origin: * + credentials — браузер блокирует, но многие думают, что “стало работать”; не проверяй wildcard для cookies.

⚠️ JWT alg: none — старый, но всё ещё встречаемый bug. В Go явно whitelist’и RS256/ES256. Не используй jwt.Parse без keyFunc, явно проверяющего Method.

⚠️ bcrypt cost — увеличивать каждые пару лет (сейчас 12+).

⚠️ Argon2 параметры — не дефолтные. memory >= 64MB, threads = num_cores.

⚠️ Time-based comparison — пароли/HMAC сравнивать через subtle.ConstantTimeCompare, не bytes.Equal.

⚠️ math/rand — НЕ для криптографии. Использовать crypto/rand.

⚠️ Go 1.20+math/rand auto-seeded, но всё равно не cryptographic.

⚠️ http.MaxBytesReader — ставь на тело запроса; иначе атакующий зальёт гигабайты.

⚠️ Reflection в JSON unmarshalling — поля без тегов exporten, могут попасть в overposting. Используй DTO-структуры.

⚠️ io.Copy без io.LimitReader — DoS через гигабайтный ответ от внешнего API.

⚠️ Cookie без HttpOnly + Secure + SameSite=Lax/Strict — XSS уведёт сессию.

⚠️ CSP unsafe-inline — фактически отключает защиту от XSS. Используй nonce.

⚠️ pprof endpointnet/http/pprof авто-регистрит в DefaultServeMux. На дефолтном http.ListenAndServe(":80", nil) будет наружу.

⚠️ Path traversal: filepath.Join("uploads", userPath) НЕ защищает. Используй filepath.Clean + проверку префикса.

clean := filepath.Clean(filepath.Join(baseDir, userPath))
if !strings.HasPrefix(clean, baseDir) {
return errors.New("path traversal")
}

⚠️ Race в JWT cache: проверка sig + claims должны быть атомарны с blacklist check.

  • Threat modeling в каждом design review.
  • Security stories в backlog с явным acceptance criteria.
  • Bug bounty или внутренний red team.
  • Tabletop exercises — учения по incident response.
  • Postmortem для security incidents (no-blame).
  • Continuous threat modeling при изменении архитектуры.

SSRF в WAF (ModSecurity) → атакующий получил IMDS креды → доступ к S3 buckets с 100M записями.

Mitigation:

  • IMDSv2 (session token).
  • WAF threat modeling — обработка пользовательских URL.

Apache Struts CVE-2017-5638 (RCE), не пропатчили вовремя. 147M PII утекло.

Mitigation:

  • SBOM + vuln scanning.
  • SLA на patch critical vulnerabilities (24-48h).

Public repos получали env (включая AWS creds) в forked PR builds.

Mitigation:

  • Ephemeral OIDC tokens вместо long-lived secrets (Sigstore, AWS OIDC).
  • Mask secrets в логах.

В Replit обнаружили IDOR в API: /api/projects/{id} отдавал чужие проекты при правильном UUID.

Lesson: always validate ownership даже когда ID “unguessable”.

Симуляция: “что если 1 dev украдёт production credentials и удалит DB”. Выявили:

  • Нет 4-eyes review на критичные операции.
  • Нет audit log.
  • Backup живёт в том же AWS аккаунте → удалят и его.

Mitigation: separate audit account, MFA для prod, vault session с записью.


  1. Что такое STRIDE и какие категории угроз?
  2. Чем DFD отличается от architecture diagram?
  3. Какие угрозы применимы к “data store” по STRIDE?
  4. DREAD vs CVSS — что выбрать в 2026?
  5. Опиши IDOR. Как защититься?
  6. RBAC vs ABAC — разница и когда что выбрать?
  7. Как защититься от SSRF в Go-сервисе, принимающем URL?
  8. Что такое DNS rebinding и почему он опасен для SSRF-защиты?
  9. Почему bytes.Equal нельзя для сравнения секретов?
  10. Чем argon2id лучше bcrypt?
  11. Что не так с JWT alg: none?
  12. CSP unsafe-inline — почему это плохо?
  13. Чем PSA отличается от PSP в Kubernetes?
  14. Как назначить distroless image read-only filesystem в k8s?
  15. Где допустимо text/template и где обязательно html/template?
  16. Что такое overposting и как защититься?
  17. Чем audit log отличается от обычного log?
  18. Какие taймouts обязательны для http.Server?
  19. math/rand vs crypto/rand — где что использовать?
  20. Как организовать threat modeling процесс в команде?

  1. Возьми существующий Go-сервис, нарисуй DFD (Mermaid или draw.io), примени STRIDE.
  2. Реализуй SSRF-safe HTTP client (с защитой от DNS rebinding).
  3. Напиши middleware для secure headers (CSP, HSTS, X-Frame-Options).
  4. Внедри Casbin или OPA для RBAC, покрой 5 endpoints policies.
  5. Argon2id password hashing + verification (с константным временем).
  6. Audit log: события auth.success, auth.fail, resource.access в отдельный поток.
  7. Запусти gosec на проекте, разбери top 10 issues.
  8. Настрой PSA “restricted” namespace, попробуй задеплоить root container — должно отвергнуться.
  9. Mini-tabletop exercise: симулируй компрометацию dev машины, оцени blast radius.

  1. STRIDE — Microsoft (1999), Adam Shostack
  2. “Threat Modeling: Designing for Security” — Adam Shostack
  3. OWASP Top 10 (2021): https://owasp.org/Top10/
  4. OWASP API Security Top 10 (2023)
  5. OWASP Cheat Sheet Series
  6. NIST SP 800-30 — Guide for Conducting Risk Assessments
  7. CIS Kubernetes Benchmark
  8. Microsoft Threat Modeling Tool docs
  9. OWASP Threat Dragon: https://owasp.org/www-project-threat-dragon/
  10. ThreatSpec: https://threatspec.org
  11. Capital One breach post-mortem
  12. Equifax breach Senate report
  13. xz-utils backdoor analysis (2024)
  14. AWS Well-Architected — Security Pillar
  15. Google SRE Security Workbook
  16. “Web Application Hacker’s Handbook” — Stuttard, Pinto
  17. gosec (Go security checker): https://github.com/securego/gosec
  18. Open Policy Agent: https://www.openpolicyagent.org
  19. Casbin: https://casbin.org
  20. CWE database: https://cwe.mitre.org