Среда, 10:40. Code review мобильного приложения платёжного сервиса - 200 тысяч транзакций в сутки. Открываю декомпилированный APK в jadx, перехожу к классу
PaymentCryptoHelper - и через 12 минут смотрю на AES-256 ключ, вшитый строковой константой. Формально всё по стандартам: AES, 256 бит, CBC-режим. А на практике этот ключ одинаков для каждой установки приложения и извлекается через apktool за минуту. По классификации OWASP, Cryptographic Failures (A02:2021) - вторая строчка в рейтинге рисков веб-приложений, а штрафы по GDPR за утечку данных, зашифрованных "для вида", достигают 4% глобальной годовой выручки компании. Ниже - полная методика аудита криптографии в приложениях: от статического анализа до detection-правил для SIEM и готового чеклиста для отчёта.Таксономия криптографических уязвимостей и маппинг на MITRE ATT&CK
Перед запуском сканеров стоит зафиксировать, что именно ищем. Криптографические уязвимости приложений разбиваются на три категории - у каждой свой профиль риска и свои техники эксплуатации.Слабые криптографические алгоритмы (CWE-327). MD5, SHA-1, DES, RC4, 3DES - алгоритмы, чья стойкость опровергнута практическими атаками. MD5-коллизии генерируются за секунды на обычном ноутбуке, SHA-1 сломана атакой SHAttered. Если приложение использует их для хеширования паролей или проверки целостности - это иллюзия защиты, красивый фантик без конфеты. Согласно описанию OWASP A02:2021, использование deprecated hash functions вроде MD5 или SHA-1 - прямой индикатор cryptographic failure.
Hardcoded ключи и пароли (CWE-259, CWE-321). Ключи шифрования, API-токены, пароли для СУБД, зашитые в исходный код или конфигурационные файлы. Атакующий применяет технику Credentials In Files (T1552.001, Credential Access) или Private Keys (T1552.004, Credential Access) по MITRE ATT&CK и получает доступ без перебора. Здесь же - секреты в git-истории: разработчик удалил ключ из
main, но он живёт в истории коммитов. Классика.Ошибки реализации и недостаточная энтропия (CWE-331). ECB-режим шифрования, CBC без проверки целостности, слабые PRNG (
Math.random() вместо SecureRandom), повторное использование IV/nonce. Эта категория самая коварная: формально алгоритм "правильный" - AES-256, RSA-2048, - но реализация обнуляет криптографическую стойкость.Отдельно стоит техника Weaken Encryption (T1600, Defense Impairment) и подтехника Reduce Key Space (T1600.001) - целенаправленное понижение стойкости. Классический пример - FREAK-атака (CVE-2015-0204): функция
ssl3_get_key_exchange в клиентском коде OpenSSL позволяла уязвимому клиенту принять слабый эфемерный RSA-ключ от сервера, что давало MitM-атакующему возможность понизить стойкость соединения до 512-битного экспортного RSA, взламываемого за часы (scope CVE - только клиентский код OpenSSL). Затронуты версии OpenSSL до 0.9.8zd, 1.0.0p и 1.0.1k.Бизнес-логика атаки. Hardcoded ключ в мобильном приложении = расшифровка трафика всех пользователей. Небезопасные алгоритмы шифрования паролей = Password Cracking (T1110.002, Credential Access; задокументированные тесты - для Windows, но техника применима кроссплатформенно) с выходом на массовый credential stuffing. Ошибка реализации TLS = MitM с перехватом платёжных данных. Скомпрометированный разработчик или insider, намеренно ослабляющий криптографию - тоже реалистичный сценарий, и detection для него строится по тем же индикаторам.
Статический анализ криптографии: инструменты и правила поиска
Требования к окружению: ОС GNU/Linux (Ubuntu 22.04+) или macOS; Windows через WSL2. RAM от 4 ГБ для мобильных приложений, от 8 ГБ для крупных кодовых баз. Python 3.8+ (semgrep, TruffleHog), Java 11+ (jadx, apktool для Android APK). Все инструменты работают локально, без облачных зависимостей.
semgrep: кастомные правила для криптоаудита
semgrep (активно поддерживается, Semgrep Inc, ~10k stars на GitHub) - SAST-инструмент с кастомными YAML-правилами. Стандартный наборp/security-audit ловит часть криптографических ошибок, но для полноценного поиска уязвимостей шифрования этого мало - нужны собственные правила.Пример правила для поиска MD5, SHA-1 и DES в Java:
YAML:
rules:
- id: weak-crypto-algorithm
patterns:
- pattern-either:
- pattern: MessageDigest.getInstance("MD5")
- pattern: MessageDigest.getInstance("SHA-1")
- pattern: Cipher.getInstance("DES/...")
message: "Weak crypto: $MATCH"
severity: ERROR
languages: [java]
semgrep --config ./crypto-rules.yml ./src/ - проходит кодовую базу за минуты. Для Python аналогично: паттерны hashlib.md5(), hashlib.sha1(), from Crypto.Cipher import DES. Для Go - crypto/des, crypto/md5 в импортах.[Применимо: code review, CI/CD pipeline, внутренний аудит. Не заменяет ручной анализ бизнес-логики шифрования.]
TruffleHog и git-secrets: охота за секретами в репозиториях
TruffleHog (Truffle Security Co, активно поддерживается, ~17k stars на GitHub) сканирует всю историю коммитов, а не только текущее состояние. Разработчик мог удалить ключ из кода месяц назад - а он всё ещё вgit log, ждёт своего часа.Запуск по локальному репозиторию:
trufflehog git file://./repo --only-verified. Флаг --only-verified проверяет, что найденные ключи реально рабочие - делает тестовый запрос к API провайдера (AWS, GCP, Stripe и т.д.).Для pre-commit блокировки - git-secrets (AWS, активно поддерживается):
git secrets --install && git secrets --register-aws. Кастомные паттерны: git secrets --add 'PRIVATE.KEY'. Каждый заблокированный коммит - событие для SOC: кто коммитил, какой секрет, куда он мог утечь до блокировки. В зрелых организациях это отдельный поток алертов в SIEM.Ограничения статического анализа
Статический анализ криптографии не ловит:- Ключи, загружаемые из Vault/KMS в рантайме - это как раз правильная реализация, ложных срабатываний не будет
- Криптографические проблемы в скомпилированных зависимостях - для этого нужен SCA (OWASP Dependency-Check, Snyk)
- Динамически формируемые строки: если алгоритм выбирается через
String algo = getConfig("crypto.algo"), semgrep не увидит конкретное значение - Ошибки в бизнес-логике: например, шифрование данных на стороне клиента с передачей ключа по тому же каналу
Ошибки реализации криптографии: ECB, padding oracle, слабые PRNG
Эта категория - основной источник находок на реальных аудитах. Приложение использует AES-256 или RSA-2048, compliance-отчёт чист, но ошибка реализации обнуляет стойкость. Я бы сказал, что 70% моих находок за последние два года - именно отсюда.
ECB-режим шифрования. ECB (Electronic Codebook) шифрует каждый блок независимо одним ключом. Одинаковые блоки открытого текста дают одинаковые блоки шифротекста - паттерны данных сохраняются полностью. В банковском приложении это означает: повторяющиеся номера счетов или суммы видны в зашифрованном трафике без расшифровки. По сути, это шифрование "в чём мать родила" - формально одето, но всё видно. Поиск в коде - паттерн
Cipher.getInstance("AES/ECB/...") для Java, AES.new(key, AES.MODE_ECB) для Python.
YAML:
- id: aes-ecb-mode
pattern: Cipher.getInstance("AES/ECB/$PADDING")
message: "ECB mode preserves data patterns - use GCM"
severity: ERROR
languages: [java]
Что искать в коде:
Cipher.getInstance("AES/CBC/PKCS5Padding") без последующей HMAC-верификации. Правильная замена - AES/GCM/NoPadding, где аутентификация встроена в режим.Слабые PRNG и предсказуемые ключи.
Math.random() в Java, random.random() в Python, rand() в C - не криптографически стойкие генераторы. Если они формируют IV, nonce или ключевой материал - стойкость шифрования падает до предсказуемости PRNG. Поиск: semgrep-паттерн new Random() в контексте криптографических операций, Math.random() рядом с Cipher или Key.Уязвимость ROCA (CVE-2017-15361) - радикальный пример. Библиотека Infineon RSA library 1.02.013 для генерации ключей в TPM использовала детерминированный процесс, из-за которого RSA-ключи до 4096 бит поддавались факторизации. Затронуты Infineon TPM (версии firmware до 0000000000000422 - 4.34, до 000000000000062b - 6.43, до 0000000000008521 - 133.33), YubiKey 4 (до версии 4.3.5), Acer C720 Chromebook и другие устройства с этим чипом. Кейс показательный: даже аппаратная реализация не гарантирует безопасность при дефектной генерации ключей.
Detection криптографических аномалий в SIEM
Аудит кода находит проблемы до продакшена. Для уже развёрнутых приложений работает мониторинг на уровне сети и инфраструктуры - и здесь пентест криптографии пересекается с задачами SOC.Мониторинг TLS-версий и cipher suites. Подключения по TLS 1.0/1.1 или с cipher suites на базе RC4, DES, 3DES - IOC на уровне сетевого трафика. В Elastic SIEM (8.x+) фильтрация по полям
tls.version и tls.cipher - нужен Filebeat с модулем TLS или Zeek/Suricata как источник парсинга handshake. В MaxPatrol SIEM - корреляция событий сетевого трафика с фильтром по версии протокола. Базовое правило:
Код:
rule: weak_tls_detected
condition:
tls.version in ["TLSv1.0","TLSv1.1","SSLv3"]
OR tls.cipher contains ["RC4","DES","3DES","NULL"]
severity: high
action: alert + enrich(src_ip, dst_ip, server_name)
Аномалии сертификатов. RSA-ключи менее 2048 бит на серверных сертификатах, самоподписанные сертификаты на продуктивных сервисах, истёкшие сертификаты - индикаторы TLS мисконфигурации. Периодический скан через
openssl s_client -connect host:443 с парсингом вывода. Результаты - в SIEM как baseline для алертинга при деградации.Детекция секретов в CI/CD. TruffleHog или Gitleaks в пайплайне генерируют события для SOC. Каждый заблокированный коммит с hardcoded ключом в коде - инцидент: нужно разобрать, куда секрет мог утечь до блокировки, не был ли ключ уже использован. Это отдельный поток алертов, коррелирующий с событиями доступа к репозиториям.
Insider threat / скомпрометированный разработчик. Намеренное ослабление криптографии (T1600, Defense Impairment) - редкий, но реальный сценарий. Индикатор: коммит, заменяющий AES-GCM на ECB или добавляющий hardcoded ключ в production-ветку. Detection: вебхук на diff-анализ криптографических паттернов в merge requests, интегрированный с SIEM. Коммит из нетипичной геолокации или в нерабочее время + изменение криптографической логики = алерт высокого приоритета.
Чеклист аудита криптографии в приложениях
Готовый чеклист для включения в отчёт или передачи команде разработки. Каждый пункт - конкретное действие с командой или инструментом.
📚 Часть контента скрыта. Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Заключение
Большинство криптографических проблем, которые я нахожу на реальных проектах, - не слабый алгоритм. Это AES-256 с ключом в git-репозитории, GCM с повторяющимся nonce, "временный" self-signed сертификат на проде третий год подряд. Индустрия зациклена на длине ключей и названиях алгоритмов, а реальные атаки эксплуатируют ошибки реализации - CWE-259 (hardcoded password, likelihood: High по классификации MITRE CWE), CWE-329 (отсутствие random IV), CWE-331 (недостаточная энтропия). Анализ безопасности криптографии на бумаге - одно, а то, что в коде, - принципиально другое. Самый результативный шаг, который я видел в командах - не покупка enterprise SAST за миллионы, а три semgrep-правила в pre-commit hook с запретом мерджа при срабатывании. Час на настройку, закрывает основную массу находок на входе. Остальное добирает TruffleHog в CI/CD и SIEM-правило на слабый TLS. Если интересно, как коллеги автоматизируют такой криптоаудит в CI/CD и делятся рабочими semgrep-конфигами под конкретные стеки, - на codeby.net есть тред по автоматизации code review с примерами для Java, Python и Go.
Последнее редактирование модератором: