쿠키에 허용되는 문자는 무엇입니까?


301

쿠키 이름과 값에 허용되는 문자는 무엇입니까? URL 또는 일반적인 하위 집합과 동일합니까?

내가 묻는 이유는 최근에 -이름 이 있는 쿠키로 이상한 행동을했으며 브라우저에 특정한 것인지 또는 코드에 결함이 있는지 궁금합니다.

답변:


391

이 사람은 빠르다 :

당신은 그것이 있어야한다고 생각할 수도 있지만 실제로는 그렇지 않습니다!

쿠키 이름과 값에 허용되는 문자는 무엇입니까?

고대 Netscape cookie_spec 에 따르면 전체 NAME=VALUE문자열은 다음과 같습니다.

세미콜론, 쉼표 및 공백을 제외한 일련의 문자

그래서 -일을해야하고, 내가 여기에있어 브라우저에서 확인을 것으로 보인다; 어디에 문제가 있습니까?

위의 의미로 :

  • =포함하는 것이 합법적이지만 잠재적으로 모호 할 수 있습니다. 브라우저는 항상 =문자열 의 첫 번째 기호에서 이름과 값을 분리 하므로 실제로 =는 NAME이 아닌 VALUE에 기호를 넣을 수 있습니다 .

언급되지 않은 것은 Netscape가 스펙 작성에 끔찍하지만 브라우저에서 지속적으로 지원되는 것 같습니다.

  • NAME 또는 VALUE는 빈 문자열 일 수 있습니다.

  • =문자열에 기호 가 없으면 브라우저는이를 빈 문자열 이름을 가진 쿠키로 취급합니다 . 즉와 Set-Cookie: foo동일합니다 Set-Cookie: =foo.

  • 브라우저가 빈 이름으로 쿠키를 출력하면 등호를 생략합니다. 그래서 Set-Cookie: =bar낳는다 Cookie: bar.

  • 등호 주위의 공백은 잘리지 만 이름과 값의 쉼표와 공백은 실제로 작동하는 것 같습니다.

  • 제어 문자 ( \x00~ \x1F더하기 \x7F)는 허용되지 않습니다

언급되지 않았고 브라우저가 완전히 일치하지 않는 것은 ASCII가 아닌 문자입니다 (유니 코드).

  • Opera와 Chrome에서는 UTF-8을 사용하여 쿠키 헤더로 인코딩됩니다.
  • IE에서는 시스템의 기본 코드 페이지가 사용됩니다 (로케일 별 및 UTF-8은 아님).
  • Firefox (및 기타 Mozilla 기반 브라우저)는 각 UTF-16 코드 포인트의 낮은 바이트를 자체적으로 사용합니다 (따라서 ISO-8859-1은 정상이지만 다른 것은 엉망입니다).
  • Safari는 단순히 ASCII가 아닌 문자를 포함하는 쿠키의 전송을 거부합니다.

실제로 쿠키에는 ASCII가 아닌 문자를 전혀 사용할 수 없습니다. 유니 코드, 제어 코드 또는 기타 임의 바이트 시퀀스를 사용하려는 경우 cookie_spec은 사용자가 선택한 임시 인코딩 체계를 사용하도록 요구하고 (JavaScript에서 생성 한대로) URL 인코딩을 encodeURIComponent합리적인 선택으로 제안 합니다.

의 측면에서 실제 표준이 성문화 쿠키 행동 몇 가지 시도를하고 있지만, 아무도 지금까지 실제로 현실 세계를 반영 없다.

  • RFC 2109 는 원래 Netscape cookie_spec을 체계화하고 수정하려는 시도였습니다. 이 표준에서는 RFC 2616 토큰 (a -여전히 허용됨)을 사용하므로 더 많은 특수 문자가 허용되지 않으며 다른 문자와 함께 따옴표로 묶인 문자열에 값만 지정할 수 있습니다. 어떤 브라우저도 한계, 인용 된 문자열의 특수 처리 및 이스케이프 처리 또는이 사양의 새로운 기능을 구현 한 적이 없습니다.

  • RFC 2965 는 2109를 정리하고 '버전 2 쿠키'체계로 더 많은 기능을 추가했습니다. 아무도 그 중 어느 것도 구현하지 않았습니다. 이 스펙은 이전 버전과 동일한 토큰 및 따옴표로 묶인 문자열 제한을 가지고 있으며, 말도 안되는 많은 부하입니다.

  • RFC 6265 는 역사적 혼란을 해결하기위한 HTML5 시대의 시도입니다. 여전히 실제와 정확히 일치하지는 않지만 이전 시도보다 훨씬 낫습니다. 브라우저가 지원하는 것 중 적어도 일부는 작동하지만 작동하지 않는 구문을 도입하지는 않습니다 (이전 인용 문자열) .

