Подтвердить что ты не робот

Лучший способ предотвратить дублирование использования кредитных карт

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

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

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

Вы, ребята, видите недостатки в этом методе? Является ли это стандартным способом решения этой проблемы?

4b9b3361

Ответ 1

Сделайте небольшую математику: номера кредитных карт - 16 цифр. Первые семь цифр - это "основные отрасли" и номера эмитентов, а последняя цифра - контрольная сумма luhn. Это оставляет 8 цифр "бесплатно", в общей сложности 100 000 000 номеров счетов, умноженное на количество потенциальных номеров эмитентов (что вряд ли будет очень высоким). Существуют реалии, которые могут делать миллионы хэшей в секунду на повседневном оборудовании, поэтому независимо от того, что вы делаете, это не будет большой проблемой для грубой силы.

Благодаря простому совпадению, когда вы ищете что-то, дающее хеш-алгоритм, я нашел эту статью о хранении хэшей кредитных карт, в которой говорится:

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

...

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

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

Ответ 2

Люди уже думают о дизайне этого, я думаю. Используйте засоленный, высокозащищенный (например, "вычислительно дорогой" ) хеш, например, sha-256, с уникальной солью за запись.

Сначала вы должны сделать недорогую проверку с высокой степенью точности, а затем выполнить дорогостоящую окончательную проверку, только если эта проверка попадает.

Шаг 1:

Ищите совпадения с последними 4 цифрами (и, возможно, также с датой exp, хотя там есть некоторые тонкости, которые могут нуждаться в адресации).

Шаг 2:

Если простые проверки попадают, используйте соль, получите значение хэша, выполните проверку глубины.

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

Ответ 3

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

Первое решение

  • Для каждой кредитной карты мы сохраняем последние 4 цифры, дату истечения срока действия, длинную случайную соль (длиной 50 байт) и соленый хэш номера CC. Мы используем алгоритм хэширования bcrypt, поскольку он очень безопасен и может быть настроен как интенсивный, как вам хотелось бы, процессор. Мы настроили его очень дорого (около 1 секунды за хэш на нашем сервере!). Но я думаю, вы могли бы использовать SHA-256 вместо этого и повторять столько раз, сколько необходимо.
  • Когда вводится новый номер CC, мы начинаем с нахождения всех существующих номеров CC, которые заканчиваются на те же 4 цифры и имеют одинаковую дату истечения срока действия. Затем для каждого совпадающего CC мы проверяем, совпадает ли его сохраненный соленый хеш соленый хэш, рассчитанный по его соли, и номер нового CC. Другими словами, мы проверяем, есть ли hash(stored_CC1_salt+CC2)==stored_CC1_hash.

Так как в нашей базе данных имеется около 100 тыс. кредитных карт, нам нужно рассчитать около 10 хэшей, поэтому мы получим результат примерно через 10 секунд. В нашем случае это нормально, но вы можете немного настроить bcrypt. К сожалению, если вы это сделаете, это решение будет менее безопасным. С другой стороны, если вы настроите bcrypt на еще большую интенсивность процессора, потребуется больше времени для сопоставления номеров CC.

Несмотря на то, что я считаю, что это решение лучше, чем просто хранить несостоявшийся хэш номера CC, это не помешает очень мотивированному пирату (которому удается получить копию базы данных), чтобы сломать одну кредитную карту в среднее время от 2 до 5 лет. Так что если у вас есть 100k кредитных карт в вашей базе данных, и если у пирата много CPU, он сможет каждый день восстанавливать несколько номеров кредитных карт!

Это приводит меня к убеждению, что вы не должны сами вычислять хеш: вы должны делегировать это кому-то другому. Это второе решение (мы переходим к этому второму решению).

Второе решение

Просто попросите поставщика платежей создать псевдоним для вашей кредитной карты.

  • для каждой кредитной карты вы просто храните все, что хотите сохранить (например, последние 4 цифры и срок годности) плюс псевдоним номер кредитной карты.
  • когда введен новый номер кредитной карты, вы связываетесь со своим поставщиком платежей и указываете ему номер CC (или перенаправляете клиента поставщику платежей, и он вводит номер CC непосредственно на веб-сайте поставщика платежей). Взамен вы получаете псевдоним кредитной карты! Это. Конечно, вы должны убедиться, что поставщик платежей предлагает эту опцию и что сгенерированный псевдоним фактически защищен (например, убедитесь, что они не просто вычисляют SHA-1 на номер кредитной карты!). Теперь пират должен разорвать вашу систему плюс вашу систему поставщика платежей, если он хочет восстановить номера кредитных карт.

