Перейти к содержимому
Назад к пути
Теория 17 мин чтения

4. Автоматическое обнаружение SQLi в CI/CD

Автоматическое обнаружение SQL Injection в CI/CD

Этот модуль научит вас настраивать полный конвейер автоматического обнаружения SQL-инъекций в Go-проектах — от pre-commit хуков на машине разработчика до мониторинга аномалий в production. Go-экосистема имеет зрелый набор инструментов безопасности: gosec, Semgrep с Go-правилами, govulncheck и golangci-lint — все они интегрируются в CI/CD за минуты.


Обзор инструментов

Категория Инструмент Что делает Когда применять
SAST gosec Статический анализ Go-кода, правила G201/G202 для SQLi Pre-commit, CI
SAST Semgrep Pattern-matching правила, taint analysis для Go Pre-commit, CI
SAST staticcheck Общий статический анализатор Go (косвенное обнаружение) CI
SAST golangci-lint Meta-линтер, объединяет gosec + staticcheck + десятки других Pre-commit, CI
DAST sqlmap Автоматический поиск SQLi в работающем приложении QA/Staging
DAST OWASP ZAP Полноценный прокси-сканер веб-приложений QA/Staging
SCA govulncheck Поиск уязвимых Go-зависимостей по базе vuln.go.dev CI, мониторинг
SCA Trivy Сканирование контейнерных образов и зависимостей CI, мониторинг

1. SAST: gosec

gosec — стандартный инструмент статического анализа безопасности для Go. Для SQL-инъекций он использует два ключевых правила: G201 (SQL-запрос, сконструированный из пользовательского ввода) и G202 (SQL-запрос, сконструированный через fmt.Sprintf).

Установка и запуск

# Установка
go install github.com/securego/gosec/v2/cmd/gosec@latest

# Сканирование всего проекта
gosec ./...

# Только правила SQL-инъекций
gosec -include=G201,G202 ./...

# JSON-вывод для CI/CD
gosec -fmt=json -out=gosec-report.json ./...

# Вывод в формате SARIF (для GitHub Security tab)
gosec -fmt=sarif -out=gosec-report.sarif ./...

Что обнаруживают G201 и G202

gosec анализирует вызовы database/sql и ищет конкатенацию или форматирование строк в SQL-запросах:

// G201 — обнаружит: конкатенация строки в SQL-запросе
query := "SELECT * FROM users WHERE username = '" + username + "'"
rows, err := db.Query(query)

// G202 — обнаружит: fmt.Sprintf в SQL-запросе
query := fmt.Sprintf("SELECT * FROM users WHERE id = %s", userID)
rows, err := db.Query(query)

// G202 — обнаружит: fmt.Sprintf с %v
query := fmt.Sprintf("DELETE FROM orders WHERE id = %v", orderID)
db.Exec(query)

// Безопасно — gosec НЕ будет жаловаться
rows, err := db.Query("SELECT * FROM users WHERE username = ?", username)
rows, err := db.QueryContext(ctx, "SELECT * FROM users WHERE id = $1", userID)

Пример вывода gosec

[/internal/handlers/handlers.go:45] - G201 (CWE-89): SQL string formatting
  (Confidence: HIGH, Severity: MEDIUM)
  > query := "SELECT id, username, role FROM users WHERE username = '" + username + "' AND password = '" + password + "'"

[/internal/handlers/handlers.go:78] - G202 (CWE-89): SQL string concatenation
  (Confidence: HIGH, Severity: MEDIUM)
  > query := fmt.Sprintf("SELECT * FROM products WHERE category = '%s'", category)

Что gosec НЕ обнаруживает

gosec работает на уровне AST (abstract syntax tree) и не выполняет межпроцедурный анализ потока данных:

// gosec НЕ увидит: значение приходит из другой функции
func getQuery(input string) string {
    return "SELECT * FROM users WHERE name = '" + input + "'"
}
func handler(w http.ResponseWriter, r *http.Request) {
    q := getQuery(r.URL.Query().Get("name"))
    db.Query(q) // gosec не отследит taint через вызов функции
}

// gosec НЕ увидит: Second-Order SQLi (данные из БД в другой запрос)
var savedName string
db.QueryRow("SELECT name FROM cache WHERE id = 1").Scan(&savedName)
db.Query("SELECT * FROM users WHERE name = '" + savedName + "'")

