Мобильное приложение, обрабатывающее платежи, обязано соответствовать стандарту PCI DSS. Эквайер требует подтверждения безопасности, а код часто содержит уязвимости: PAN в логах, отсутствие certificate pinning, возможность снятия скриншотов экрана с картой. Наша команда помогает привести приложение к актуальной версии стандарта и пройти аудит QSA с гарантией соответствия. За годы работы мы реализовали более 50 проектов мобильной безопасности.
Почему PCI DSS критичен для мобильных приложений
PCI DSS — стандарт Совета по безопасности платёжных карт, обязательный для любого ПО, передающего, обрабатывающего или хранящего данные держателей карт. Для мобильных приложений особенно важны раздел 6 (Secure Development) и раздел 4 (Encryption in Transit). Без соответствия крупные эквайеры не разрешают прямой эквайринг — только iFrame-решения с ограниченным функционалом.
Типичные нарушения и их исправление
Хранение PAN в логах
Разработчик добавляет Log.d("Payment", "Card: $cardNumber") для отладки. Данные попадают в logcat, читаемый любым приложением на незащищённом Android. PCI DSS требование 3.3: PAN не должен отображаться в логах в незашифрованном виде. Правильное решение — маскировка PAN и ведение логов только операций без карточных данных.
Отсутствие защиты экрана
Android по умолчанию позволяет снимать скриншоты любого Activity. На экране ввода реквизитов это критическая уязвимость:
// Должно быть на любом экране с карточными данными window.setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE ) На iOS аналогично — нужно перекрывать UI при переходе в background:
func applicationWillResignActive(_ application: UIApplication) { coverSensitiveContent() } Certificate pinning не настроен
Трафик к платёжному серверу перехватывается Charles Proxy или mitmproxy без препятствий. PCI DSS 6.5.4 требует защиты от man-in-the-middle. Реализация на iOS:
class PinnedURLSessionDelegate: NSObject, URLSessionDelegate { func urlSession( _ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void ) { guard let serverTrust = challenge.protectionSpace.serverTrust, let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else { completionHandler(.cancelAuthenticationChallenge, nil) return } let pinnedHash = "sha256/AbCdEfGhIjKlMnOpQrStUvWxYz123456789=" let serverHash = certificateHash(certificate) if serverHash == pinnedHash { completionHandler(.useCredential, URLCredential(trust: serverTrust)) } else { completionHandler(.cancelAuthenticationChallenge, nil) } } } Root/Jailbreak detection
PCI DSS 6.4.3 рекомендует обнаруживать скомпрометированные устройства. Используем комбинацию: проверка наличия /bin/bash, Cydia, команды su, несовпадение подписи процесса. Крупные эквайеры требуют этого через SDK.
Почему токенизация — главный инструмент для PCI DSS?
Главный принцип — не хранить PAN вообще. Приложение работает с токеном от платёжного провайдера: Stripe PaymentMethod, CloudPayments Token, ЮKassa payment_method_id. Токенизация снижает scope PCI DSS с SAQ D до SAQ A — это упрощает аудит в 20 раз по сравнению с хранением карточных данных. Штрафы за утечку PAN могут достигать 500 000 $ в квартал, а экономия на аудите за счёт правильного scoping — до 250 000 ₽.
import StripePaymentSheet var configuration = PaymentSheet.Configuration() configuration.merchantDisplayName = "YourShop" PaymentSheet.FlowController.create( paymentIntentClientSecret: clientSecret, configuration: configuration ) { [weak self] result in switch result { case .success(let flowController): self?.paymentSheetFlowController = flowController case .failure(let error): // обрабатываем } } Карточные данные уходят напрямую в Stripe SDK, приложение получает paymentMethodId. PAN никогда не касается вашего сервера.
Audit trail и логирование
PCI DSS требование 10: логировать доступ к cardholder data environment. Для мобильного приложения:
- Логировать каждый успешный/неуспешный платёж с timestamp, userId, замаскированным PAN (первые 6 + последние 4 цифры), статусом.
- Логи хранить не менее 12 месяцев, из которых 3 — немедленно доступны.
- Защитить логи от модификации (append-only storage).
Маскировка PAN в логах:
fun maskPan(pan: String): String { return pan.take(6) + "*".repeat(pan.length - 10) + pan.takeLast(4) } // "4111111111111111" → "411111******1111" Что такое scoping и зачем он нужен?
Выбор типа SAQ напрямую влияет на объём аудита. Сравнение SAQ A и SAQ D:
| Параметр | SAQ A | SAQ D |
|---|---|---|
| Scope | Только токенизация | Полное CDE |
| Количество требований | 13 | 250+ |
| Трудоёмкость аудита | 2-3 дня | 3-4 недели |
| Стоимость приведения | Низкая | Высокая |
Правильная токенизация и аутсорсинг обработки карт (Stripe, CloudPayments) позволяют претендовать на SAQ A. Экономия на аудите может превышать стоимость доработок.
Процесс работы: 5 шагов к соответствию
| Этап | Длительность | Результат |
|---|---|---|
| Scoping | 1 день | Определены границы CDE, выбран тип SAQ |
| Gap-анализ | 2-3 дня | Список несоответствий по 12 требованиям |
| Remediation | 1-3 недели | Исправление уязвимостей: certificate pinning, FLAG_SECURE, шифрование local storage |
| Penetration testing | 3-5 дней | Статический (MobSF) и динамический анализ, проверка binary reversing |
| Подготовка к QSA-аудиту | 2 дня | Документация, отчёты, рекомендации |
Реализация certificate pinning на iOS: пошаговая инструкция
- Получить сертификат сервера (DER).
- Вычислить SHA-256 хеш сертификата.
- Создать делегат
URLSessionDelegateс проверкой хеша. - Зашить хеш в код как константу.
- При каждом запросе сравнивать хеш сервера с зашитым.
- При несовпадении — разрывать соединение.
Эта последовательность гарантирует защиту от MITM-атак. На Android certificate pinning проще реализовать через NetworkSecurityConfig. Достаточно добавить XML-конфиг в res/xml/network_security_config.xml с перечислением pin-сертификатов. Однако для большей гибкости используем OkHttp с CertificatePinner.
Что входит в работу
- Полный gap-анализ кодовой базы и инфраструктуры (выявляем все несоответствия)
- Внедрение certificate pinning на iOS и Android с учётом версий и конфигов
- Защита экранов ввода карты (FLAG_SECURE, overlay prevention)
- Настройка токенизации через Stripe/CloudPayments
- Реализация root/jailbreak detection с несколькими проверками
- Аудит логов и внедрение маскировки PAN
- Консультация по SAQ и прохождению QSA-аудита
Ориентировочные сроки
Аудит и базовое исправление — от 2 до 4 недель. Полный цикл с pen-тестированием и подготовкой к QSA — до 6 недель. Стоимость рассчитывается индивидуально после анализа текущего состояния.
Закажите предварительный аудит — оценим объём работ и сроки за 2 дня нашей команды. Свяжитесь для консультации, и мы поможем подготовить приложение к сертификации. Гарантируем соответствие стандарту и прохождение внешнего аудита.
Получите оценку вашего приложения за 2 дня — напишите нам.







