Хранение номеров кредитных карт на СЕЗОНЕ – пути вокруг него?

Я хорошо осведомлен о PCI Compliance, поэтому не нужно внимательно следить за хранением номеров CC (и особенно CVV nums) в нашей базе данных компании во время процесса оформления заказа.

Тем не менее, я хочу быть в безопасности, насколько это возможно, при обработке конфиденциальной информации о потребителях, и мне любопытно, как обойти номера CC с страницы на страницу БЕЗ использования переменных SESSION, если это вообще возможно.

Мой сайт построен таким образом:

  1. Шаг 1) собирать информацию о кредитной карте от клиента – когда клиент отправляет заявку, информация сначала запускается через проверку JS, а затем выполняется через проверку PHP, если все проходит, он переходит к шагу 2.
  2. Шаг 2) Информация отображается на странице обзора для клиента, чтобы убедиться, что отображаются детали их предстоящей транзакции. На этой странице показаны только первые 6 и последние 4 из CC, но тип карты и дата перехода полностью удалены. Если он нажимает,
  3. Шаг 3). Информация отправляется на другую страницу php, которая выполняет одну последнюю проверку, отправляет информацию через безопасный платежный шлюз, а строка возвращается с подробной информацией.
  4. Шаг 4) Если все хорошо и хорошо, потребительская информация (личная, а не СС) хранится в БД и перенаправляется на страницу завершения. Если что-то плохое, ему сообщают и советуют повторно просмотреть страницу обработки CC, чтобы повторить попытку (максимум 3 раза).

Какие-либо предложения?

РЕДАКТИРОВАТЬ

Я получил очень хороший ответ на этот вопрос – большинство, похоже, согласны в следующем:

  1. перенос переменных POST после проверки
  2. шифрование ccnum и cvv (не уверен, что вам разрешено хранить cvv в DB вообще)
  3. Хранение во временной БД
  4. БД доступа сразу после просмотра страницы «ОК»
  5. расшифровать данные из БД
  6. отправлять информацию процессору
  7. получать ответ
  8. завершить БД

Я думаю, что это имеет смысл в целом. У кого-нибудь есть хороший метод для шифрования / дешифрования, а также лучший способ создать временную информацию БД, которая автоматически удаляется при последующем вызове?

Я программирую в PHP и MySQL DB

EDIT # 2

Я столкнулся с Packet General, который кажется идеальным решением, но ДЕЙСТВИТЕЛЬНО не хочет платить за другую лицензию на программное обеспечение для достижения этой цели. http://www.packetgeneral.com/pcigeneralformysql.html

РЕДАКТИРОВАТЬ № 3 – Пример кода

Теперь я опубликовал некоторый пример кода, который я собрал, пытаясь понять шифрование / дешифрование / ключ и память, упомянутые в этом сообщении. Надеемся, что уже полезные вкладчики могут подтвердить, а другие могут использовать аналогичные функции. Ради длины я не буду вдаваться в методы проверки, используемые для собственно CC num.

Ввод формы

<form action="<?php $_SERVER['PHP_SELF']; ?>" method="POST"> <input type="text" name="CC" /> <input type="text" name="CVV" /> <input type="text" name="CardType" /> <input type="text" name="NameOnCard" /> <input type="submit" name="submit" value="submit" /> </form> 

PHP Шифрование и хранение данных

 <?php $ivs = mcrypt_get_iv_size(MCRYPT_DES,MCRYPT_MODE_CBC); $iv = mcrypt_create_iv($ivs,MCRYPT_RAND); $key = "1234"; //not sure what best way to generate this is! $_SESSION['key'] = $key; $ccnum = $_POST['CC']; $cvv = $_POST['CVV']; $cctype = $_POST['CardType']; $ccname = $_POST['NameOnCard']; $enc_cc = mcrypt_encrypt(MCRYPT_DES, $key, $ccnum, MCRYPT_MODE_CBC, $iv); $enc_cvv = mcrypt_encrypt(MCRYPT_DES, $key, $cvv, MCRYPT_MODE_CBC, $iv); $enc_cctype = mcrypt_encrypt(MCRYPT_DES, $key, $cctype, MCRYPT_MODE_CBC, $iv); $enc_ccname = mcrypt_encrypt(MCRYPT_DES, $key, $ccname, MCRYPT_MODE_CBC, $iv); //if we want to change BIN info to HEXIDECIMAL // bin2hex($enc_cc) $conn = mysql_connect("localhost", "username", "password"); mysql_select_db("DBName",$conn); $enc_cc = mysql_real_escape_string($enc_cc); $enc_cvv = mysql_real_escape_string($enc_cvv); $enc_cctype = mysql_real_escape_string($enc_cctype); $enc_ccname = mysql_real_escape_string($enc_ccname); $sql = "INSERT INTO tablename VALUES ('$enc_cc', '$enc_cvv', '$enc_cctype', '$enc_ccname'); $result = mysql_query($sql, $conn) or die(mysql_error()); mysql_close($conn); Header ("Location: review_page.php"); ?> 