// gosec НЕ увидит: использование ORM с raw-запросом
db.Raw("SELECT * FROM users WHERE name = '" + name + "'").Scan(&users)

Подавление ложных срабатываний

Если gosec даёт ложноположительное (например, статическая строка), используйте аннотацию:

// Статическая строка, не содержит пользовательского ввода
query := "SELECT * FROM config WHERE key = 'app_version'" // #nosec G201
rows, err := db.Query(query)

Важно: никогда не используйте #nosec без комментария, объясняющего почему это безопасно. В code review отсутствие объяснения — красный флаг.


2. SAST: Semgrep

Semgrep обеспечивает более глубокий анализ, чем gosec, благодаря поддержке taint analysis (в Pro-версии) и гибким YAML-правилам. Для Go он имеет обширную библиотеку готовых правил.

Установка и запуск

# Установка
pip install semgrep
# или через brew
brew install semgrep

# Go-специфичные правила безопасности
semgrep --config "p/golang" ./...

# Только SQL-инъекции
semgrep --config "p/golang" --include="*.go" ./internal/

# С авто-набором правил (OWASP Top 10)
semgrep --config auto ./...

Готовые правила для SQL-инъекций в Go

Rule ID Что ищет
go.lang.security.audit.sqli.tainted-sql-string Конкатенация строк в SQL с данными из http.Request
go.lang.security.audit.sqli.string-formatted-query fmt.Sprintf в SQL-запросах
go.lang.security.audit.database-sql-string-formatting Форматирование строк в database/sql вызовах
go.gorilla.security.audit.sqli-taint SQLi через Gorilla Mux переменные
go.gin.security.audit.sqli-taint SQLi через Gin context параметры

Пользовательское правило для Go

Создайте файл .semgrep.yml в корне проекта:

rules:
  - id: go-sqli-sprintf
    patterns:
      - pattern: |
                    $DB.$METHOD(fmt.Sprintf("...", ...))
      - metavariable-regex:
          metavariable: $METHOD
          regex: (Query|QueryRow|QueryContext|Exec|ExecContext|Prepare)
    message: >
      SQL injection: fmt.Sprintf используется для построения SQL-запроса
      в $DB.$METHOD(). Используйте параметризованные запросы:
      db.Query("SELECT * FROM t WHERE id = ?", id)      
    severity: ERROR
    languages: [go]
    metadata:
      cwe: "CWE-89"
      owasp: "A03:2021 - Injection"
      confidence: HIGH

  - id: go-sqli-concatenation
    patterns:
      - pattern: |
                    $DB.$METHOD("..." + $VAR + "...")
      - metavariable-regex:
          metavariable: $METHOD
          regex: (Query|QueryRow|QueryContext|Exec|ExecContext|Prepare)
    message: >
      SQL injection: конкатенация строк в $DB.$METHOD().
      Используйте параметризованные запросы.      
    severity: ERROR
    languages: [go]
    metadata:
      cwe: "CWE-89"

  - id: go-sqli-strings-replace
    patterns:
      - pattern: |
          $QUERY = strings.Replace($TEMPLATE, "...", $INPUT, ...)
          ...
          $DB.$METHOD($QUERY, ...)          
    message: >
      SQL injection: strings.Replace используется для подстановки
      значений в SQL-запрос. Используйте параметризованные запросы.      
    severity: ERROR
    languages: [go]
    metadata:
      cwe: "CWE-89"

Пример вывода Semgrep

