Was sind erlaubte Zeichen in Cookies?

301

Was sind die zulässigen Zeichen in Cookie-Name und Wert? Entsprechen sie einer URL oder einer gemeinsamen Teilmenge?

Der Grund, den ich -frage , ist, dass ich kürzlich ein seltsames Verhalten mit Cookies festgestellt habe, die ihren Namen haben, und ich frage mich nur, ob es etwas Browserspezifisches ist oder ob mein Code fehlerhaft ist.

Esko
quelle

Antworten:

391

Das ist ein Quickie:

Sie könnten denken, es sollte sein, aber es ist wirklich überhaupt nicht!

Was sind die zulässigen Zeichen in Cookie-Name und Wert?

Laut der alten Netscape cookie_spec ist die gesamte NAME=VALUEZeichenfolge:

Eine Folge von Zeichen ohne Semikolon, Komma und Leerzeichen.

Sollte also -funktionieren, und es scheint in Browsern, die ich hier habe, in Ordnung zu sein; Wo hast du Probleme damit?

Aus impliziten Gründen:

  • =ist legal einzuschließen, aber möglicherweise mehrdeutig. Browser teilen immer den Namen und den Wert des ersten =Symbols in der Zeichenfolge auf, sodass Sie in der Praxis ein =Symbol in den Wert, aber nicht in den Namen einfügen können.

Was nicht erwähnt wird, weil Netscape schrecklich darin war, Spezifikationen zu schreiben, aber von Browsern konsequent unterstützt zu werden scheint:

  • entweder der NAME oder der VALUE können leere Zeichenfolgen sein

  • Wenn =die Zeichenfolge überhaupt kein Symbol enthält, wird sie von den Browsern als Cookie mit dem Namen der leeren Zeichenfolge behandelt, dh es Set-Cookie: fooist dasselbe wie Set-Cookie: =foo.

  • Wenn Browser ein Cookie mit einem leeren Namen ausgeben, wird das Gleichheitszeichen weggelassen. Also Set-Cookie: =barzeugt Cookie: bar.

  • Kommas und Leerzeichen in Namen und Werten scheinen tatsächlich zu funktionieren, obwohl Leerzeichen um das Gleichheitszeichen gekürzt werden

  • Steuerzeichen ( \x00bis \x1Fplus \x7F) sind nicht erlaubt

Was nicht erwähnt wird und Browser völlig inkonsistent sind, sind Nicht-ASCII-Zeichen (Unicode):

  • In Opera und Google Chrome werden sie mit UTF-8 in Cookie-Header codiert.
  • Im IE wird die Standardcodepage des Computers verwendet (länderspezifisch und niemals UTF-8).
  • Firefox (und andere Mozilla-basierte Browser) verwenden das Low-Byte jedes UTF-16-Codepunkts für sich (ISO-8859-1 ist also in Ordnung, aber alles andere ist verstümmelt).
  • Safari lehnt es einfach ab, Cookies zu senden, die Nicht-ASCII-Zeichen enthalten.

In der Praxis können Sie daher in Cookies überhaupt keine Nicht-ASCII-Zeichen verwenden. Wenn Sie Unicode, Steuercodes oder andere beliebige Bytesequenzen verwenden möchten, fordert cookie_spec, dass Sie ein Ad-hoc-Codierungsschema Ihrer Wahl verwenden und eine URL-Codierung (wie von JavaScript erstellt encodeURIComponent) als vernünftige Wahl vorschlagen .

In Bezug auf die tatsächlichen Standards gab es einige Versuche, das Verhalten von Cookies zu kodifizieren, aber bisher spiegelte keiner tatsächlich die reale Welt wider.

  • RFC 2109 war ein Versuch, die ursprüngliche Netscape cookie_spec zu codieren und zu reparieren. In diesem Standard sind viele weitere Sonderzeichen nicht zulässig , da RFC 2616- Token verwendet werden (a -ist dort noch zulässig), und nur der Wert darf in einer Zeichenfolge in Anführungszeichen mit anderen Zeichen angegeben werden. Kein Browser hat jemals die Einschränkungen, die spezielle Behandlung von Zeichenfolgen und Escapezeichen in Anführungszeichen oder die neuen Funktionen in dieser Spezifikation implementiert.

  • RFC 2965 war ein weiterer Versuch, 2109 aufzuräumen und weitere Funktionen im Rahmen eines Cookies der Version 2 hinzuzufügen. Auch das hat noch niemand umgesetzt. Diese Spezifikation hat die gleichen Einschränkungen für Token und Zeichenfolgen wie die frühere Version und ist genauso viel Unsinn.

  • RFC 6265 ist ein Versuch aus der HTML5-Ära, das historische Durcheinander zu beseitigen. Es stimmt immer noch nicht genau mit der Realität überein, aber es ist viel besser als die früheren Versuche - es ist zumindest eine richtige Teilmenge dessen, was Browser unterstützen, und führt keine Syntax ein, die funktionieren soll, aber nicht funktioniert (wie die zuvor zitierte Zeichenfolge). .