6265에서 쿠키 이름은 여전히 ​​RFC 2616으로 지정됩니다. token즉, 영숫자 더하기에서 선택할 수 있습니다.

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

쿠키 값에서는 (브라우저에 의해 필터링 된) 제어 문자와 (일관되지 않은) 비 ASCII 문자를 공식적으로 금지합니다. 공간, 쉼표 및 세미콜론에 대한 cookie_spec의 금지를 유지하고 실제로 이전 RFC를 구현 한 가난한 바보와의 호환성을 위해 전체 값을 감싸는 따옴표 이외의 백 슬래시와 따옴표를 금지했습니다 (그러나이 경우 따옴표는 여전히 인코딩 체계가 아닌 값). 따라서 알파 플러스와 함께 당신을 떠나십시오 :

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

실제로 우리는 원래의 최악의 Netscape cookie_spec을 사용하고 있으므로 쿠키를 소비하는 코드는 거의 모든 것을 만날 준비가되어 있어야하지만 쿠키를 생성하는 코드의 경우 RFC 6265의 하위 집합을 따르는 것이 좋습니다.


@bobince RFC에서 쿠키 값 ;이 큰 따옴표로 묶인 한 문자를 가질 수 있다고 명시하고 있습니까? 같은 :Set-Cookie: Name=Va";"lue; Max-Age=3600
Pacerier

@Pacerier : 전체 값은 따옴표로 묶어야하므로이어야 Name="Va;lue"; max-age...합니다. 브라우저에서는 작동하지 않으며 RFC 6265에서는 허용되지 않습니다. RFC 6265는 2965를 대체하도록 제안되었으며 현실을 조금 더 잘 반영하려고 시도합니다.
bobince

@bobince-이것이 오래되었다는 것을 알고 있지만 쿠키 값에서 공백이 기술적으로 허용되지 않는다는 것을 의미하는 답을 올바르게 읽고 있습니까? "세미콜론, 쉼표를 제외한 공백을 " [강조 광산]
아담 Rackis

1
@Adam : 그렇습니다. Netscape 사양이나 RFC 6265를 사용하는 경우 원시 (비 DQUOTEd) 쿠키 값에는 공백이 허용되지 않습니다. 그럼에도 불구하고 시도한 브라우저에서 작동하지만 의존하지는 않습니다.
bobince 2013

2
RFC 6265 명 을 정의로 토큰 1*<any CHAR except CTLs or separators>과 분리되어 (, ), <, >, @, ,, ;, :, \, ", /, [, ], ?, =, {, }, SPHT, 쿠키 이름은 alphanums해야하므로 플러스!#$%&'*+-.?^_`|~
웨이 코 뮤니시 콴

28

ASP.Net에서는 System.Web.HttpUtility쿠키에 쓰기 전에 쿠키 값을 안전하게 인코딩하고 읽을 때 쿠키를 원래 형식으로 다시 변환하는 데 사용할 수 있습니다 .

// Encode
HttpUtility.UrlEncode(cookieData);

// Decode
HttpUtility.UrlDecode(encodedCookieData);

이렇게하면 앰퍼샌드가 중지되고 값이 쿠키에 기록 될 때 값을 여러 이름 / 값 쌍으로 분할하는 부호와 같습니다.


1
내부적으로 asp.net은 인증 쿠키를 저장할 때 UrlEncode 대신 16 진 인코딩을 사용합니다. referencesource.microsoft.com # System.Web / Security /… URL 인코딩이 잘리지 않는 경우가 있습니까?
피터

17