internal/handlers/handlers.go
  severity:error rule:go-sqli-sprintf
  SQL injection: fmt.Sprintf используется для построения SQL-запроса
  в db.Query(). Используйте параметризованные запросы.
  45│ rows, err := db.Query(fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", name))

Semgrep vs gosec для SQLi

Критерий gosec Semgrep
Правила SQLi G201, G202 (2 правила) 10+ готовых правил
Кастомные правила Нет (только встроенные) Да (YAML)
Taint analysis Нет Да (Pro)
Межпроцедурный анализ Нет Частично (Pro)
Second-Order SQLi Нет Частично (Pro)
Скорость Очень быстрый (~2 сек) Быстрый (~5-10 сек)
Ложноположительные Больше Меньше
Цена Бесплатный Community бесплатно, Pro платный
Интеграция с Go Нативная (Go AST) Через tree-sitter

Рекомендация: используйте оба инструмента. gosec как быстрый первый фильтр (встроен в golangci-lint), Semgrep для глубокого анализа с кастомными правилами.


3. SAST: golangci-lint

golangci-lint — мета-линтер для Go, объединяющий десятки линтеров в один инструмент. Для обнаружения SQL-инъекций включите gosec и sqlclosecheck:

# .golangci.yml
linters:
  enable:
    - gosec          # SQL-инъекции (G201, G202) + другие security правила
    - sqlclosecheck  # Незакрытые sql.Rows (утечки ресурсов)
    - rowserrcheck   # Непроверенные ошибки sql.Rows.Err()
    - bodyclose      # Незакрытые HTTP response body

linters-settings:
  gosec:
    includes:
      - G201  # SQL query string formatting
      - G202  # SQL query string concatenation
    severity: high
    confidence: medium

issues:
  exclude-rules:
    - path: _test\.go
      linters:
        - gosec  # Тесты могут содержать небезопасный код для проверки

Запуск:

# Установка
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

# Запуск с конфигурацией
golangci-lint run ./...

# Только security линтеры
golangci-lint run --enable-only gosec,sqlclosecheck ./...

4. DAST: sqlmap

sqlmap — инструмент для автоматического поиска и эксплуатации SQL-инъекций в работающем приложении. В отличие от SAST, sqlmap находит уязвимости, которые не видны в коде (Second-Order, Blind SQLi, нюансы конкретной СУБД).

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

# Установка
pip install sqlmap

# Тестирование GET-параметра
sqlmap -u "http://localhost:8080/api/search?q=test" --batch --level=3

# Тестирование POST-формы (login)
sqlmap -u "http://localhost:8080/login" \
  --data="username=admin&password=test" \
  --batch --level=3 --risk=2

# Тестирование с cookie (авторизованная зона)
sqlmap -u "http://localhost:8080/api/users?id=1" \
  --cookie="session_token=abc123" \
  --batch --level=5 --risk=3

# Указание СУБД для ускорения (Go-лабы используют SQLite)
sqlmap -u "http://localhost:8080/catalog?q=test" \
  --dbms=sqlite --batch --level=3

Ключевые параметры для Go-приложений

Параметр Назначение
--batch Авто-ответы на все вопросы (для CI/CD)
--level=1-5 Глубина тестирования (3 — хороший баланс)
--risk=1-3 Агрессивность (2 — безопасно для staging)
--dbms=sqlite Go-лабы используют SQLite — ускоряет сканирование
--technique=BEUST Boolean, Error, Union, Stacked, Time-based
--forms Автоматически найти формы на странице
--crawl=3 Обход сайта до глубины 3
--tamper=space2comment Обход WAF (замена пробелов на комментарии)
--output-dir=./reports Директория для отчётов

Скрипт для CI/CD

#!/bin/bash
# scripts/dast-sqlmap.sh — проверка что SQLi не найдены

TARGET="http://staging:8080"
REPORT_DIR="/tmp/sqlmap-report"
FOUND_VULN=0

# Тестируем все известные эндпоинты
ENDPOINTS=(
  "/login --data=username=test&password=test"
  "/api/search?q=test"
  "/api/users?id=1 --cookie=session_token=$SESSION"
)

for ep in "${ENDPOINTS[@]}"; do
  sqlmap -u "${TARGET}${ep}" \
    --batch --level=3 --risk=2 --dbms=sqlite \
    --output-dir="$REPORT_DIR" 2>&1 | tee /tmp/sqlmap-output.txt

  if grep -q "is vulnerable" /tmp/sqlmap-output.txt; then
    echo "FAIL: SQL injection found at ${ep}!"
    FOUND_VULN=1
  fi
done

if [ $FOUND_VULN -eq 1 ]; then
  echo "DAST FAILED: SQL injection vulnerabilities detected"
  exit 1
fi
echo "DAST PASSED: No SQL injection found"

5. DAST: OWASP ZAP

OWASP ZAP — полноценный прокси-сканер, который находит не только SQLi, но и XSS, CSRF, broken access control и другие уязвимости. Для Go-приложений он работает как чёрный ящик — сканирует HTTP-эндпоинты без знания исходного кода.

Автоматическое сканирование в Docker

# Baseline scan (пассивный, ~2 мин) — находит очевидные проблемы
docker run --rm --network host ghcr.io/zaproxy/zaproxy:stable \
  zap-baseline.py -t http://localhost:8080 -r zap-baseline.html

# Full scan (активный, ~15-30 мин) — включает SQLi-тесты
docker run --rm --network host ghcr.io/zaproxy/zaproxy:stable \
  zap-full-scan.py -t http://localhost:8080 -r zap-full.html

# API scan (для REST API)
docker run --rm --network host ghcr.io/zaproxy/zaproxy:stable \
  zap-api-scan.py -t http://localhost:8080/openapi.json \
  -f openapi -r zap-api.html

ZAP SQL Injection правила

Rule ID Название Описание
40018 SQL Injection Базовый тест (error-based)
40019 SQL Injection (MySQL) MySQL-специфичные пейлоады
40020 SQL Injection (Hypersonic) HyperSQL пейлоады
40021 SQL Injection (Oracle) Oracle-специфичные
40022 SQL Injection (PostgreSQL) PostgreSQL-специфичные
40024 SQL Injection (SQLite) SQLite-специфичные (актуально для Go-лаб)
90018 Advanced SQL Injection Blind + time-based

Настройка правил для Go + SQLite

# .zap-rules.tsv — настройка правил для Go-проекта
# Формат: rule_id	action	parameter
40018	FAIL	# SQL Injection — фейлить pipeline
40024	FAIL	# SQLite Injection — фейлить pipeline
90018	FAIL	# Advanced SQL Injection — фейлить pipeline
40019	IGNORE	# MySQL — не актуально для SQLite
40021	IGNORE	# Oracle — не актуально для SQLite

6. SCA: govulncheck и Trivy

SQL-инъекции могут быть не только в вашем коде, но и в ORM-библиотеках и драйверах СУБД. govulncheck проверяет Go-зависимости по официальной базе vuln.go.dev.

govulncheck

# Установка
go install golang.org/x/vuln/cmd/govulncheck@latest

# Проверка зависимостей
govulncheck ./...

# JSON-вывод для CI
govulncheck -json ./... > govulncheck-report.json

# Пример вывода
# Vulnerability #1: GO-2023-1571
#   A request smuggling vulnerability exists in the
#   net/http package when using MaxBytesHandler.
#   Found in: net/http@go1.20.1
#   Fixed in: net/http@go1.20.3

Trivy

# Сканирование Go-модуля
trivy fs --scanners vuln .

# Сканирование Docker-образа
trivy image myapp:latest

# Только critical и high
trivy image --severity CRITICAL,HIGH myapp:latest

# JSON для CI
trivy image --format json --output trivy-report.json myapp:latest

Какие CVE искать

Для Go-приложений с SQL наиболее релевантны уязвимости в:

Пакет Тип уязвимости Пример CVE
github.com/mattn/go-sqlite3 Buffer overflow, SQL injection CVE-2022-35737
github.com/go-sql-driver/mysql Auth bypass, injection CVE-2022-27664
github.com/lib/pq SQL injection в параметрах Проверяйте vuln.go.dev
gorm.io/gorm Raw SQL injection Проверяйте vuln.go.dev
net/http Request smuggling (косвенно) GO-2023-1571

7. Pre-commit хуки

Makefile targets

# Makefile — security-related targets

.PHONY: security security-sast security-dast security-sca

# Все проверки безопасности
security: security-sast security-sca

# SAST: gosec + Semgrep
security-sast:
	@echo "=== Running gosec (G201, G202 — SQL Injection) ==="
	gosec -include=G201,G202 -fmt=json -out=reports/gosec.json ./...
	@echo "=== Running Semgrep ==="
	semgrep --config .semgrep.yml --config "p/golang" --json -o reports/semgrep.json ./...

# SCA: govulncheck + Trivy
security-sca:
	@echo "=== Running govulncheck ==="
	govulncheck ./...
	@echo "=== Running Trivy ==="
	trivy fs --scanners vuln --exit-code 1 --severity CRITICAL,HIGH .

# DAST: sqlmap + ZAP (требует запущенное приложение)
security-dast:
	@echo "=== Running sqlmap ==="
	bash scripts/dast-sqlmap.sh
	@echo "=== Running ZAP ==="
	docker run --rm --network host ghcr.io/zaproxy/zaproxy:stable \
		zap-full-scan.py -t http://localhost:8080 -r reports/zap.html

# Quick check (для pre-commit)
security-quick:
	gosec -include=G201,G202 -quiet ./...
	govulncheck ./...

Pre-commit конфигурация

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/securego/gosec
    rev: v2.21.4
    hooks:
      - id: gosec
        args: ['-include=G201,G202', '-quiet', './...']

  - repo: https://github.com/golangci/golangci-lint
    rev: v1.62.2
    hooks:
      - id: golangci-lint
        args: ['--enable-only=gosec,sqlclosecheck,rowserrcheck']

  - repo: https://github.com/semgrep/semgrep
    rev: v1.108.0
    hooks:
      - id: semgrep
        args: ['--config', '.semgrep.yml', '--error']
        types: [go]

Установка:

pip install pre-commit
pre-commit install
# Теперь при git commit автоматически запустятся gosec и Semgrep

8. CI/CD Pipeline

GitHub Actions

# .github/workflows/security.yml
name: Security Scan

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  sast:
    name: SAST Analysis
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-go@v5
        with:
          go-version: '1.23'

      - name: gosec — SQL Injection Rules
        uses: securego/gosec@master
        with:
          args: '-include=G201,G202 -fmt=sarif -out=gosec.sarif ./...'

      - name: Upload gosec SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: gosec.sarif

      - name: Semgrep — Go Security Rules
        uses: semgrep/semgrep-action@v1
        with:
          config: >-
            p/golang
            .semgrep.yml            

      - name: golangci-lint — Security Linters
        uses: golangci/golangci-lint-action@v6
        with:
          args: --enable-only=gosec,sqlclosecheck,rowserrcheck

  sca:
    name: Dependency Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-go@v5
        with:
          go-version: '1.23'

      - name: govulncheck
        run: |
          go install golang.org/x/vuln/cmd/govulncheck@latest
          govulncheck ./...          

      - name: Trivy — Filesystem Scan
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

  dast:
    name: DAST Scan
    runs-on: ubuntu-latest
    needs: [sast]
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-go@v5
        with:
          go-version: '1.23'

      - name: Build and Start Application
        run: |
          go build -o app ./cmd/main.go
          LAB_ADMIN_PASS=test LAB_FLAG=flag{test} ./app &
          sleep 5          

      - name: OWASP ZAP — Full Scan
        uses: zaproxy/action-full-scan@v0.12.0
        with:
          target: 'http://localhost:8080'
          rules_file_name: '.zap-rules.tsv'
          allow_issue_writing: false

      - name: sqlmap — SQL Injection Scan
        run: |
          pip install sqlmap
          sqlmap -u "http://localhost:8080/login" \
            --data="username=admin&password=test" \
            --batch --level=3 --risk=2 --dbms=sqlite \
            --output-dir=/tmp/sqlmap 2>&1 | tee /tmp/sqlmap.log
          if grep -q "is vulnerable" /tmp/sqlmap.log; then
            echo "::error::SQL injection vulnerability found!"
            exit 1
          fi          

  container:
    name: Container Scan
    runs-on: ubuntu-latest
    needs: [sast]
    steps:
      - uses: actions/checkout@v4

      - name: Build Docker Image
        run: docker build -t app:${{ github.sha }} .

      - name: Trivy — Image Scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'app:${{ github.sha }}'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

GitLab CI

# .gitlab-ci.yml
stages:
  - sast
  - sca
  - build
  - dast

gosec:
  stage: sast
  image: securego/gosec:latest
  script:
    - gosec -include=G201,G202 -fmt=json -out=gosec-report.json ./...
  artifacts:
    reports:
      sast: gosec-report.json

semgrep:
  stage: sast
  image: semgrep/semgrep:latest
  script:
    - semgrep --config p/golang --config .semgrep.yml --json -o semgrep-report.json ./...
  artifacts:
    reports:
      sast: semgrep-report.json

govulncheck:
  stage: sca
  image: golang:1.23
  script:
    - go install golang.org/x/vuln/cmd/govulncheck@latest
    - govulncheck -json ./... > govulncheck-report.json
  artifacts:
    paths:
      - govulncheck-report.json

trivy:
  stage: sca
  image: aquasec/trivy:latest
  script:
    - trivy fs --scanners vuln --severity CRITICAL,HIGH --exit-code 1 .

zap:
  stage: dast
  image: ghcr.io/zaproxy/zaproxy:stable
  services:
    - name: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
      alias: app
  script:
    - zap-full-scan.py -t http://app:8080 -r zap-report.html -I
  artifacts:
    paths:
      - zap-report.html

9. Мониторинг в Production

SAST и DAST обнаруживают уязвимости до деплоя. Но если уязвимость прошла все проверки (zero-day, логическая ошибка, Second-Order SQLi), нужен мониторинг в production.

WAF: ModSecurity с Core Rule Set

# nginx.conf с ModSecurity
load_module modules/ngx_http_modsecurity_module.so;

server {
    modsecurity on;
    modsecurity_rules_file /etc/modsecurity/main.conf;

    location / {
        proxy_pass http://go-app:8080;
    }
}
# modsecurity.conf — правила для SQLi
# CRS (Core Rule Set) включает ~50 правил для SQLi
SecRuleEngine On

# Правило 942100 — обнаружение SQL-инъекций через libinjection
# Правило 942110 — обнаружение SQL-инъекций (keyword detection)
# Правило 942120 — обнаружение SQL-операторов (UNION, SELECT, etc.)
# Правило 942150 — обнаружение SQL-функций (CONCAT, CHAR, etc.)

# Кастомное правило для SQLite (Go-лабы)
SecRule ARGS "@rx (?i)(sqlite_version|sqlite_master|randomblob)" \
  "id:100001,\
   phase:2,\
   block,\
   log,\
   msg:'SQLite-specific injection attempt',\
   severity:'CRITICAL'"

Логирование SQL-ошибок в Go

// middleware/sql_monitor.go
package middleware

import (
    "log/slog"
    "net/http"
    "strings"
)

// SQLErrorPatterns — паттерны, указывающие на попытку SQL-инъекции
var sqlErrorPatterns = []string{
    "syntax error",
    "SQLITE_ERROR",
    "unrecognized token",
    "near \"UNION\"",
    "near \"SELECT\"",
    "near \"OR\"",
    "no such column",
    "ambiguous column name",
}

func SQLInjectionMonitor(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // Проверяем параметры запроса на подозрительные паттерны
        for key, values := range r.URL.Query() {
            for _, v := range values {
                if containsSQLPattern(v) {
                    slog.Warn("Suspicious SQL pattern in request",
                        "param", key,
                        "value", v,
                        "ip", r.RemoteAddr,
                        "path", r.URL.Path,
                        "user_agent", r.UserAgent(),
                    )
                }
            }
        }
        next.ServeHTTP(w, r)
    })
}

