Валидация гипотез безопасности

Валидация гипотез безопасности

Технический документ для архитекторов безопасности и исследователей


Содержание

Аннотация

Традиционные инструменты SAST (Static Application Security Testing) страдают от высокого уровня ложных срабатываний (до 70-90%), что делает результаты анализа практически неприменимыми для реальной работы. CodeGraph решает эту проблему с помощью многокритериальной системы валидации гипотез, которая:

  1. Генерирует тестируемые гипотезы на основе CWE/CAPEC баз знаний
  2. Оценивает гипотезы по трём критериям с учётом контекста кодовой базы
  3. Верифицирует уязвимости через анализ потоков данных на графе свойств кода (CPG)
  4. Достигает 100% обнаружения CVE при снижении доли ложных срабатываний с 70–90% до менее 30% (снижение на 60%+)

1. Проблема

1.1 Ограничения традиционного SAST

Традиционный SAST:
  Обнаружен шаблон: "strcpy"
  Результат: ВОЗМОЖНАЯ уязвимость
  Частота ложных срабатываний: 70-90%

CodeGraph:
  Гипотеза: Ненадежные потоки данных от recv() к strcpy()
  Доказательство: Путь к источнику заражения проверен с помощью CPG
  Результат: Уязвимость ПОДТВЕРЖДЕНА
  Частота ложных срабатываний: <30%

1.2 Почему сопоставления шаблонов недостаточно

Проблема Описание
Нет контекста strcpy безопасен, если источник — константа
Нет анализа потоков данных Не учитывается откуда приходят данные
Нет санитизации Игнорируются функции-валидаторы
Нет приоритизации Все находки имеют равный вес

2. Архитектура решения

2.1 Конвейер валидации гипотез

┌─────────────────────────────────────────────────────────────────────────┐
│                  КОНВЕЙЕР ВАЛИДАЦИИ ГИПОТЕЗ                              │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │ 1. ГЕНЕРАЦИЯ                                                    │   │
│  │    HypothesisGenerator.generate()                               │   │
│  │    ├── База CWE (58 записей)                                   │   │
│  │    ├── База CAPEC (27 паттернов атак)                          │   │
│  │    ├── Языковые шаблоны (C, Python, Java)                      │   │
│  │    └── Декартово произведение: CWE × CAPEC × Шаблоны            │   │
│  │    Результат: SecurityHypothesis[]                              │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                              │                                          │
│                              ▼                                          │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │ 2. МНОГОКРИТЕРИАЛЬНЫЙ СКОРИНГ                                   │   │
│  │    MultiCriteriaScorer.score_batch()                           │   │
│  │                                                                  │   │
│  │    Оценка = Частота_CWE×0.40 + Сходство_атак×0.30 + Подверж.×0.30│  │
│  │                                                                  │   │
│  │    Бонусы:                                                      │   │
│  │    ├── Известный шаблон CVE: ×1.20                             │   │
│  │    ├── Критическая серьёзность: ×1.10                          │   │
│  │    └── Недавний эксплойт: ×1.15                                │   │
│  │                                                                  │   │
│  │    Результат: Приоритизированные гипотезы                       │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                              │                                          │
│                              ▼                                          │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │ 3. СИНТЕЗ ЗАПРОСОВ                                              │   │
│  │    QuerySynthesizer.synthesize()                                │   │
│  │    ├── Сопоставление гипотезы с SQL-шаблоном                   │   │
│  │    ├── Подстановка параметров                                  │   │
│  │    └── Результат: DuckDB SQL / PGQ-запросы                     │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                              │                                          │
│                              ▼                                          │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │ 4. ВЫПОЛНЕНИЕ                                                   │   │
│  │    HypothesisExecutor.execute()                                 │   │
│  │    ├── Выполнение запросов к CPG                                │   │
│  │    ├── Сбор доказательств                                      │   │
│  │    └── Результат: Evidence[]                                   │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                              │                                          │
│                              ▼                                          │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │ 5. ВАЛИДАЦИЯ                                                    │   │
│  │    HypothesisValidator.validate()                               │   │
│  │    ├── Анализ доказательств                                    │   │
│  │    ├── Обновление статуса (ПОДТВЕРЖДЕНА/ОТКЛОНЕНА)             │   │
│  │    └── Расчёт метрик точности/полноты                          │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

3. Многокритериальная модель скоринга

3.1 Формула приоритизации

Оценка приоритета = (Частота_CWE × 0.40)
                   + (Сходство_атак × 0.30)
                   + (Подверженность_кодовой_базы × 0.30)

3.2 Компоненты скоринга

Оценка частоты CWE (40%)

Оценивает, насколько часто данная уязвимость встречается в реальных CVE.

