Мобільний застосунок, що обробляє платежі, зобов'язаний відповідати стандарту 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 дні — напишіть нам.