func containsSQLPattern(s string) bool {
    lower := strings.ToLower(s)
    patterns := []string{
        "union select", "' or '1'='1", "'; drop table",
        "1=1", "' or 1=1", "sleep(", "benchmark(",
        "sqlite_version", "information_schema",
    }
    for _, p := range patterns {
        if strings.Contains(lower, p) {
            return true
        }
    }
    return false
}

Alerting: Prometheus + Grafana

// metrics/security.go
package metrics

import "github.com/prometheus/client_golang/prometheus"

var (
    SQLInjectionAttempts = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "security_sqli_attempts_total",
            Help: "Number of suspected SQL injection attempts",
        },
        []string{"endpoint", "source_ip"},
    )

    SQLErrorsTotal = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "security_sql_errors_total",
            Help: "Number of SQL errors (potential injection indicator)",
        },
        []string{"endpoint", "error_type"},
    )
)
# prometheus/alerts.yml
groups:
  - name: sql_injection
    rules:
      - alert: HighSQLInjectionRate
        expr: rate(security_sqli_attempts_total[5m]) > 10
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "High rate of SQL injection attempts"
          description: "{{ $labels.endpoint }} receiving {{ $value }} SQLi attempts/sec"

      - alert: SQLErrorSpike
        expr: rate(security_sql_errors_total[5m]) > 5
        for: 1m
        labels:
          severity: warning
        annotations:
          summary: "Spike in SQL errors"
          description: "Possible SQL injection probing at {{ $labels.endpoint }}"