일반적으로 브라우저마다 다릅니다. 안전한 측면을 유지하기 위해 base64는 JSON 객체를 인코딩하고 모든 것을 저장합니다. 그렇게하면 해독하고 JSON을 구문 분석해야합니다. base64에 사용 된 모든 문자는 모든 브라우저가 아니라도 대부분 잘 재생됩니다.


이 답변은 여러 브라우저에서 일관된 답변으로 보입니다. 나는 빠른 해결책을 얻으려고 많은 시간을 일한 후에 이것을 깨달았습니다 : 나는 하나도 얻지 못했습니다. 번거 로움을 덜기 위해 위의 권장 사항대로하십시오.
미소

이것을 시도하지는 않았지만 base64 인코딩은 ASCII 문자로만 작동한다는 다른 게시물을 읽었습니다.
user984003

11

여기에 가능한 한 적은 단어가 있습니다 . 탈출 할 필요가없는 캐릭터에 집중하십시오 :

쿠키의 경우 :

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

URL의 경우

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

쿠키 및 URL (교차로)

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

당신이 대답하는 방법입니다.

쿠키의 경우 = 는 일반적으로 쿠키 값을 설정하는 데 사용되므로 제거되었습니다.

URL의 경우 =가 유지되었습니다. 교차로는 분명히 없다.

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

특히 쿠키가 마지막 문자를 발견하면 큰 따옴표로 묶인 Java 쿠키 환경에서 이스케이프가 여전히 발생하고 예기치 않은 상황이 발생합니다.

안전을 위해 A-Za-z1-9를 사용하십시오. 그게 내가 할 일입니다.


