Разрешенные символы в файлах cookie

этот быстрый:

Каковы допустимые символы в имени и значении cookie? Являются ли они такими же, как URL или некоторые общие подмножества?

Причина, о которой я прошу, заключается в том, что я недавно столкнулся с каким-то странным поведением с файлами cookie, которые имеют - в своем имени, и мне просто интересно, не является ли это чем-то конкретным браузером или если мой код неисправен.

Ответ 1

этот быстрый:

Вы можете подумать, что это должно быть, но на самом деле это совсем не так!

Каковы допустимые символы в имени и значении cookie?

В соответствии с древним Netscape cookie_spec вся строка NAME=VALUE:

последовательность символов, исключая запятую, запятую и пробел.

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

Подразумевается выше:

  • = является законным включать, но потенциально двусмысленным. Браузеры всегда разделяют имя и значение на первом символе = в строке, поэтому на практике вы можете поместить символ = в VALUE, но не в ИМЯ.

Что не упоминается, потому что Netscape были ужасны при написании спецификаций, но, кажется, последовательно поддерживаются браузерами:

  • либо NAME, либо VALUE могут быть пустыми строками

  • если в строке вообще нет символа =, браузеры рассматривают его как файл cookie с именем пустой строки, то есть Set-Cookie: foo совпадает с Set-Cookie: =foo.

  • когда браузеры выводят файл cookie с пустым именем, они опускают знак равенства. Итак, Set-Cookie: =bar порождает Cookie: bar.

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

  • управляющие символы (\x00 - \x1F plus \x7F) не разрешены

Что не упоминается, и браузеры абсолютно несовместимы, это символы, отличные от ASCII (Unicode):

  • в Opera и Google Chrome они закодированы в заголовки Cookie с UTF-8;
  • в IE используется кодовая страница машины по умолчанию (специфичная для локали и никогда не UTF-8);
  • Firefox (и другие браузеры на основе Mozilla) используют младший байт каждой кодовой точки UTF-16 самостоятельно (так что ISO-8859-1 в порядке, но все остальное искажено);
  • Safari просто отказывается отправлять какие-либо файлы cookie, содержащие не-ASCII-символы.

поэтому на практике вы не можете использовать символы, отличные от ASCII, в файлах cookie. Если вы хотите использовать Unicode, управляющие коды или другие произвольные последовательности байтов, cookie_spec требует, чтобы вы использовали специальную схему кодирования по своему выбору и предлагали кодирование URL (как это было создано JavaScript encodeURIComponent) в качестве разумного выбора.

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

  • RFC 2109 была попытка кодифицировать и исправить исходный файл cookie Netscape. В этом стандарте многие другие специальные символы запрещены, поскольку он использует RFC 2616 (a - по-прежнему разрешено там), и только значение может указываться в кавычках с другими символами. Ни один браузер никогда не реализовал ограничения, специальную обработку цитированных строк и экранирование, а также новые функции в этой спецификации.

  • RFC 2965 - это еще один шаг к этому, уборка 2109 и добавление дополнительных функций в "куки-версию версии 2". Никто никогда не реализовал ни одно из них. Эта спецификация имеет те же ограничения на токен-и-кавычки, что и в более ранней версии, и на столько же нагрузка ерунды.

  • RFC 6265 - это попытка HTML5-эры для устранения исторического беспорядка. Он по-прежнему не соответствует действительности, но намного лучше, чем предыдущие попытки - это, по крайней мере, правильное подмножество того, что поддерживает браузер, а не введение какого-либо синтаксиса, который должен работать, но не (как и предыдущая кавычка).

В 6265 имя файла cookie все еще указано как RFC 2616 token, что означает, что вы можете выбрать из букв плюс:

!#$%&'*+-.^_`|~

В значении cookie оно формально запрещает управляемые символы (отфильтрованные браузерами) и (непоследовательно-реализованные) символы, отличные от ASCII. Он сохраняет запрет cookie_spec на пространство, запятую и точку с запятой, а также для совместимости с любыми бедными идиотами, которые на самом деле реализовали предыдущие RFC, а также запретили обратную косую черту и кавычки, за исключением кавычек, обертывающих всю ценность (но в этом случае кавычки по-прежнему считаются частью значение, а не схема кодирования). Таким образом, вы получите букву плюс:

!#$%&'()*+-./:<=>[email protected][]^_`{|}~

В реальном мире мы по-прежнему используем оригинальный и худший Netscape cookie_spec, поэтому код, который потребляет файлы cookie, должен быть готов к тому, чтобы встречаться практически во всем, но для кода, который создает файлы cookie, желательно придерживаться подмножества в RFC 6265.

Ответ 2

В ASP.Net вы можете использовать System.Web.HttpUtility, чтобы безопасно кодировать значение cookie перед записью в файл cookie и преобразовать его обратно в исходную форму при чтении.

// Encode
HttpUtility.UrlEncode(cookieData);

// Decode
HttpUtility.UrlDecode(encodedCookieData);

Это остановит амперсанды и примет знаки, разделяющие значение, на кучу пар имя/значение, поскольку оно записано в файл cookie.

Ответ 3

Я думаю, что это вообще браузер специфический. Чтобы быть в безопасности, base64 кодирует объект JSON и сохраняет все в этом. Таким образом, вам просто нужно его расшифровать и проанализировать JSON. Все символы, используемые в base64, должны отлично работать с большинством, если не во всех браузерах.

Ответ 4

Вот он, как можно меньше слов. Сосредоточьтесь на символах, которые не требуют экранирования:

Для файлов cookie:

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!#$%&'()*+-./:<>[email protected][]^_`{|}~

Для URL-адресов

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789.-_~!$&'()*+,;=:@

Для файлов cookie и URL-адресов (пересечение)

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!$&'()*+-.:@_~

Как вы отвечаете.

Обратите внимание, что для файлов cookie значение = было удалено, так как оно обычно используется для установки значения cookie.

Для URL-адресов это значение было сохранено. Пересечения, очевидно, нет.

var chars = "abdefghijklmnqrstuvxyz"; chars += chars.toUpperCase() + "0123456789" + "!$&'()*+-.:@_~";

Выключает экранирование, которое все еще происходит и неожиданно происходит, особенно в среде Java cookie, где куки файл обернут двойными кавычками, если он встречает последние символы.

Чтобы быть в безопасности, просто используйте A-Za-z1-9. Это то, что я собираюсь делать.

Ответ 5

Более новый rfc6265, опубликованный в апреле 2011 года:

cookie-header = "Cookie:" OWS cookie-string OWS
cookie-string = cookie-pair *( ";" SP cookie-pair )
cookie-pair  = cookie-name "=" cookie-value
cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )

cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
                   ; US-ASCII characters excluding CTLs,
                   ; whitespace DQUOTE, comma, semicolon,
                   ; and backslash

Если вы посмотрите на @bobince ответ, вы увидите, что более новое ограничение более строгое.

Ответ 6

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

Ответ 7

Существует 2 версии спецификаций файлов cookie
 1. Версия 0 cookie aka Файлы cookie Netscape,
 2. Версия 1, а также cookie RFC 2965

В версии 0 Имя и значение части файлов cookie - это последовательности символов, исключая точку с запятой, запятую, знак равенства и пробелы, если они не используются с двойными кавычками
 версия 1 намного сложнее, вы можете ее проверить здесь
В этой версии спецификация для части значения имени почти такая же, за исключением того, что имя не может начинаться со знака $sign

Ответ 8

Есть еще одна интересная проблема с IE и Edge. Файлы cookie с именами более 1 периода, по-видимому, молча отбрасываются. Так что это работает:

cookie_name_a = значение а

пока это упадет

cookie.name.a = значение а