10. Сравнительная таблица инструментов

Инструмент Категория SQLi Coverage False Positive Rate Скорость Цена
gosec (G201/G202) SAST Средний — прямая конкатенация/sprintf Низкий Очень быстрый (~2с) Бесплатный
Semgrep SAST Высокий — паттерны + taint (Pro) Очень низкий Быстрый (~10с) Community бесплатно
golangci-lint SAST Средний (через gosec) Низкий Быстрый (~5с) Бесплатный
sqlmap DAST Очень высокий — все типы SQLi Минимальный Медленный (~5-30мин) Бесплатный
OWASP ZAP DAST Высокий — error/blind/time-based Низкий Медленный (~15-30мин) Бесплатный
govulncheck SCA Зависимости Go Нет (точный) Быстрый (~3с) Бесплатный
Trivy SCA Зависимости + образы Низкий Быстрый (~10с) Бесплатный
ModSecurity CRS WAF Runtime — все типы Средний Реалтайм Бесплатный

Что каждый инструмент пропускает

Слепая зона Какой инструмент пропускает Кто ловит
Second-Order SQLi gosec, Semgrep Community sqlmap, ZAP, Semgrep Pro
Межпроцедурный taint gosec Semgrep Pro
Blind SQLi (time-based) Все SAST sqlmap, ZAP
SQLi через ORM raw queries gosec (частично) Semgrep с кастомными правилами
Zero-day в зависимостях govulncheck (до обновления БД) WAF, мониторинг
Логические SQLi (бизнес-логика) Все автоматические Code review, пентест