Это просто, быстро, безопасно (ну, по крайней мере, если ваш поставщик платежей). Единственная проблема, которую я вижу, это то, что она связывает вас с поставщиком платежей.

Надеюсь, что это поможет.

Ответ 4

PCI DSS утверждает, что вы можете хранить PAN (номера кредитных карт) с использованием сильного одностороннего хэша. Они даже не требуют, чтобы они были солеными. Тем не менее, вы должны солить его с уникальной стоимостью карты. Датой истечения срока является хорошим началом, но, возможно, слишком коротким. Вы можете добавить другие данные с карты, например, эмитентом. Вы не должны использовать CVV/номер безопасности, поскольку вам не разрешено хранить его. Если вы используете дату истечения срока действия, тогда, когда владелец карты получает новую карту с таким же номером, она будет считаться другой картой. Это может быть хорошей или плохой в зависимости от ваших требований.

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

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

Ответ 5

@Cory R. King

SHA 1 сам по себе не нарушается. Что показывает статья, так это то, что возможно генерировать 2 строки, которые имеют одно и то же значение хэша меньше, чем время грубой силы. Вы по-прежнему не можете генерировать строку, которая приравнивается к ХОРОШЕМУ КОНКРЕТНОМУ за разумное время. Между ними существует большая разница.

Ответ 6

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

  • Создайте защищенный сервер на EC2, Heroku и т.д. Этот сервер будет служить ОДНОЙ цели и ТОЛЬКО одной целью: хешировать вашу кредитную карту.
  • Установите защищенный веб-сервер (Node.js, Rails и т.д.) на этом сервере и настройте вызов REST API.
  • На этом сервере используйте уникальную соль (1000 символов) и SHA512 1000 раз.

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

Ответ 7

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

Из эта статья о кодировании ужасов:

Добавьте длинную уникальную случайную соль к каждому сохраненному вами паролю. Точка соли (или nonce, если вы предпочитаете) состоит в том, чтобы сделать каждый пароль уникальным и достаточно длинным, чтобы атаки грубой силы были пустой тратой времени. Таким образом, пароль пользователя вместо сохранения в качестве хэша "myspace1" заканчивается тем, что он хранится как хэш из 128 символов случайной строки Unicode + "myspace1". Теперь вы полностью защищены от атаки радужного стола.

Ответ 8

Почти хорошая идея.

Хранение только хэша - хорошая идея, он десятилетиями служил в мире паролей.

Добавление соли кажется справедливой идеей и действительно делает атаку грубой силы, которая намного сложнее для атакующего. Но эта соль будет стоить вам много дополнительных усилий, если вы действительно убедитесь, что новый CC уникален: у вас будет SHA-1 ваш новый номер CC N раз, где N - количество солей, которые у вас есть уже используется для всех CC, с которыми вы сравниваете это. Если вы действительно выбираете хорошие случайные соли, вам придется делать хэш для каждой другой карты в вашей системе. Итак, теперь вы делаете грубую силу. Поэтому я бы сказал, что это не масштабируемое решение.

Вы видите, что в мире паролей соль добавляет никакой стоимости, потому что мы просто хотим знать, есть ли чистый текст + хэш-хэш для того, что мы сохранили для этого конкретного пользователя. Ваше требование на самом деле очень отличается.

Вам придется взвесить компромисс. Добавление соли не делает вашу базу данных безопасной, если она украдена, она просто упрощает декодирование. Насколько сложнее? Если он изменит атаку, требуя 30 секунд, чтобы в один прекрасный день вы ничего не достигли - он все равно будет декодирован. Если он изменит его с одного дня до 30 лет, вы достигнете того, что стоит подумать.

Ответ 9

Да, сравнение хэшей должно работать нормально в этом случае.

Ответ 10

Соленый хэш должен работать нормально. Наличие системы солей для пользователей должно быть достаточным для обеспечения безопасности.

Ответ 11

SHA1 broken. Конечно, информации о том, что такое хорошая замена, мало информации. SHA2?

Ответ 12

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

Ответ 13

Я думаю, что хорошим решением, намеченным выше, было бы сохранение хэш-значения, например, номера карты, даты истечения срока действия и имени. Таким образом, вы все равно можете выполнять быстрые сравнения...

Ответ 14

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

Ответ 15

Если вы используете процессор платежей, например Stripe/Braintree, пусть они выполняют "тяжелый подъем".

Они оба предлагают картографическую отпечатку пальца, которую вы можете безопасно хранить в своем db, и сравните позже, чтобы узнать, существует ли карта:

  • Stripe возвращает строку fingerprint - см. doc
  • Braintree возвращает unique_number_identifier string - см. doc