Розробник нового стартапу вирішує «зекономити час» та зберегти номери карток клієнтів у власній базі даних — без шифрування, для «майбутніх повторних покупок». Через рік стається витік. Компанія отримує штраф від Visa/Mastercard у розмірі від $50,000 до $500,000, втрачає право приймати картки та зазнає репутаційної катастрофи.
Це не гіпотетичний сценарій — це реальна модель покарання у платіжній індустрії. Стандарт PCI DSS (Payment Card Industry Data Security Standard) існує саме для того, щоб такі ситуації не виникали. І знаємо щось, що полегшить вашу відповідальність: більшість розробників ніколи не повинні бачити дані карток.
PCI DSS (Payment Card Industry Data Security Standard) — це набір вимог безпеки, розроблених спільно Visa, Mastercard, American Express, Discover та JCB у рамках організації PCI Security Standards Council (PCI SSC). Стандарт застосовується до всіх організацій, які зберігають, обробляють або передають дані платіжних карток.
Поточна версія — PCI DSS 4.0 (вийшла у березні 2022 року, обов'язкова з березня 2024 року).
Стандарт складається з 12 основних вимог, згрупованих у 6 цілей:
| Мета | Вимоги |
|---|---|
| Побудова та підтримка захищеної мережі | 1. Мережеві засоби захисту, 2. Безпечна конфігурація |
| Захист даних власника картки | 3. Захист збережених даних, 4. Шифрування при передачі |
| Управління вразливостями | 5. Захист від шкідливого ПЗ, 6. Безпечна розробка |
| Сильний контроль доступу | 7. Обмеження доступу, 8. Ідентифікація та автентифікація, 9. Фізичний захист |
| Моніторинг та тестування мереж | 10. Логування та моніторинг, 11. Регулярне тестування безпеки |
| Політика інформаційної безпеки | 12. Корпоративна політика безпеки |
Рівень відповідності визначається обсягом транзакцій на рік і впливає на те, який тип аудиту потрібен.
| Рівень | Умова (Visa) | Вимога |
|---|---|---|
| Level 1 | >6 млн транзакцій/рік або компанія після витоку | Щорічний аудит QSA (Qualified Security Assessor) |
| Level 2 | 1–6 млн транзакцій/рік | Щорічний SAQ + квартальне сканування мережі |
| Level 3 | 20K–1 млн e-commerce транзакцій/рік | SAQ + квартальне сканування мережі |
| Level 4 | <20K e-commerce або <1 млн інших | SAQ (самооцінка) |
Більшість стартапів та середніх e-commerce проєктів потрапляють на рівень 4 — і саме для них найважливіший інструмент — SAQ (Self-Assessment Questionnaire).
| Тип SAQ | Сценарій | Кількість питань |
|---|---|---|
| SAQ-A | Hosted payment page PSP, ніяких карткових даних взагалі | ~22 |
| SAQ-A-EP | Redirect на PSP, але ваш сайт «торкається» payment flow | ~191 |
| SAQ-B | Тільки POS-термінали, без електронної комерції | ~41 |
| SAQ-C | Payment application через інтернет, без збереження даних | ~160 |
| SAQ-D | All others: зберігаєте дані карток або повний API | ~329 |
Це найважливіший практичний принцип для розробників. Якщо ваш додаток ніколи не бачить PAN (номер картки), CVV, PIN — більшість вимог PCI DSS просто не застосовуються до вашого коду.
Користувач перенаправляється на захищену сторінку PSP для введення реквізитів. Ваш сервер взагалі не отримує карткових даних.
Flow:
pay.liqpay.ua або stripe.com/checkoutПереваги:
Недоліки:
Форма введення картки відображається на вашому сайті, але реалізована JavaScript-бібліотекою PSP. Ваш JS-код не має доступу до введених даних — лише iframe або shadow DOM.
LiqPay Checkout Widget — JavaScript-компонент, що вставляється в ваш HTML, але обробляє дані на серверах LiqPay.
Stripe Elements — набір pre-built React/JS-компонентів, де введені дані одразу токенізуються на сервері Stripe.
SAQ-A-EP вимагає додаткової увагу до:
Ваш сервер напряму отримує реквізити картки від клієнта (номер PAN, CVV, expiry) та передає їх PSP через API.
Ніколи не робіть це, якщо у вас немає:
Що означає SAQ-D:
Токенізація — це заміна чутливих даних (номер картки) на непрозорий токен, який безпечно зберігати та передавати. Токен не містить математичного зв'язку з оригінальними даними, тому навіть при витоку токен марний для зловмисника.
Реальний PAN: 4111 1111 1111 1111
Токен: tok_live_AbCxYzQ1r2s3t4u5...
PSP зберігають відповідність токен → PAN у власній захищеній системі Token Vault. Ви отримуєте токен і використовуєте його для:
**** **** **** 1111)У вашій базі даних зберігається лише токен — НЕ картка. Це ключова різниця.
3-D Secure — протокол додаткової автентифікації власника картки. Назва «3-D» відображає трьох учасників: платіжну мережу, банк-емітент та банк-еквайрер.
3DS 1.0 (застарілий): завжди відображав додатковий екран підтвердження (SMS-код або карткова сторінка банку). Низька конверсія через погану UX.
3DS 2.x (EMV 3DS) (сучасний): використовує risk-based authentication (RBA). Банк-емітент аналізує десятки факторів ризику (пристрій, локація, сума, поведінка) та у більшості випадків підтверджує платіж без втручання користувача (frictionless flow).
Frictionless (80–90% транзакцій):
User → Cart → Pay → ✅ Done (без додаткових дій)
Challenge flow (10–20% транзакцій):
User → Cart → Pay → 📱 SMS/Push від банку → Підтвердження → ✅ Done
Реалізація: При інтеграції через PSP (LiqPay, Monobank, Stripe) — 3DS обробляється автоматично. Вам потрібно лише коректно обробити action_url від PSP, якщо emitted заклик на challenge.
| Дані | Можна зберігати | Примітка |
|---|---|---|
| PAN (повний номер картки) | ❌ Ніколи | Лише PSP |
| CVV/CVC/CVV2 | ❌ Ніколи навіть тимчасово | Суворо заборонено PCI DSS |
| PIN | ❌ Ніколи | |
| Токен PSP | ✅ Так | Основний ідентифікатор картки |
Замасковний PAN (**** 1234) | ✅ Так | Для відображення в UI |
| Термін дії (MM/YY) | ⚠️ Обережно | Лише разом з токеном, без PAN |
| Ім'я власника | ✅ Так | Не є захищеними даними картки |
| ID транзакції, сума, статус | ✅ Так | Завжди |
Один з найпоширеніших векторів витоку — логи. Розробник додає _logger.LogInformation($"Payment request: {JsonSerializer.Serialize(request)}") — і дані картки потрапляють у файли логів.
Правило: Ніколи не логуйте об'єкти запитів до PSP без явного маскування.
public static string MaskSensitiveData(string json)
{
// Маскуємо типові поля карткових даних
return Regex.Replace(json,
@"(""card_number""\s*:\s*"")(\d{6})\d+(\d{4})("")",
"$1$2******$3$4");
}
PCI DSS — це не бюрократія, це система захисту, яка evolved під реальні загрози. Для більшості розробників ключовий висновок простий: делегуйте обробку карткових даних PSP через Hosted Page або Embedded JS Form (SAQ-A або SAQ-A-EP). Зберігайте лише токени, ніколи не логуйте реквізити. 3-D Secure 2.x позбавляє вас від відповідальності за chargeback і покращує безпеку з мінімальним впливом на конверсію.
Завдання 1.1: Пройдіть онлайн-версію SAQ-A на сайті PCI SSC (pcisecuritystandards.org) та зафіксуйте 5 питань, які здалися вам найважливішими. Що вони перевіряють?
Завдання 1.2: Знайдіть у відкритих звітах або новинах реальний кейс витоку платіжних даних (Data Breach). Яка технічна причина? Якого рівня SAQ виявилося недостатньо?
Завдання 2.1: Напишіть C#-клас PaymentDataMasker з двома методами:
MaskPan(string pan) → повертає "**** **** **** 1234" (лише останні 4 цифри)SanitizeLogObject(object request) → серіалізує об'єкт у JSON, замінюючи значення полів card_number, cvv, pin на "[MASKED]"Завдання 2.2: Налаштуйте Content-Security-Policy для ASP.NET Minimal API, що дозволяє завантажувати JS лише з 'self' та checkout.liqpay.ua. Де потрібно це налаштувати і чому це важливо для SAQ-A-EP?
Завдання 3.1: Спроєктуйте схему БД для зберігання платіжних методів користувача з дотриманням PCI DSS. Таблиця payment_methods має зберігати: токен PSP, замасковний PAN, термін дії, ім'я PSP (stripe/liqpay), прапор is_default. Напишіть EF Core entity та пояснення, чому саме такий набір полів.