def _score_cwe_frequency(cwe_ids: List[str]) -> float:
    """
    Компоненты:
    - prevalence: Частота в базе CVE (0.0-1.0)
    - exploitability: Насколько легко эксплуатировать (0.0-1.0)
    - cvss_base: Базовый балл CVSS / 10 (0.0-1.0)

    Оценка = prevalence × 0.4 + exploitability × 0.4 + cvss × 0.2
    """
CWE Распространённость Эксплуатируемость CVSS Оценка
CWE-120 (переполнение буфера) 0.85 0.90 8.0 0.86
CWE-78 (внедрение команд) 0.75 0.95 9.8 0.88
CWE-89 (SQL-инъекция) 0.90 0.95 9.8 0.94
CWE-200 (раскрытие информации) 0.60 0.70 5.3 0.63

Оценка сходства с атакой (30%)

Оценивает, насколько гипотеза соответствует известным шаблонам атак из CAPEC.

def _score_attack_similarity(capec_ids: List[str]) -> float:
    """
    Компоненты:
    - likelihood: Вероятность атаки (0.0-1.0)
    - skill_level: Требуемый уровень навыков
      - Низкий: ×1.0 (выше риск)
      - Средний: ×0.8
      - Высокий: ×0.6
      - Экспертный: ×0.4 (ниже риск)

    Оценка = likelihood × skill_adjustment
    """

Оценка подверженности кодовой базы (30%)

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

def _score_codebase_exposure(hypothesis) -> float:
    """
    Компоненты:
    - sink_exposure: Наличие опасных функций-приёмников
    - source_exposure: Наличие источников внешних данных
    - sanitizer_coverage: Наличие функций-санитайзеров (понижает риск)
    - taint_paths: Количество путей источник → приёмник

    Подверженность = (sink × 0.4 + source × 0.4) × (1 - sanitizer × 0.5)
    """

3.3 Бонусные множители

Бонус Множитель Условие
Известный CVE ×1.20 Шаблон соответствует известному CVE
Критическая серьёзность ×1.10 CWE имеет критический уровень
Недавний эксплойт ×1.15 Недавняя эксплуатация в реальных атаках

4. Статистика кодовой базы

4.1 Сбор статистики из CPG

@dataclass
class CodebaseStats:
    total_methods: int        # Общее количество методов
    total_calls: int          # Общее количество вызовов

    sink_counts: Dict[str, int]       # приёмник → количество
    source_counts: Dict[str, int]     # источник → количество
    sanitizer_counts: Dict[str, int]  # санитайзер → количество

    taint_paths: int          # Количество путей источник→приёмник

4.2 Отслеживаемые функции

Опасные приёмники (C):

strcpy, strcat, sprintf, gets, memcpy
system, popen, execl, execv
printf, fprintf (форматная строка)
appendPQExpBuffer, SPI_execute, PQexec (PostgreSQL)

Недоверенные источники:

recv, read, fgets, getenv
PQgetvalue, SPI_getvalue, getTables (PostgreSQL)

Санитайзеры:

strlcpy, snprintf
fmtId, quote_identifier, quote_literal
pg_class_aclcheck

5. Анализ потоков данных на CPG

5.1 Верификация потока данных

-- Поиск непроверенных путей от source к sink
FROM GRAPH_TABLE(cpg
    MATCH (src:CALL)-[:REACHING_DEF*1..10]->(sink:CALL)
    WHERE src.name IN ('recv', 'getenv', 'PQgetvalue')
      AND sink.name IN ('strcpy', 'sprintf', 'system')
    COLUMNS (
        src.name AS source,
        sink.name AS sink,
        sink.filename,
        sink.line_number
    )
)

5.2 Проверка санитизации

-- Проверка наличия санитайзеров на пути
SELECT h.id, h.source, h.sink,
       EXISTS (
           SELECT 1 FROM nodes_call nc
           WHERE nc.name IN ('strlcpy', 'snprintf', 'quote_identifier')
             AND nc.line_number BETWEEN h.source_line AND h.sink_line
             AND nc.filename = h.filename
       ) AS has_sanitizer
FROM hypothesis_paths h;

6. Результаты валидации

6.1 Тестирование на PostgreSQL 17

Метрика Значение
Доля обнаружения CVE 100% (3/3)
Доля подтверждения гипотез 55%
Среднее время запроса 2–3 мс
Время генерации (100 гип.) <1 сек
Время выполнения (20 гип.) <30 сек

6.2 Обнаруженные CVE

CVE ID Тип Метод обнаружения
CVE-2025-8713 Раскрытие статистики Гипотеза + анализ потоков
CVE-2025-8714 Инъекция pg_dump На основе методов
CVE-2025-8715 Инъекция переноса строки На основе методов

6.3 Сравнение с традиционным SAST

