Как отделить личность человека от его личных данных? - PullRequest
5 голосов
/ 11 сентября 2010

Я пишу приложение, основной целью которого является ведение списка покупок пользователей.

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

Я изначально придумал следующую схему:

    --------------+------------+-----------
    user_hash     | item       | price
    --------------+------------+-----------
    a45cd654fe810 | Strip club |     400.00
    a45cd654fe810 | Ferrari    | 1510800.00
    54da2241211c2 | Beer       |       5.00
    54da2241211c2 | iPhone     |     399.00
  • Пользователь входит в систему с именем пользователя и паролем.
  • Из пароля вычислите user_hash (возможно, с засолкой и т. Д.).
  • Используйте хеш для доступа к данным пользователей с помощью обычных SQL-запросов.

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

Это разумная вещь, или я совершенно глуп?

Ответы [ 7 ]

4 голосов
/ 17 сентября 2010

Боюсь, что если ваше приложение может связать человека с его данными, любой разработчик / администратор может.

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


Идея основана на @no idea:

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

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

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

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

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

С другой стороны, (как я сказал в комментарии к @no) остерегайтесь коллизий .Плюс, если ваш пользователь пишет неверный «проход», вы не можете его проверить.


Обновление: в последней части у меня была другая идея: вы можете сохранить в своей базе данных хэш своего «прохода»/ password "пара, таким образом вы можете проверить, в порядке ли ваш" пропуск ".

2 голосов
/ 17 сентября 2010
  1. Создайте таблицу пользователей с:
    1. user_id: столбец идентификаторов (автоматически сгенерированный идентификатор)
    2. username
    3. пароль: убедитесь, что он хеширован!
  2. Создайте таблицу продуктов, как в вашем примере:
    1. user_hash
    2. item
    3. цена

user_hash будет основан на user_id, который никогда не меняется.Имя пользователя и пароль могут быть изменены по мере необходимости.Когда пользователь входит в систему, вы сравниваете имя пользователя / пароль, чтобы получить идентификатор_пользователя.Вы можете отправить user_hash обратно клиенту на время сеанса или зашифрованную / косвенную версию хэша (это может быть идентификатор сеанса, где сервер хранит user_hash в сеансе).

Сейчасвам нужен способ, чтобы хэшировать user_id в user_hash и сохранить его защищенным.

  1. Если вы делаете это на стороне клиента, как предложено @no, клиент должен иметь user_id.Большая дыра в безопасности (особенно если это веб-приложение), хеш легко может быть подделан, а алгоритм свободно доступен для общественности.
  2. Вы можете использовать его как функцию в базе данных.Плохая идея, поскольку в базе данных есть все части, чтобы связать записи.
  3. Для веб-сайтов или клиент-серверных приложений это может быть в коде на стороне сервера.Гораздо лучше, но тогда один разработчик получает доступ к алгоритму хеширования и данным.
  4. Пусть другой разработчик напишет алгоритм хеширования (к которому у вас нет доступа) и подключится к другому серверу (который вы также не используете).не имеет доступа к) как TCP / веб-сервис.Ваш серверный код затем передаст идентификатор пользователя и вернет хэш.У вас не было бы алгоритма, но вы можете отправить все идентификаторы пользователей, чтобы вернуть все их хэши.Не так много преимуществ для # 3, хотя служба может иметь журналирование и тому подобное, чтобы минимизировать риск.
  5. Если это просто приложение клиент-база данных, у вас есть только варианты № 1 и 2. Я бынастоятельно рекомендуем добавить еще один [бизнес] уровень, который находится на стороне сервера, отдельно от сервера базы данных.

Редактировать: Это перекрывает некоторые из предыдущих пунктов.Есть 3 сервера:

  • Сервер аутентификации : Сотрудник А. имеет доступ.Поддерживает пользовательскую таблицу.Имеет веб-сервис (с зашифрованной связью), который принимает комбинацию пользователь / пароль.Хеширует пароль, ищет user_id в таблице, генерирует user_hash.Таким образом, вы не можете просто отправить все user_ids и вернуть хэши.Вы должны иметь пароль, который нигде не хранится и доступен только во время процесса аутентификации.
  • Основной сервер базы данных : Сотрудник B. имеет доступ.Хранит только user_hash.Нет ИД пользователя, нет паролей.Вы можете связать данные, используя user_hash, но фактическая информация о пользователе находится где-то еще.
  • Сервер веб-сайта : Сотрудник B. имеет доступ.Получает информацию для входа в систему, передает на сервер аутентификации, возвращает хэш, затем удаляет информацию для входа.Сохраняет хэш в сеансе для записи / запроса к базе данных.