PHP расшифровка данных и отправка на шлюз

  $conn = mysql_connect("localhost", "username", "password"); mysql_select_db("DBName",$conn); $result = mysql_query("SELECT * FROM tablename"); echo mcrypt_decrypt (MCRYPT_DES, $_SESSION['key'], $enc_ccnum, MCRYPT_MODE_CBC, $iv); echo mcrypt_decrypt (MCRYPT_DES, $_SESSION['key'], $enc_cvv, MCRYPT_MODE_CBC, $iv); echo mcrypt_decrypt (MCRYPT_DES, $_SESSION['key'], $enc_cctype, MCRYPT_MODE_CBC, $iv); echo mcrypt_decrypt (MCRYPT_DES, $_SESSION['key'], $enc_ccname, MCRYPT_MODE_CBC, $iv); mysql_close($con); ?> 

затем перейдите к передаче данных, только что отправленных в строку, и используйте их в представлении «Шлюз». Понятно?

Подумайте о том, как изменить процесс оформления заказа, чтобы избавиться от необходимости хранить информацию о кредитной карте.

Страница 1: Пользователь вводит информацию о заказе некредитной карты, например, адрес доставки и платежный адрес
Страница 2: Пользователь проверяет информацию о некредитной карточке, вводит информацию о кредитной карте и нажимает «Оплатить сейчас» (или «Изменить порядок», если они хотят что-то изменить)
Шаг 3: Информация отправляется через запрос $ _POST на страницу SSL, которая завершает проверки на сервере, передает данные кредитной карты процессору и направляет пользователя на страницу успеха или ошибки на основе ответа.

Таким образом вы избегаете мутности технических проблем и проблем с соблюдением. Хранение данных кредитной карты в базе данных или в файле cookie даже на короткий период времени, даже если зашифровано, означает, что вы отвечаете за более высокий уровень соответствия PCI. Единственным компромиссом является то, что вы не сможете отобразить страницу «Просмотр заказа» с данными кредитной карты. И насколько большой компромисс заключается в том, что, если ваша страница «Заказ на просмотр» не может даже показать полный номер кредитной карты?

Сохраните данные карты на любой носитель постоянства (база данных, независимо), но закрепите номер карты уникальным и случайным ключом, который вы храните в сеансе. Таким образом, если сеанс потерян, ключ тоже – что дает вам достаточно времени для очистки истекших / оставленных данных.

Также убедитесь, что ваши сеансы защищены от угона. Есть аппаратные решения для этого, но простой способ в коде – связать идентификатор сеанса с хэшем первого октета IP плюс пользовательский агент. Не уверен, но это помогает.

Редактирование . Ключи для минимизации вашего риска – это как можно скорее избавиться от этой информации. Сразу после транзакции удалите запись из базы данных. Вам также требуется скользящее задание (скажем, каждые 5 минут), которое удаляет записи, превышающие тайм-аут сеанса (обычно 20 минут). Кроме того, если вы используете базу данных для этих очень временных данных, убедитесь, что она не находится в автоматизированной системе резервного копирования.

Опять же, это решение не является надежным, и я даже не уверен, что он соответствует требованиям безопасности CC. Тем не менее, это должно потребовать, чтобы злоумышленник имел полный контроль выполнения вашей среды, чтобы активно расшифровывать информацию о CC-клиентах, и если снимок вашей базы данных скомпрометирован (гораздо более вероятен / распространен), только один CC может быть принудительно принудительно за один раз, о котором вы можете надеяться.

Я знаю, что вы упомянули о том, что вам известно о соблюдении PCI, но использование любого из описанных методов (например, сохранение номера карты на диске в любом месте) будет падать на PCI и означает, что перед вами стоит кошмар соответствия головных болей. Если вы действительно настаиваете на сохранении номера карты на диске, тогда вы можете также получить аудитора PCI в настоящее время, чтобы помочь вам в этом процессе и предложить советы. В конечном итоге им нужно будет подтвердить, что метод, который вы приняли, уместен.