Инструмент Истинные срабатывания Ложные срабатывания Точность
Шаблонный SAST 3 45 6.25%
CodeGraph 3 2 60%
TaintVerifiedScanner 3 0.4 88% (12% FP)

7. Структура гипотезы

7.1 SecurityHypothesis

@dataclass
class SecurityHypothesis:
    id: str                          # Уникальный идентификатор
    hypothesis_text: str             # Текст гипотезы

    # Классификация
    cwe_ids: List[str]              # ["CWE-120", "CWE-119"]
    capec_ids: List[str]            # ["CAPEC-100"]
    language: str                   # "C", "Python"
    category: str                   # "buffer_overflow"

    # Шаблоны потоков данных
    source_patterns: List[str]      # ["PQgetvalue", "getenv"]
    sink_patterns: List[str]        # ["strcpy", "memcpy"]
    sanitizer_patterns: List[str]   # ["strlcpy", "sizeof"]

    # Скоринг
    priority_score: float           # 0.0-1.0+
    confidence: float               # 0.0-1.0

    # Многокритериальная разбивка
    cwe_frequency_score: float
    attack_similarity_score: float
    codebase_exposure_score: float

    # Валидация
    sql_query: Optional[str]
    evidence: List[Evidence]
    validation_status: ValidationStatus

7.2 Формат гипотезы

"Если недоверенные данные из {источники} поступают в {приёмники}
 без санитизации через {санитайзеры},
 то {cwe_id} делает возможной атаку {capec_id},
 потенциально приводя к {последствия}."

Пример:

"Если недоверенные данные из PQgetvalue() поступают в strcpy()
 без проверки границ через strlcpy(),
 то CWE-120 делает возможной атаку CAPEC-100 (переполнение буфера),
 потенциально приводя к повреждению памяти или выполнению кода."

8. API для интеграции

8.1 Полный пример

from src.security.hypothesis import (
    HypothesisGenerator,
    MultiCriteriaScorer,
    QuerySynthesizer,
    HypothesisExecutor,
    HypothesisValidator,
    CodebaseStats,
    compute_codebase_stats_from_duckdb
)
import duckdb
from src.project_manager import ProjectManager

# 1. Подключение к CPG
conn = duckdb.connect(ProjectManager.get_active_db_path())

# 2. Сбор статистики кодовой базы
stats = compute_codebase_stats_from_duckdb(ProjectManager.get_active_db_path())

# 3. Генерация гипотез
generator = HypothesisGenerator()
hypotheses = generator.generate(
    language="C",
    cwe_filter=["CWE-120", "CWE-78", "CWE-89"],
    max_hypotheses=100
)

# 4. Многокритериальный скоринг
scorer = MultiCriteriaScorer(codebase_stats=stats)
scored = scorer.score_batch(hypotheses)

# 5. Синтез SQL-запросов
synthesizer = QuerySynthesizer()
for h in scored:
    h.sql_query = synthesizer.synthesize_query(h)

# 6. Выполнение на CPG
executor = HypothesisExecutor(conn)
for h in scored[:20]:  # Top 20
    evidence = executor.execute(h)
    h.evidence.extend(evidence)

# 7. Валидация и отчёт
validator = HypothesisValidator()
results = validator.validate_batch(scored)

print(f"Доля обнаружения: {results.detection_rate:.1%}")
print(f"Точность: {results.precision:.1%}")
print(f"F1-мера: {results.f1_score:.2f}")

9. Заключение

Многокритериальная система валидации гипотез CodeGraph представляет собой принципиально новый подход к поиску уязвимостей:

  1. Контекстуальный анализ — учёт специфики конкретной кодовой базы
  2. Верификация потоков данных — подтверждение потока данных через CPG
  3. Приоритизация по риску — фокус на реально эксплуатируемых уязвимостях
  4. Снижение ложных срабатываний — от 70-90% до менее 30%

Результат: 100% обнаружение целевых CVE при драматическом снижении ложных срабатываний.

Визуализация потоков данных и интеграция с SARIF

Подтверждённые гипотезы могут быть экспортированы с полной визуализацией путей потоков данных: - Mermaid-диаграммы (src/security/taint_visualizer.py) отображают потоки данных от источника к приёмнику в виде интерактивных диаграмм - Экспорт SARIF 2.1.0 (src/security/sarif_exporter.py) включает codeFlows с пошаговым распространением потоков данных - Маппинг OWASP Top 10 (src/security/owasp_mapping.py) классифицирует находки для отчётности по соответствию

Проверка достижимости путей через z3

Движок символьного исполнения z3 валидирует ограничения путей для подтверждённых гипотез, исключая недостижимые пути и дополнительно снижая ложные срабатывания. Это особенно эффективно для условных уязвимостей, где эксплуатация зависит от определённых диапазонов входных данных или конфигурации.


Связанные документы


Версия: 1.1 | Февраль 2026