11. Чеклист эшелонированной защиты

Полная стратегия обнаружения SQL-инъекций в Go-проекте:

┌─────────────────────────────────────────────────────────┐
│  IDE (разработка)                                       │
│  └─ gopls + gosec integration + Semgrep LSP             │
├─────────────────────────────────────────────────────────┤
│  Pre-commit (локально)                                  │
│  └─ gosec G201/G202 + Semgrep .semgrep.yml              │
├─────────────────────────────────────────────────────────┤
│  CI/CD — SAST (каждый push)                             │
│  └─ golangci-lint (gosec) + Semgrep + govulncheck       │
├─────────────────────────────────────────────────────────┤
│  CI/CD — DAST (staging)                                 │
│  └─ sqlmap (level=3) + OWASP ZAP full scan              │
├─────────────────────────────────────────────────────────┤
│  CI/CD — SCA (каждый push)                              │
│  └─ govulncheck + Trivy image scan                      │
├─────────────────────────────────────────────────────────┤
│  Production — WAF                                       │
│  └─ ModSecurity CRS + кастомные SQLite-правила          │
├─────────────────────────────────────────────────────────┤
│  Production — Мониторинг                                │
│  └─ SQL error logging + Prometheus alerts + slog        │
└─────────────────────────────────────────────────────────┘

Финальный чеклист

  • gosec G201/G202 включены в golangci-lint и CI pipeline
  • Semgrep с Go-правилами и кастомными .semgrep.yml запускается на каждый PR
  • govulncheck проверяет зависимости на известные CVE
  • Trivy сканирует Docker-образы перед деплоем
  • sqlmap тестирует все эндпоинты с пользовательским вводом на staging
  • OWASP ZAP выполняет full scan на staging перед release
  • WAF (ModSecurity) с CRS защищает production
  • SQL-ошибки логируются через slog и мониторятся в Prometheus/Grafana
  • Pre-commit хуки установлены у всех разработчиков
  • #nosec аннотации проходят обязательный code review
  • SARIF-отчёты загружаются в GitHub Security tab для отслеживания трендов
  • Регулярный пентест (раз в квартал) проверяет то, что автоматика не поймает

Дополнительные материалы

Продолжить чтение

Что бы прочитать модуль полностью, зарегистрируйтесь/войдите на платформу

Когда закончишь — отметь раздел, чтобы продолжить.

🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru