Opened 8 months ago

Closed 7 months ago

#2144 closed defect (wontfix)

$cookie_name variable inconsistent cookie-pair splitting

Reported by: auseviciusdev@… Owned by:
Priority: minor Milestone:
Component: nginx-core Version: 1.19.x
Keywords: cookie Cc: auseviciusdev@…
uname -a: Linux 6637fda45745 4.15.0-133-generic #137~16.04.1-Ubuntu SMP Fri Jan 15 02:55:18 UTC 2021 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.19.7
built by gcc 8.3.0 (Debian 8.3.0-6)
built with OpenSSL 1.1.1d 10 Sep 2019
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.19.7/debian/debuild-base/nginx-1.19.7=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

Description

$cookie_name variable cookie pair splitting is inconsistent and looks to be not complying to rfc6265

According to https://tools.ietf.org/html/rfc6265#section-4.2.1 cookie pairs are split by ';' followed with space.

   cookie-header = "Cookie:" OWS cookie-string OWS
   cookie-string = cookie-pair *( ";" SP cookie-pair )

I found that Nginx is splitting on ';' and ',' (only unique cookie names?) with optional spaces.

I have the following block:

location / {
  return 200 $cookie_PHPSESSID\n;
}

Test cases:

root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: PHPSESSID=one; PHPSESSID=two"
one
root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: PHPSESSID=one;PHPSESSID=two"
one
root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: PHPSESSID=one PHPSESSID=two"
one PHPSESSID=two
root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: PHPSESSID=one, PHPSESSID=two"
one, PHPSESSID=two
root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: PHPSESSID=one,PHPSESSID=two"
one,PHPSESSID=two
root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: ID=one, PHPSESSID=two"
two
root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: ID=one PHPSESSID=two"

root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: PHPSESSID = one; PHPSESSID=two"
one
root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: PHPSESSID = one PHPSESSID=two"
one PHPSESSID=two
root@6637fda45745:/etc/nginx/conf.d# curl localhost -H "Cookie: PHPSESSID = one, PHPSESSID=two"
one, PHPSESSID=two

Other syntax error is allowing spaces between cookie-name and cookie-value (not allowed in https://tools.ietf.org/html/rfc6265#section-4.1.1).
I'm wondering why is this done like this, or is there a document that follows this syntax?

Thank you

Change History (2)

comment:1 by Maxim Dounin, 8 months ago

To parse cookies for the $cookie_* variables nginx uses permissive syntax from RFC 2109 and RFC 2965, which permits list values in the Cookie header to be separated by either ; (as historically used by the Cookie header) or ',' (as normally used by lists in HTTP, and required as an alternative separator by RFC 2109/2965):

   The syntax for the header is:

   cookie          =       "Cookie:" cookie-version
                           1*((";" | ",") cookie-value)
   cookie-value    =       NAME "=" VALUE [";" path] [";" domain]
   cookie-version  =       "$Version" "=" value
   NAME            =       attr
   VALUE           =       value
   path            =       "$Path" "=" value
   domain          =       "$Domain" "=" value

   ...

   Note: For backward compatibility, the separator in the Cookie header
   is semi-colon (;) everywhere.  A server should also accept comma (,)
   as the separator between cookie-values for future compatibility.

The same applies to spaces, which aren't used to be explicitly specified by grammars, but rather assumed implicitly:

   ... White space is permitted between tokens. ...

Switching to strict parsing per RFC 6265 grammar is possible, but unlikely unless there are practical reasons to do so. Especially given that RFC 6265 itself uses permissive approach in example algorithms it provides.

   NOTE: The algorithm below is more permissive than the grammar in
   Section 4.1.  For example, the algorithm strips leading and trailing
   whitespace from the cookie name and value (but maintains internal
   whitespace), whereas the grammar in Section 4.1 forbids whitespace in
   these positions.  User agents use this algorithm so as to
   interoperate with servers that do not follow the recommendations in
   Section 4.

If you think there are practical reasons to change the parsing, please elaborate.

comment:2 by Maxim Dounin, 7 months ago

Resolution: wontfix
Status: newclosed

Feedback timeout.

Note: See TracTickets for help on using tickets.