Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-123067: Denial of Service Vulnerability in http.cookies._unquote() #123066

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 14 additions & 36 deletions Lib/http/cookies.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,51 +184,29 @@ def _quote(str):
return '"' + str.translate(_Translator) + '"'


_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]")
_QuotePatt = re.compile(r"[\\].")
_OctalPatt = re.compile(r"\\([0-3][0-7][0-7])")
_QuotePatt = re.compile(r'\\"')

def _unquote(str):
# If there aren't any doublequotes,
# then there can't be any special characters. See RFC 2109.
if str is None or len(str) < 2:
return str
if str[0] != '"' or str[-1] != '"':
return str

# We have to assume that we must decode this string.
# Down to work.

# Remove the "s
# Remove the surrounding quotes
str = str[1:-1]

# Check for special sequences. Examples:
# \012 --> \n
# \" --> "
#
i = 0
n = len(str)
res = []
while 0 <= i < n:
o_match = _OctalPatt.search(str, i)
q_match = _QuotePatt.search(str, i)
if not o_match and not q_match: # Neither matched
res.append(str[i:])
break
# else:
j = k = -1
if o_match:
j = o_match.start(0)
if q_match:
k = q_match.start(0)
if q_match and (not o_match or k < j): # QuotePatt matched
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to be removing all backslashes from the cookie, where the new behavior is only removing backslashes in front of quotes. Is that what we're expecting to change with this PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From reading the RFC, I think we should preserve the original behavior of unquoting all single-character preceded by a backslash. If you agree, can we add a test case that ensures this behavior is preserved.

res.append(str[i:k])
res.append(str[k+1])
i = k + 2
else: # OctalPatt matched
res.append(str[i:j])
res.append(chr(int(str[j+1:j+4], 8)))
i = j + 4
return _nulljoin(res)
# Function to replace octal patterns
def replace_octal(match):
octal_value = match.group(1)
return chr(int(octal_value, 8))

# Replace octal escape sequences
str = _OctalPatt.sub(replace_octal, str)
# Replace escaped quotes
str = _QuotePatt.sub('"', str)

return str

# The _getdate() routine is used to set the expiration time in the cookie's HTTP
# header. By default, _getdate() returns the current time in the appropriate
Expand Down
Loading