In 6265 wird der Cookie-Name immer noch als RFC 2616 angegeben token, was bedeutet, dass Sie aus den Alphanums plus auswählen können:

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

Im Cookie-Wert werden die (nach Browsern gefilterten) Steuerzeichen und (inkonsistent implementierten) Nicht-ASCII-Zeichen formell gesperrt. Das Verbot von Leerzeichen, Komma und Semikolon von cookie_spec sowie die Kompatibilität mit armen Idioten, die die früheren RFCs implementiert haben, wurden beibehalten. Außerdem wurden Backslash und Anführungszeichen verboten, außer Anführungszeichen, die den gesamten Wert umschließen (in diesem Fall werden die Anführungszeichen jedoch weiterhin als Teil von betrachtet der Wert, kein Kodierungsschema). So bleiben Ihnen die Alphanums plus:

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

In der realen Welt verwenden wir immer noch die ursprünglichste und schlechteste Netscape cookie_spec. Daher sollte Code, der Cookies verwendet, auf so ziemlich alles vorbereitet sein. Für Code, der Cookies erzeugt, ist es jedoch ratsam, sich an die Teilmenge in RFC 6265 zu halten.

Bobince
quelle
@bobince Meinst du, dass der RFC angibt, dass Cookie-Werte den ;Charakter haben können, solange sie in doppelte Anführungszeichen gesetzt sind? Als solche:Set-Cookie: Name=Va";"lue; Max-Age=3600
Pacerier
@Pacerier: Der gesamte Wert müsste eine Zeichenfolge in Anführungszeichen sein, also müsste es sein Name="Va;lue"; max-age.... Es funktioniert nicht in Browsern und ist in RFC 6265 nicht zulässig, das 2965 ersetzen soll und versucht, die Realität ein wenig besser widerzuspiegeln.
Bobince
@bobince - Ich weiß, dass dies alt ist, aber lese ich Ihre Antwort richtig, um zu bedeuten, dass Leerzeichen in Cookie-Werten technisch nicht zulässig sind? "Ohne
Semikolon
1
@Adam: Ja, wenn Sie sich an die Netscape-Spezifikation oder RFC 6265 halten, ist Leerzeichen in einem unformatierten (un-DQUOTEd) Cookie-Wert nicht zulässig. Es funktioniert trotzdem in Browsern, die ich ausprobiert habe, aber ich würde mich nicht darauf verlassen.
Bobince
2
RFC 6265 definiert Token wie 1*<any CHAR except CTLs or separators>und Separatoren sind (, ), <, >, @, ,, ;, :, \, ", /, [, ], ?, =, {, }, SPund HT, so Cookie - Namen sollten alphanums plus!#$%&'*+-.?^_`|~
Gan Quan
28

In ASP.Net können Sie System.Web.HttpUtilityden Cookie-Wert vor dem Schreiben in das Cookie sicher codieren und beim Auslesen wieder in seine ursprüngliche Form konvertieren.

// Encode
HttpUtility.UrlEncode(cookieData);

// Decode
HttpUtility.UrlDecode(encodedCookieData);

Dies stoppt kaufmännisches Und und Gleichheitszeichen, die einen Wert in eine Reihe von Name / Wert-Paaren aufteilen, während er in ein Cookie geschrieben wird.

stephen
quelle
1
Nur eine Anmerkung: intern verwendet asp.net beim Speichern des Authentifizierungscookies Hex-Codierung anstelle von UrlEncode. referencesource.microsoft.com # System.Web / Security /… kann es also Fälle geben, in denen die URL-Codierung nicht funktioniert?
Peter
17

Ich denke, es ist im Allgemeinen browserspezifisch. Um auf der sicheren Seite zu sein, codiert base64 ein JSON-Objekt und speichert alles darin. Auf diese Weise müssen Sie es nur dekodieren und den JSON analysieren. Alle in base64 verwendeten Zeichen sollten mit den meisten, wenn nicht allen Browsern gut funktionieren.

Jamie Rumbelow
quelle
Diese Antwort scheint in allen Browsern konsistent zu sein. Ich erkannte dies, nachdem ich viele Stunden gearbeitet hatte, um eine schnelle Lösung zu finden: Ich bekam auch keine. Tun Sie einfach wie oben empfohlen, um sich den Ärger zu ersparen.
Lächeln
Ich habe es nicht versucht, aber ich habe andere Beiträge darüber gelesen, in denen es heißt, dass base64 encode nur mit ASCII-Zeichen funktioniert.
user984003
11

Hier ist es in so wenigen Worten wie möglich . Konzentrieren Sie sich auf Charaktere, die nicht entkommen müssen:

Für Cookies:

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

Für URLs

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

Für Cookies und URLs (Kreuzung)

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

So antwortest du.

Beachten Sie, dass bei Cookies das = entfernt wurde, da es normalerweise zum Festlegen des Cookie-Werts verwendet wird.

Für URLs wurde dies = beibehalten. Die Kreuzung ist offensichtlich ohne.

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

Es stellt sich heraus, dass es immer noch zu unerwarteten Ereignissen kommt, insbesondere in einer Java-Cookie-Umgebung, in der das Cookie in doppelte Anführungszeichen gesetzt wird, wenn es auf die letzten Zeichen trifft.

Verwenden Sie zur Sicherheit einfach A-Za-z1-9. Das werde ich tun.

mmm
quelle
Safari Cookies war mein einziger Problembrowser - alle anderen Browser funktionierten einwandfrei. Ich musste meinen Cookie mit UrlEncode und UrlDecode bearbeiten, um mit Gleichheitszeichen und Leerzeichen umgehen zu können. Wie ein Base64Encode im Cookie. (Safari nur erforderlich - andere Browser funktionierten gut mit und ohne das codierte Cookie.)
SQL Surfer
Es ist besser, wenn Sie auflisten, welche Quellen zu Ihrer Antwort führen!
Loc
1
@Loc Über 3 Stunden Probezeit und Inspektion.
mmm
10

Neuere rfc6265 veröffentlicht im April 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

Wenn Sie auf die Antwort von @bobince schauen, sehen Sie, dass neuere Einschränkungen strenger sind.

Gavenkoa
quelle
6

Sie können nicht ";" Im Wertefeld eines Cookies wird als Name die Zeichenfolge bis zum ";" in den meisten Browsern ...

hagay onn
quelle
1

Es gibt 2 Versionen der Cookies-Spezifikationen:
1. Version 0-Cookies, auch bekannt als Netscape-Cookies,
2. Version 1, auch bekannt als RFC 2965-Cookies.
In Version 0 sind der Name und der Wertteil von Cookies Zeichenfolgen, ausgenommen Semikolon, Komma, Gleichheitszeichen und Leerzeichen Wenn es nicht mit doppelten Anführungszeichen verwendet wird, ist
Version 1 viel komplizierter. Sie können es hier überprüfen.
In dieser Version sind die Spezifikationen für den Namen-Wert-Teil fast gleich, außer dass der Name nicht mit dem $ -Zeichen beginnen kann

Tinku
quelle
Wo steht, dass Werte in Version 0 Gleichheitszeichen ausschließen müssen?
Gili
1

Es gibt ein weiteres interessantes Problem mit IE und Edge. Cookies mit Namen mit mehr als einem Punkt scheinen stillschweigend gelöscht zu werden. Das funktioniert also:

cookie_name_a = valueea

während dies fallen gelassen wird

cookie.name.a = valueea

Arvoreen
quelle
Wäre großartig, wenn Sie die genaue Browserversion hinzufügen, damit wir sie replizieren können, da das Browserverhalten bei Cookies nicht konsistent ist.
Gerald
0

das ist einfach:

Ein <Kochname> kann ein beliebiges US-ASCII-Zeichen sein, mit Ausnahme von Steuerzeichen (CTLs), Leerzeichen oder Tabulatoren. Es darf auch kein Trennzeichen wie das folgende enthalten: () <> @ ,; : \ "/ []? = {}.

Ein <cookie-Wert> kann optional in doppelte Anführungszeichen gesetzt werden, und alle US-ASCII-Zeichen mit Ausnahme von CTLs, Leerzeichen, doppelten Anführungszeichen, Komma, Semikolon und Backslash sind zulässig. Codierung: Viele Implementierungen führen eine URL-Codierung für Cookie-Werte durch, die jedoch gemäß der RFC-Spezifikation nicht erforderlich ist. Es hilft jedoch, die Anforderungen zu erfüllen, für die Zeichen zulässig sind.

Link: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives

Webolizzer
quelle
0

