Edgewall Software
Modify

Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#13000 closed defect (cantfix)

Other cookies with special characters prevent login/form submission

Reported by: Jorrit Schippers <jorrit@…> Owned by:
Priority: normal Milestone:
Component: general Version: 1.2
Severity: normal Keywords:
Cc: Branch:
Release Notes:
API Changes:
Internal Changes:

Description

I host trac on trac.domain.com. Some SEO tool on www.domain.com created a cookie on .domain.com with JSON content. This conflicts with the cookies read by Trac (1.2.2 on Linux) for CSRF purposes.

For example:

When a cookie with key test and value {"test": "test"} is present, logging in is no longer possible and the CSRF consistently fails.

The HTTP request contains the following Cookie header:

Cookie: test={"test": "test"}; trac_form_token=0357f2daf3e464472961449e

As long as the test cookie is after the trac_form_token there is no problem, but when it is before trac_form_token CSRF always fails.

I guess the cookie parsing code has trouble dealing with quotes.

Attachments (0)

Change History (8)

comment:1 by Jun Omae, 6 years ago

Trac uses Cookie module. It seems json string cannot lead the issue.

>>> from Cookie import SimpleCookie
>>> cookies = SimpleCookie()
>>> cookies.load('test={"test": "test"}; trac_form_token=0357f2daf3e464472961449e')
>>> cookies['trac_form_token'].value
'0357f2daf3e464472961449e'               # ok
>>> cookies['test'].value
'{'                                      # broken due to invalid cookie

Please post cookie string which leads the issue and trac.log.

Also, the Cookie module formerly strictly applied the parsing rules described in the RFC 2109 and RFC 2068 specifications. However, the JSON string violates RFC 2109.

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

   token           =       1*<any CHAR except CTLs or tspecials>
   quoted-string   =       ( <"> *(qdtext) <"> )
   qdtext          =       <any TEXT except <">>

I don't think we can resolve your issue.

Last edited 6 years ago by Jun Omae (previous) (diff)

comment:2 by Jorrit Schippers <jorrit@…>, 6 years ago

Thanks for your quick and extensive reply, I appreciate it a lot.

My /usr/lib/python2.7/Cookie.py has this version header:

Id: Cookie.py,v 2.29 2000/08/23 05:28:49 timo Exp

Your code leads to a different result for me:

>>> cookies['trac_form_token'].value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'trac_form_token'

What's your version? Do you have any idea how to update it?

comment:3 by Jun Omae, 6 years ago

The same results using Python 2.4 - 2.7:

$ for i in /usr/bin/python2.[4567]; do $i -c 'import sys
from Cookie import SimpleCookie
c = SimpleCookie()
c.load("""test={"test": "test"}; trac_form_token=0357f2daf3e464472961449e""")
print(c.keys(), c["trac_form_token"].value, sys.version_info[:3])'; done
(['test', 'trac_form_token'], '0357f2daf3e464472961449e', (2, 4, 6))
(['test', 'trac_form_token'], '0357f2daf3e464472961449e', (2, 5, 6))
(['test', 'trac_form_token'], '0357f2daf3e464472961449e', (2, 6, 9))
(['test', 'trac_form_token'], '0357f2daf3e464472961449e', (2, 7, 6))

comment:4 by Jun Omae, 6 years ago

The Id header is no longer updated. Instead, please post Python version.

$ grep 'Id: ' /usr/lib/python2.?/Cookie.py
/usr/lib/python2.4/Cookie.py:# Id: Cookie.py,v 2.29 2000/08/23 05:28:49 timo Exp
/usr/lib/python2.5/Cookie.py:# Id: Cookie.py,v 2.29 2000/08/23 05:28:49 timo Exp
/usr/lib/python2.6/Cookie.py:# Id: Cookie.py,v 2.29 2000/08/23 05:28:49 timo Exp
/usr/lib/python2.7/Cookie.py:# Id: Cookie.py,v 2.29 2000/08/23 05:28:49 timo Exp

comment:5 by Jun Omae, 6 years ago

Using Cookie.py in Python 2.7.8:

$ python2.7 -c '
import sys
from Cookie import SimpleCookie
c = SimpleCookie(); c.load("""test={"test": "test"}; trac_form_token=0357f2daf3e464472961449e""")
print(c.keys())'
['test', 'trac_form_token']

Using Cookie.py in Python 2.7.9:

$ python2.7 -c '
import sys
from Cookie import SimpleCookie
c = SimpleCookie(); c.load("""test={"test": "test"}; trac_form_token=0357f2daf3e464472961449e""")
print(c.keys())'
[]

Cookies which has non-standard cookie value cannot be loaded since Python 2.7.9.

comment:6 by Jorrit Schippers <jorrit@…>, 6 years ago

Python 2.7

root@server2:/usr/lib/python2.7# dpkg -S Cookie.py
libpython2.7-stdlib:amd64: /usr/lib/python2.7/Cookie.py
root@server2:/usr/lib/python2.7# dpkg -s libpython2.7-stdlib | grep Version
Version: 2.7.12-1ubuntu0~16.04.3

It's probably this changelog entry:

- Lax cookie parsing in http.cookies could be a security issue when combined
  with non-standard cookie handling in some Web browsers.  Reported by
  Sergey Bobrov.

https://hg.python.org/cpython/raw-file/v2.7.9/Misc/NEWS

The problem is that Firefox and Chrome have no issue with setting illegal cookie values using document.cookie = '' and I have no control over them. Annoying.

in reply to:  6 comment:7 by Jun Omae, 6 years ago

Resolution: cantfix
Status: newclosed

Replying to Jorrit Schippers <jorrit@…>:

The problem is that Firefox and Chrome have no issue with setting illegal cookie values using document.cookie = '' and I have no control over them. Annoying.

Set-Cookie: test={.... json string...} should be used for testing. The document.cookie = ... doesn't lead parsing the cookie string.

We cannot fix the issue. The SEO tool should be fixed, otherwise try workaround to remove invalid cookie strings by mod_headers, etc.

Last edited 6 years ago by Jun Omae (previous) (diff)

comment:8 by Jorrit Schippers <jorrit@…>, 6 years ago

You're right, thanks for your time.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The ticket will remain with no owner.
The resolution will be deleted. Next status will be 'reopened'.
to The owner will be changed from (none) to the specified user.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.