Как защитить куки от атаки - PullRequest
1 голос
/ 10 июля 2011

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

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

Вот мой код:

public static int GetUserId(Page page)
        {
            int userId;

            if (page.Request.Cookies["userId"] != null && page.Request.Cookies["userIdHashed"] != null)
            {
                string userIdHashed = page.Request.Cookies["userIdHashed"].Value;
                string userIdCoockie = page.Request.Cookies["userId"].Value;
                string coockie = (userIdCoockie + "945AFF2FD0F1D89B4B1DBEB1B0C5D3B8B5DCE000AAEA331EB0C3F3A68C3865EFA73BC6EBF30C8DF1AD6B9ECB7094DA5B0C1AF36B5BBD096E3D873E9589E3F664").GetHashCode().ToString();
                if (userIdHashed == coockie)
                {
                    userId = Int32.Parse(userIdCoockie);
                }
                else
                {
                    throw new Exception("UserId does not match!");
                }
            }

                else
                {

                    userId = ...//here userId is being retrieved from the data base and than:

                    page.Response.Cookies["userId"].Value = userId.ToString();
                    page.Response.Cookies["userId"].HttpOnly = true;
                string userIdHashed = (userId.ToString() + "945AFF2FD0F1D89B4B1DBEB1B0C5D3B8B5DCE000AAEA331EB0C3F3A68C3865EFA73BC6EBF30C8DF1AD6B9ECB7094DA5B0C1AF36B5BBD096E3D873E9589E3F664").GetHashCode().ToString();
                page.Response.Cookies["userIdHashed"].Value = userIdHashed;
                page.Response.Cookies["userIdHashed"].HttpOnly = true;
            }

            return userId;
        }

Итак, мои вопросы:

  • Может ли такой подход считаться достаточно надежным в этой ситуации?

  • Если нет, я должен изменить его и как или я должен искать что-то другое (например, шифрование /дешифрование с помощью System.Security.Cryptography в соответствии с рекомендациями здесь )?

И дополнительный вопрос: имеет ли смысл устанавливать HttpCookie.HttpOnly = true, чтобы запретить JavaScriptполучить доступ к куки-файлу, учитывая, что он также может быть легко изменен пользователем?

ОБНОВЛЕНИЕ

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

Предлагаются следующие варианты:

  • Использование ASP.NET cache (но я считаю, что обычно предполагается хранить информацию, которая должна быть передана пользователям, поэтому я смотрю на другие дваoptions).
  • Добавление пользовательской строки с userId в часть UserData FormsAuthenticationTicket.
  • Использование Session State.

Так что в настоящее время явыбор между двумя последними.

Изменение FormsAuthenticationTicket не совсем просто.Кроме того, он не работает с аутентификацией форм без cookie (как указано здесь ).

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

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

Заранее спасибо!

Ответы [ 3 ]

3 голосов
/ 11 июля 2011

Вы, кажется, изобретаете здесь некоторые колеса. Хотя это может быть приемлемо при выполнении какого-либо стандартного кода, но при обеспечении безопасности это почти всегда приводит к катастрофическим последствиям.

Для отслеживания активно вошедшего в систему пользователя, я бы порекомендовал вам использовать аутентификацию форм (и вот еще полезное руководство ). Он использует куки аутентификации для отслеживания пользователей. Эти куки-файлы надежно зашифрованы платформой, поэтому их нельзя изменить с помощью раздела <machineKey> файла machine.config сервера.

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

public static string GetUserId(HttpContextBase context)
{
    if (context == null || !context.User.Identity.IsAuthenticated)
    {
        return null;
    }

    return context.User.Identity.Name;
}

Вы действительно не должны обрабатывать все эти вещи вручную, особенно если в ASP.NET есть встроенный механизм для этого.

2 голосов
/ 10 июля 2011

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

Все, что вам когда-либо понадобитсяобменяться с клиентом - это идентификатор сессии, действительно.

0 голосов
/ 11 июля 2011

вы также можете зашифровать куки с помощью Secure Socket Layer HttpCookie cookie = new HttpCookie(); cookie.Secure = true;

...