Noch eine Überlegung. Ich habe kürzlich ein Schema implementiert, in dem einige vertrauliche Daten, die in ein PHP-Skript gepostet wurden, konvertiert und als verschlüsseltes Cookie zurückgegeben werden mussten. Dabei wurden alle base64-Werte verwendet, die ich für "sicher" hielt. Also habe ich die Datenelemente pflichtbewusst mit RC4 verschlüsselt und ausgeführt Die Ausgabe über base64_encode und die glückliche Rückgabe des Cookies an die Site. Das Testen schien gut zu laufen, bis eine base64-codierte Zeichenfolge ein "+" - Symbol enthielt. Die Zeichenfolge wurde ohne Probleme in das Seiten-Cookie geschrieben. Mit der Browser-Diagnose konnte ich auch Überprüfen Sie, ob die Cookies unverändert geschrieben wurden. Als dann eine nachfolgende Seite mein PHP aufrief und das Cookie über das Array $ _COOKIE erhielt, stammelte ich und stellte fest, dass in der Zeichenfolge jetzt das "+" - Zeichen fehlte. Jedes Vorkommen dieses Zeichens wurde durch ein ersetzt ASCII-Speicherplatz.

Angesichts der Anzahl ähnlicher ungelöster Beschwerden, die ich seitdem gelesen habe und die dieses Szenario beschreiben, und der häufig zahlreiche Verweise auf die Verwendung von base64 zum "sicheren" Speichern beliebiger Daten in Cookies enthält, dachte ich, ich würde auf das Problem hinweisen und meine zugegebenermaßen klobige Lösung anbieten.

Nachdem Sie die gewünschte Verschlüsselung für ein Datenelement vorgenommen und dann base64_encode verwendet haben, um es "Cookie-sicher" zu machen, führen Sie die Ausgabezeichenfolge durch ...

// 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;
    }

Hier ersetze ich einfach "+" (und ich habe auch "=" entschieden) durch andere "Cookie-sichere" Zeichen, bevor ich den codierten Wert zur Verwendung als Cookie auf die Seite zurückbringe. Beachten Sie, dass sich die Länge der verarbeiteten Zeichenfolge nicht ändert. Wenn dieselbe (oder eine andere Seite auf der Site) mein PHP-Skript erneut ausführt, kann ich dieses Cookie ohne fehlende Zeichen wiederherstellen. Ich muss nur daran denken, das Cookie über denselben fix64 () -Aufruf zurückzugeben, den ich erstellt habe, und von dort aus kann ich es mit dem üblichen base64_decode () dekodieren, gefolgt von jeder anderen Entschlüsselung in Ihrem Schema.

Möglicherweise kann ich in PHP eine Einstellung vornehmen, mit der in Cookies verwendete Base64-Zeichenfolgen ohne Beschädigung wieder auf PHP übertragen werden können. In der Zwischenzeit funktioniert das. Das "+" kann ein "legaler" Cookie-Wert sein. Wenn Sie jedoch eine solche Zeichenfolge an PHP zurücksenden möchten (in meinem Fall über das Array $ _COOKIE), empfehle ich eine erneute Verarbeitung zum Entfernen beleidigende Zeichen und stellen Sie sie nach der Wiederherstellung wieder her. Es gibt viele andere "Cookie-sichere" Charaktere zur Auswahl.

Geil
quelle
0

Wenn Sie die Variablen später verwenden, werden Sie feststellen, dass Dinge wie pathAkzentzeichen tatsächlich durchlassen, aber nicht mit dem Browserpfad übereinstimmen. Dafür müssen Sie sie URIEncode. Also dh so:

  const encodedPath = encodeURI(myPath);
  document.cookie = `use_pwa=true; domain=${location.host}; path=${encodedPath};`

Die "erlaubten" Zeichen könnten also mehr sein als in der Spezifikation angegeben. Sie sollten jedoch innerhalb der Spezifikation bleiben und aus Sicherheitsgründen URI-codierte Zeichenfolgen verwenden.

Odinho - Velmont
quelle
-1

Vor Jahren hatte MSIE 5 oder 5.5 (und wahrscheinlich beide) ein ernstes Problem mit einem "-" im HTML-Block, wenn Sie es glauben können. Obwohl es nicht direkt damit zusammenhängt, haben wir einen MD5-Hash (der nur Buchstaben und Zahlen enthält) im Cookie gespeichert, um alles andere in der serverseitigen Datenbank nachzuschlagen.

FYA
quelle
-2

Am Ende habe ich verwendet

cookie_value = encodeURIComponent(my_string);

und

my_string = decodeURIComponent(cookie_value);

Das scheint für alle Arten von Charakteren zu funktionieren. Ich hatte ansonsten seltsame Probleme, selbst mit Zeichen, die keine Semikolons oder Kommas waren.

user984003
quelle