Safari Cookies는 문제가있는 유일한 브라우저였습니다. 다른 모든 브라우저는 제대로 작동했습니다. 등호 = 공백 및 공백을 처리하려면 쿠키를 UrlEncode 및 UrlDecode해야했습니다. 쿠키의 Base64Encode와 같습니다. (Safari는이 브라우저 만 필요했습니다. 인코딩 된 쿠키를 사용하거나 사용하지 않고
Sql Surfer

답변으로 이어지는 출처를 나열하는 것이 좋습니다!
Loc

1
@Loc 3 시간 이상의 시험 및 검사.
mmm

10

2011 년 4 월에 발표 된 최신 rfc6265 :

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

";"을 넣을 수 없습니다 쿠키의 값 필드에서 설정 될 이름은 ";"까지의 문자열입니다. 대부분의 브라우저에서 ...


1

쿠키 사양에는 두 가지 버전이 있습니다
. 버전 0 쿠키 일명 Netscape 쿠키,
2. 버전 1 일명 RFC 2965 쿠키
버전 0 인 쿠키 의 이름과 값 부분은 세미콜론, 쉼표, 등호 및 공백을 제외한 일련의 문자입니다. 큰 따옴표와 함께 사용하지 않으면
버전 1이 훨씬 더 복잡합니다. 여기
에서 확인할 수 있습니다 .이 버전에서 이름 값 부분에 대한 사양은 이름이 $ 기호로 시작할 수 없다는 점을 제외하면 거의 동일합니다.


버전 0에서 값이 등호를 제외해야한다는 것은 어디에 있습니까?
길리

1

IE와 Edge에는 또 다른 흥미로운 문제가 있습니다. 마침표가 둘 이상인 쿠키는 자동으로 삭제 된 것으로 보입니다. 그래서 이것은 작동합니다 :

cookie_name_a = 값 a

이 동안 떨어질 것입니다

cookie.name.a = valuea


브라우저 동작이 쿠키와 일치하지 않으므로 복제하기 위해 정확한 브라우저 버전을 추가하면 좋을 것입니다.
Gerald

0

간단합니다 :

<쿠키 이름>은 제어 문자 (CTL), 공백 또는 탭을 제외한 모든 US-ASCII 문자 일 수 있습니다. 또한 다음과 같은 구분 기호 문자를 포함해서는 안됩니다. () <> @,; : \ "/ []? = {}.

<cookie-value>는 큰 따옴표로 선택적으로 설정할 수 있으며 CTL, 공백, 큰 따옴표, 쉼표, 세미콜론 및 백 슬래시를 제외한 모든 US-ASCII 문자가 허용됩니다. 인코딩 : 많은 구현은 쿠키 값에 대해 URL 인코딩을 수행하지만 RFC 사양에 따라 필요하지는 않습니다. 허용되는 문자에 대한 요구 사항을 충족시키는 데 도움이됩니다.

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


0

한 가지 더 고려하십시오. 최근에 PHP 스크립트에 게시 된 일부 민감한 데이터를 암호화 된 쿠키로 변환하고 반환하는 데 필요한 스키마를 구현했습니다.이 쿠키는 '안전한'것으로 보장 된 모든 base64 값을 사용했습니다. 따라서 RC4를 사용하여 데이터 항목을 정식으로 암호화했습니다. base64_encode를 통한 출력과 쿠키를 사이트에 행복하게 반환했습니다. base64로 인코딩 된 문자열에 "+"기호가 포함될 때까지 테스트가 잘 진행되는 것 같았습니다. 문자열은 아무 문제없이 페이지 쿠키에 기록되었습니다. 쿠키가 변경되지 않은 상태로 작성되었는지 확인한 다음 내 PHP라는 후속 페이지에서 $ _COOKIE 배열을 통해 쿠키를 얻었을 때 문자열에 "+"기호가없는 것을 발견했습니다. ASCII 공간.

쿠키를 사용하여 임의의 데이터를 "안전하게"저장하기 위해 base64를 사용하는 것에 대한 수많은 참고 자료를 제시 한 이후로이 시나리오에 대해 읽은 유사한 해결되지 않은 불만이 얼마나 많은지를 고려할 때 문제를 지적하고 인정할만한 해결책을 제시 할 것이라고 생각했습니다.

데이터 조각에 대해 암호화를 수행 한 다음 base64_encode를 사용하여 "쿠키 안전"으로 설정 한 후이를 통해 출력 문자열을 실행하십시오.

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

여기에서는 쿠키로 사용하기 위해 인코딩 된 값을 페이지에 반환하기 전에 "+"를 다른 "쿠키 안전"문자로 대체하고 있습니다. 처리되는 문자열의 길이는 변경되지 않습니다. 동일한 (또는 사이트의 다른 페이지)가 내 PHP 스크립트를 다시 실행하면 문자가 누락되지 않고이 쿠키를 복구 할 수 있습니다. 쿠키를 내가 만든 것과 동일한 fix64 () 호출을 통해 다시 전달해야한다는 것을 기억해야하며 거기에서 일반적인 base64_decode ()로 해독하고 스키마의 다른 암호 해독을 수행 할 수 있습니다.

쿠키에 사용 된 base64 문자열을 손상없이 PHP로 다시 전송할 수 있도록 PHP에서 설정할 수있는 설정이있을 수 있습니다. 그 동안 이것은 작동합니다. "+"는 "법적"쿠키 값일 수 있지만 이러한 문자열을 PHP로 다시 전송하려면 ($ _COOKIE 배열을 통해) PHP로 다시 전송하려는 경우 다시 처리하여 제거하는 것이 좋습니다. 문제가있는 문자를 복구하고 복구 후 복원하십시오. 선택할 수있는 다른 "쿠키 안전"문자가 많이 있습니다.


0

나중에 변수를 사용하는 경우 path실제로 악센트 문자를 사용할 수 있지만 실제로 브라우저 경로와 일치하지는 않습니다. 이를 위해서는 URIEncode해야합니다. 그래서 이렇게 :

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

따라서 "허용 된"문자는 사양에 포함 된 것 이상일 수 있습니다. 그러나 사양 내에서 유지하고 URI 인코딩 문자열을 사용하여 안전해야합니다.


-1

몇 년 전 MSIE 5 또는 5.5 (그리고 아마도 둘 다)는 HTML 블록에서 "-"와 관련하여 심각한 문제를 겪었습니다. 쿠키와 MD5 해시 (문자 및 숫자 만 포함)를 저장하여 서버 측 데이터베이스의 다른 모든 항목을 조회 한 이후로 직접 ​​연관되어 있지는 않습니다.


-2

나는 사용했다

cookie_value = encodeURIComponent(my_string);

my_string = decodeURIComponent(cookie_value);

그것은 모든 종류의 캐릭터에 효과적입니다. 세미콜론이나 쉼표가 아닌 문자에서도 이상한 문제가 발생했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.