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

17

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

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

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

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

    
задан Lars A. Brekken 19.09.2008 в 17:54
источник

15 ответов

17

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

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

  

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

     

...

     

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

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

    
ответ дан Nick Johnson 19.09.2008 в 20:46
источник
10

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

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

Шаг 1:

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

Шаг 2:

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

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

    
ответ дан Wedge 19.09.2008 в 18:52
источник
  • Это звучит неплохо, чтобы выполнить последние 4 цифры перед сравнением хэшей. Благодаря! –  Lars A. Brekken 19.09.2008 в 19:31
  • Хранение последних 4 цифр упрощает атаку грубой силы еще больше. –  Nick Johnson 19.09.2008 в 21:33
  • @Arachnid К сожалению, хранение последних 4 цифр является обычной практикой для торговцев. Тем не менее, вы можете просто сравнить с датой истечения срока действия в качестве первого теста, если вы абсолютно не хотите сохранять последние 4 цифры. –  Wedge 19.09.2008 в 22:07
  • Хорошая идея, хотя я думаю, что было бы лучше использовать 14-16 бит из «дорогой» хеш, а не последние четыре цифры, как предселектор; дорогой хэш должен включать соль для каждой базы данных, чтобы предотвратить создание таблиц радуги, которые могли бы помочь атакам на несколько систем. –  supercat 23.12.2010 в 00:00
5

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

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

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

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

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

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

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

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

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

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

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

    
ответ дан MiniQuark 12.08.2009 в 20:03
источник
3

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

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

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

    
ответ дан J.D. Fitz.Gerald 19.09.2008 в 18:43
источник
2

@Cory R. King

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

ответ дан Kibbee 19.09.2008 в 18:13
источник
2

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

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

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

    
ответ дан TIMEX 11.08.2014 в 10:02
источник
1

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

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

  

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

    
ответ дан ine 19.09.2008 в 17:58
источник
  • Да, но если вы используете другую случайную соль для каждого хэша, вам нужно попробовать каждую соль для нового значения, которое вы хотите сравнить. Используйте длинную случайную, но постоянную строку + срок годности. –  MattW. 19.09.2008 в 18:02
  • Если вы используете дату истечения срока в соли, как она постоянна? –  ine 19.09.2008 в 18:16
  • Если они не используют словарь, который включает дату истечения срока действия в качестве соли. –  Ethan Heilman 28.11.2011 в 16:30
1

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

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

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

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

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

    
ответ дан Jeff 19.09.2008 в 17:58
источник
  • Ah - и если SHA-1 настолько дорога, что добавление этой соли фактически будет стоить хакерским годам, тогда это также будет так дорого, что вы, вероятно, будете страдать, чтобы добавить к CC номер 10000. Но вы всегда можете просто протестировать его по сравнению с ожидаемым размером клиентской базы и посмотреть, не больно ли это. –  Jeff 19.09.2008 в 18:29
  • -1 Извините, но я действительно не согласен с этим ответом: вы не можете обрабатывать номера кредитных карт, такие как пароли, потому что люди могут при необходимости выбирать сложные пароли (длинные, с буквами, цифрами и специальными символами), тогда как кредитная карта цифры составляют около 16 цифр, а половина из них можно легко угадать (первые 7 являются отраслевыми стандартами (см. ответ Ник Джонсона), а последние 4 хранятся в базе данных в соответствии с вопросом (и это обычная практика) Так что действительно не храните «только хэш». Вместо этого следуйте за ответом Клина или моим. –  MiniQuark 12.08.2009 в 18:55
  • -1 MiniQuark прав. Эта схема уступает другим предложениям, сделанным здесь. Тот факт, что кредитные карты просто можно угадать, здесь не рассматривается. –  Accipitridae 13.08.2009 в 09:54
0

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

    
ответ дан Ben Hoffstein 19.09.2008 в 17:56
источник
0

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

    
ответ дан Chris Marasti-Georg 19.09.2008 в 17:57
источник
  • Я согласен. Имейте в виду, что это делает регистрацию кредитной карты операцией O (n), где n - это существующее количество зарегистрированных карт. Плюс хеширование - довольно дорогостоящая операция. –  Johan 19.09.2008 в 18:03
0

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

    
ответ дан Cory R. King 19.09.2008 в 18:02
источник
  • Оба SHA1 и MD5 только сломаны, что можно создать две строки с одинаковым хешем. Ни один из них не разбивается, когда дело доходит до вычисления прообразов для хеша, или когда дело доходит до создания строки с тем же хешем, что и известная строка. –  Nick Johnson 19.09.2008 в 20:28
0

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

ответ дан Rob Allen 19.09.2008 в 18:08
источник
  • да, вы бы хотели - дело в том, что для создания табличных атак требуется много времени. Если у вас есть другая соль для каждого номера карты, при построении таблицы вы получите максимум 1 карту. Стоимость не стоит. –  Chris Marasti-Georg 19.09.2008 в 18:19
  • Я выступал против соленого хэша - я думаю, что это слишком сложно, когда цель OP состоит в том, чтобы просто предотвратить несколько экземпляров данных, которые сами по себе не являются достаточно уникальными, чтобы соответствовать. –  Rob Allen 19.09.2008 в 20:28
0

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

    
ответ дан Mitchel Sellers 19.09.2008 в 18:13
источник
0

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

    
ответ дан Martin Beckett 19.09.2008 в 18:13
источник
0

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

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

ответ дан Michael 14.09.2014 в 15:29
источник