Ответ 9

так просто:

<Cookie-name> может быть любым символом US-ASCII, кроме управляющих символов (CTL), пробелов или символов табуляции. Он также не должен содержать символ-разделитель, например:() <> @,; знак равно

<Cookie-значение> может быть необязательно установлено в двойных кавычках, и любые символы US-ASCII, за исключением CTL, пробелов, двойных кавычек, запятой, точки с запятой и обратной косой черты, допускаются. Кодировка. Многие реализации выполняют кодирование URL-адресов для значений файлов cookie, однако это не требуется согласно спецификации RFC. Это помогает удовлетворить требования о том, какие символы разрешены.

Ссылка: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives

Ответ 10

Еще одно соображение. Недавно я реализовал схему, в которой некоторые конфиденциальные данные, публикуемые в сценарии PHP, должны были преобразовываться и возвращаться в виде зашифрованного файла cookie, в котором использовались все значения base64, которые я считал гарантированно "безопасными". Поэтому я должным образом зашифровал элементы данных с помощью RC4, запустив вывод через base64_encode и благополучно вернул cookie на сайт. Тестирование шло хорошо, пока строка в кодировке base64 не содержала символ "+". Строка была записана в cookie страницы без проблем. С помощью диагностики браузера я также мог убедитесь, что файлы cookie были записаны без изменений. Затем, когда на следующей странице был вызван мой PHP и получен файл cookie через массив $ _COOKIE, я заикался, обнаружив, что в строке теперь отсутствует знак "+". Каждое вхождение этого символа заменялось на Пространство ASCII.

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

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

// from browser to PHP. substitute troublesome chars with 
// other cookie safe chars, or vis-versa.  

function fix64($inp) {
    $out =$inp;
    for($i = 0; $i < strlen($inp); $i++) {
        $c = $inp[$i];
        switch ($c) {
            case '+':  $c = '*'; break; // definitly won't transfer!
            case '*':  $c = '+'; break;

            case '=':  $c = ':'; break; // = symbol seems like a bad idea
            case ':':  $c = '='; break;

            default: continue;
            }
        $out[$i] = $c;
        }
    return $out;
    }

Здесь я просто заменяю "+" (и я решил "=") другими символами "cookie", прежде чем возвращать закодированное значение на страницу для использования в качестве cookie. Обратите внимание, что длина обрабатываемой строки не изменяется. Когда тот же (или другая страница на сайте) снова запустит мой PHP-скрипт, я смогу восстановить этот cookie без пропущенных символов. Мне просто нужно помнить, чтобы передать cookie обратно через тот же вызов fix64(), который я создал, и оттуда я могу декодировать его с помощью обычной base64_decode(), за которой следует любая другая расшифровка в вашей схеме.

Могут быть некоторые настройки, которые я могу сделать в PHP, которые позволяют передавать строки base64, используемые в cookie, обратно в PHP без повреждения. В то же время это работает. "+" Может быть "допустимым" значением cookie, но если у вас есть желание передать такую строку обратно в PHP (в моем случае через массив $ _COOKIE), я предлагаю повторную обработку для удаления оскорблять персонажей и восстанавливать их после восстановления. Есть множество других "безопасных от печенья" символов на выбор.

Ответ 11

Несколько лет назад MSIE 5 или 5.5 (и, вероятно, оба) имели серьезную проблему с "-" в блоке HTML, если вы можете в это поверить. Хотя это не связано напрямую, с тех пор как мы сохранили хэш MD5 (содержащий только буквы и цифры) в файле cookie, чтобы найти все остальное в базе данных на стороне сервера.

Ответ 12

Я закончил тем, что использовал

cookie_value = encodeURIComponent(my_string);

и

my_string = decodeURIComponent(cookie_value);

Это похоже на все виды персонажей. В противном случае у меня были странные проблемы, даже с символами, которые не были точками с запятой или запятыми.