В качестве примера, многие ответы здесь говорят об использовании шифрования. Это легкий бит. Они не говорили о ключевом управлении, которое значительно сложнее

Поэтому я думаю, что лучшим подходом было бы представить данные карты на платежный шлюз, как только они будут собраны. Многие платежные шлюзы позволят вам выполнить транзакцию типа «только в магазине», которая будет выполнять базовую проверку данных карты и сохранить номер карты на своем (уже совместимом с PCI) сервере и вместо этого вернуть вам идентификатор токена. Этот метод означает, что вы НЕ ДОЛЖНЫ хранить полный номер карты / cvv2 в любом месте на своих серверах, а соблюдение PCI становится намного проще.

Позже в процессе проверки вы используете идентификатор маркера для отправки авторизации и расчета.

PCI позволяет хранить первые шесть / последние четыре цифры (и дату истечения срока действия) номера карты в виде открытого текста, поэтому вы можете безопасно их записывать везде, где вам удобно, чтобы их можно было отобразить только до последнего шага.

Есть ли причина, по которой вы не можете пропустить шаг подтверждения и сразу отправить транзакцию?

Я не понимаю, почему сохранение его в базе данных более безопасно, чем сохранение его в переменной сеанса – компромисс сервера по-прежнему будет выдавать номер кредитной карты, но если вы сохраните его в сеансе, то гораздо менее вероятно, что он будет записан в диск. Вы можете зашифровать его, если хотите, но полезность этого сомнительна (он все равно будет заменен на диск). Добавление другой машины для работы с зашифрованным хранилищем тоже не помогает, поскольку скомпрометированный компьютер может просто попросить другого сделать дешифрование.

EDIT: Просто подумал об этом:

  1. Генерируйте случайный 128-битный ключ. Сохраните это в сеансе.
  2. Шифруйте данные с помощью ключа. Отправьте его клиенту в <input type = "hidden">
  3. При подтверждении дешифруйте данные и отправьте транзакцию.

Злоумышленник должен скомпрометировать как клиент, так и сервер, чтобы получить номер кредитной карты (такой атакующий, вероятно, будет иметь номер уже в любом случае). Компромисс онлайн-сервера по-прежнему будет содержать номера кредитных карт будущих транзакций, но вы не можете этого прекратить.

EDIT: И я забыл детали. Для всех этих схем (а не только для моих) вам также нужен MAC для предотвращения повторных атак (или Ева отвлекает Алису, изменяет корзину покупок и адрес выставления счетов и попадает на страницу подтверждения). В общем, вы хотите иметь MAC для всех имеющихся у вас данных транзакций (CC, CVV, идентификатор транзакции, сумма транзакции, адрес выставления счетов …).

Вы правы, использование сеансов очень небезопасно для хранения конфиденциальных данных, есть способы взломать сеансы с тем, что известно как:

Захват сеанса
Фиксация сеанса

Самый безопасный способ, который приходит мне на ум, заключается в том, что хранить информацию в базе данных (для временного времени), а затем читать это значение на странице, где она вам нужна. Как только вы закончите делать все это, вы можете удалить его обратно.

Обратите внимание, что:

  • вы должны зашифровать его перед сохранением в базе данных.
  • будьте осторожны, если вы находитесь на общем хостинге
  • убедитесь, что вы удалили его, как только сделали это

Вы также можете найти это полезным образом 🙂

Похоже, что в любом случае вы прикоснетесь к нему, вам нужно будет обеспечить возможности хранения номеров кредитных карт. Если сервер скомпрометирован, в любой момент он будет содержать достаточно информации для дешифрования имеющихся в настоящее время номеров кредитных карт (т.е. ключей и зашифрованных номеров). Потенциальным решением является использование внутреннего сервера, который действует как служба шифрования / дешифратора и ничего больше. Таким образом, компрометация одной машины не предоставляет номера кредитных карт.

Существует другой способ, но для этого требуется Ajax. Нет хранения номеров кредитных карт и страницы обзора.

Страница 1: Форма для записи информации о доставке, биллинге и кредитной карте. Убедитесь, что «тело» страницы, включая форму, находится в DIV с уникальным идентификатором, чтобы вы могли ссылаться на него с помощью JavaScript.

Страница 2: Файл на сервере, который будет принимать запрос GET / POST с полями формы в нем и вернуть надлежащим образом отформатированную страницу обзора по своему вкусу.