Таким образом, у сотрудника A есть user_id, имя пользователя, пароль и алгоритм.У сотрудника B есть user_hash и данные.Если сотрудник B не модифицирует веб-сайт для хранения необработанного пользователя / пароля, он не сможет связываться с реальными пользователями.

При использовании профилирования SQL сотрудник A получит хэш user_id, username и password (поскольку генерируется user_hash)позже в коде).Сотрудник B получит user_hash и данные.

1 голос
/ 18 сентября 2010

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

По этой причине, когда вы дезидентифицируете медицинские записи (для использования в исследованиях и т. Д.), Вы должны удалить дни рождения для людей старше 89 лет (потому что люди такого возраста достаточно редки, чтобы указывать конкретную дату рождения один человек) и удалить любое географическое кодирование, в котором указана область, содержащая менее 20 000 человек. (См. http://privacy.med.miami.edu/glossary/xd_deidentified_health_info.htm)

AOL выяснил трудный путь, когда они публиковали поисковые данные, которые можно идентифицировать, просто зная, какие поиски связаны с анонимным человеком. (См. http://www.fi.muni.cz/kd/events/cikhaj-2007-jan/slides/kumpost.pdf)

1 голос
/ 17 сентября 2010

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

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

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

В конечном итоге это социальная проблема, а не технологическая проблема.Лучшие решения будут социальным решением.После усиления защиты ваших систем от несанкционированного доступа (хакеры и т. Д.) Вы, вероятно, получите больший пробег, работая над установлением доверия со своими пользователями и внедрением системы политик и процедур, касающихся безопасности данных.Включите специальные штрафы для сотрудников, которые злоупотребляют информацией о клиентах.Так как одного нарушения доверия клиентов достаточно, чтобы разрушить вашу репутацию и отогнать всех ваших пользователей, соблазн неправильного использования этих данных теми, у кого есть доступ «верхнего уровня», меньше, чем вы думаете (поскольку крах компании обычноперевешивает любой выигрыш).

0 голосов
/ 18 сентября 2010

Кажется, что вы на правильном пути с этим, но вы просто слишком думаете об этом (или я просто не понимаю)

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

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

Свяжите все действия пользователя с хешем пользователя.

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

Я думаю, что вы ответили на свой вопрос в своем первоначальном сообщении.

0 голосов
/ 17 сентября 2010

На самом деле, есть способ, которым вы могли бы делать то, о чем говорите ...

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

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

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

1010 * редактировать *

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

Например, вы берете генератор хеша, как это:

http://baagoe.com/en/RandomMusings/javascript/Mash.js

// From http://baagoe.com/en/RandomMusings/javascript/
// Johannes Baagoe <baagoe@baagoe.com>, 2010
function Mash() {
  var n = 0xefc8249d;

  var mash = function(data) {
    data = data.toString();
    for (var i = 0; i < data.length; i++) {
      n += data.charCodeAt(i);
      var h = 0.02519603282416938 * n;
      n = h >>> 0;
      h -= n;
      h *= n;
      n = h >>> 0;
      h -= n;
      n += h * 0x100000000; // 2^32
    }
    return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
  };

  mash.version = 'Mash 0.9';
  return mash;
}

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

  • Хешируйте имя пользователя + пароль, используя обычный алгоритм хэширования. Это будет то же самое, что и ключ «секретной» таблицы в базе данных, но больше ничего не будет соответствовать в базе данных.
  • Добавьте хешированный проход к имени пользователя и хэшируйте его с помощью вышеуказанного алгоритма.
  • Base-16 кодирует var n и добавляет его в исходный хеш с символом-разделителем.

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

0 голосов
/ 17 сентября 2010

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

Нет абсолютно никакого способа предотвратить это.

Реальность такова, что, имея полный доступ, мы находимся в состоянии доверия. Это означает, что руководители компании должны верить, что даже если вы можете видеть данные, вы не будете действовать в соответствии с ними. Именно здесь в игру вступают такие мелочи, как этика.

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

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

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

Смысл всего этого в том, что это проблема персонала; и не тот, который действительно может быть решен с помощью технических средств.


UPDATE

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

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

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

В конце концов, все, что вы сделали, это усложнили разработку с абсолютно нулевым преимуществом безопасности. Я не могу подчеркнуть это достаточно: единственный способ скрыть данные из базы данных - это либо 1. чтобы данные были только доступными для самого человека, который их ввел, либо 2. чтобы они не существовали во-первых.

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

...