Валидация гипотез безопасности¶
Технический документ для архитекторов безопасности и исследователей
Содержание¶
- Аннотация
- 1. Проблема
- 1.1 Ограничения традиционного SAST
- 1.2 Почему сопоставления шаблонов недостаточно
- 2. Архитектура решения
- 2.1 Конвейер валидации гипотез
- 3. Многокритериальная модель скоринга
- 3.1 Формула приоритизации
- 3.2 Компоненты скоринга
- 3.3 Бонусные множители
- 4. Статистика кодовой базы
- 4.1 Сбор статистики из CPG
- 4.2 Отслеживаемые функции
- 5. Анализ потоков данных на CPG
- 5.1 Верификация потока данных
- 5.2 Проверка санитизации
- 6. Результаты валидации
- 6.1 Тестирование на PostgreSQL 17
- 6.2 Обнаруженные CVE
- 6.3 Сравнение с традиционным SAST
- 7. Структура гипотезы
- 7.1 SecurityHypothesis
- 7.2 Формат гипотезы
- 8. API для интеграции
- 8.1 Полный пример
- 9. Заключение
- Связанные документы
Аннотация¶
Традиционные инструменты SAST (Static Application Security Testing) страдают от высокого уровня ложных срабатываний (до 70-90%), что делает результаты анализа практически неприменимыми для реальной работы. CodeGraph решает эту проблему с помощью многокритериальной системы валидации гипотез, которая:
- Генерирует тестируемые гипотезы на основе CWE/CAPEC баз знаний
- Оценивает гипотезы по трём критериям с учётом контекста кодовой базы
- Верифицирует уязвимости через анализ потоков данных на графе свойств кода (CPG)
- Достигает 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 представляет собой принципиально новый подход к поиску уязвимостей:
- Контекстуальный анализ — учёт специфики конкретной кодовой базы
- Верификация потоков данных — подтверждение потока данных через CPG
- Приоритизация по риску — фокус на реально эксплуатируемых уязвимостях
- Снижение ложных срабатываний — от 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