Процесс оформления заказа:

  1. Подтвердить форму.
  2. Скопируйте связанные поля кредитной карты в глобальные переменные JavaScript.
  3. Прокрутите поля формы и постройте строку запроса / данных с полями формы (за исключением полей, связанных с кредитной картой)
  4. Сделайте запрос Ajax на страницу «Обзор», передав с ним строку запроса полей / значений формы. Откажитесь от сервера и вернитесь к функции Ajax.
  5. Возьмите предоставленную страницу обзора HTML, возвращенную из запроса Ajax, и замените содержимое в вашем контейнере «DIV» (эффективно заменив форму и другие элементы обзором HTML).
  6. Используйте JavaScript, чтобы скопировать данные кредитной карты, хранящиеся в глобальных переменных JS, в соответствующее место на странице обзора. Вы также можете скопировать данные карты в скрытые поля формы для отправки, когда пользователь «завершает» заказ со страницы «Обзор».
  7. Пользователь отправляет заказ с страницы обзора на сервер, выполняет проверку карты с помощью шлюза процессора, а затем либо делает заказ, либо возвращается на страницу обработки ошибок, никогда не сохраняя данные карты.
  8. Я бы рекомендовал, чтобы функция «порядок места» выполняла полный HTTP-запрос (а не Ajax), чтобы перезагрузить браузер со страницей, которая больше не хранит данные карты в глобальных переменных JS.

Это немного взломанный, но когда он сделан правильно, он на 100% бесшовна для пользователя и позволяет вам иметь одну передачу данных карты без необходимости принимать риски при хранении временного БД и т. Д.

Для этого нужна база данных. Я не уверен в правовых последствиях здесь (которые различаются в зависимости от страны и региона), но одним из подходов было бы зашифровать номер CC и сохранить его в базе данных, как только вы получите его от пользователя. Вы можете сохранить последние 4 цифры в отдельном поле, чтобы вы могли показать его пользователю, когда это необходимо. Когда вам необходимо взаимодействовать с процессором карт на сервере, извлеките и расшифруйте номер карты из своей базы данных.

Вот как я планирую это сделать – все по https, используя ssl, конечно.

Шаг 1. Пользователь вводит информацию CC и нажимает следующую кнопку. Информация CC немедленно сохраняется в базе данных процессора CC, а не в вашей собственной БД, иначе вы нарушите PCI Compliance. На этом CC фактически не взимается. Но вы должны получить уникальный идентификатор от процессора, идентифицирующий информацию CC. (сохраните уникальный идентификатор в своем db, если хотите)

Шаг 2. На странице подтверждения извлеките информацию CC из процессора CC, используя уникальный идентификатор, который они вам предоставили. Мой процессор только позволит мне получить последние 4 номера CC в любом случае.

Шаг 3. После подтверждения покупки и нажмите кнопку «Купить сейчас», зарядите кредитную карту, используя уникальный идентификатор.

Шаг 4. Перенаправление на страницу с благодарностью, содержащую счет / reciept, который содержит только последние 4 цифры CC (конечно, вам не нужно отображать последние 4 из CC, но я думаю, что это хорошая вещь, чтобы показать ).

Вы можете сохранить хэш карты nr в сеансе и тот же хеш, а также фактическое число и идентификатор сеанса пользователя в базе данных. Затем для каждой страницы вы можете проверить хэш и информацию о сеансе, чтобы получить карту nr.

В какой-то момент в процессе обработки платежа (последняя часть шага 3) вам нужно будет зашифровать CC # (и CVC), чтобы отправить его процессу обработки платежей (я полагаю)

Почему бы не сделать это шифрование сразу, когда вы получите информацию, рядом с обфускацией, необходимой для страницы подтверждения. (это последняя часть шага 1)

С этого момента работайте только с зашифрованными или обфусками данными, что делает CC-компанию единственной, кто может фактически расшифровать полные данные.

Нет необходимости в сеансах или базе данных для хранения информации.

Каждая страница представляет собой форму, которая публикует данные. На каждой последующей странице переменные сообщения с предыдущей страницы добавляются в поля скрытой формы, так что в следующем представлении формы данные снова помещаются. Таким образом, ничего не сохраняется, но информация переносится со страницы на страницу. Это также заставляет пользователя завершить процесс от начала до конца, не пытаясь пропустить шаги.

Пока форма передается через HTTPS, данные зашифровываются автоматически, а бремя безопасности лежит на вашем поставщике сертификатов SSL.

Это реализует многие сайты популярной торговли. Например, OSCommerce.

Использовать токенизацию. Его полностью совместим с PCI DSS.

Здесь может быть больше, https://www.pcisecuritystandards.org/documents/Tokenization_Guidelines_Info_Supplement.pdf