CWE-157 covers products that do not properly handle the characters that start and end a group, such as parentheses, brackets, braces, angle brackets and quotes. The pair is a promise: whatever opens will close. Attackers send input that breaks the promise.
Parsers for queries, mail, markup and protocols are the usual targets. If your code looks for a closing character and trusts that it exists, read on.
How it happens
Code finds an opener, then searches for the matching closer, then uses the position it found.
# Vulnerable: find returns -1 when the closing quote is missing
start = text.index('"') + 1
end = text.find('"', start)
value = text[start:end] # with end == -1 this silently drops the last character
The bug is not always a crash. A missing closer can make a length calculation wrong, and in lower level languages that becomes a memory error.
Observed examples show each outcome. CVE-2004-0956 is a crash from a missing paired delimiter, an open double quote with no closing one. CVE-2000-1165 is a crash from a message without a closing angle bracket. CVE-2005-2933 is a buffer overflow from a mailbox name with an opening double quote and no closing one, causing a larger copy than expected.
What an attacker gains
MITRE lists integrity impact as unexpected state. The examples add denial of service by crash and, in the overflow case, memory corruption.
How to find it
No detection methods are listed, so test and review.
- Send every opener without its closer, closers without openers, and wrongly ordered or nested pairs.
- Read each parser for code that assumes a closer exists. Check every search that can return not found.
- Fuzz protocol fields with truncated input.
How to fix it
- Treat a missing closer as invalid input. Reject it with an error instead of guessing where the value ends.
start = text.index('"') + 1
end = text.find('"', start)
if end == -1:
raise ValueError("unterminated quoted value")
value = text[start:end]
- Anticipate that delimiters will be injected, removed or manipulated.
- Use an allowlist for acceptable input and reject what does not conform.
- Base any copy length on the data you verified, not on an assumption about the shape of the input.
Quick check
Is an unbalanced quote only a crash risk?
No. CVE-2005-2933 turned a missing closing quote into a buffer overflow because the copy was larger than expected.