Slowing down with sudo or (The importance of accurately mapping vulnerabilities to weaknesses)
A recent vulnerability in sudo, CVE-2021–3156, allows unauthenticated users to execute programs as root on Linux and Mac. When initially submitted, the CVE description mentioned a heap overflow (CWE-122) leading to a privilege escalation, but this was not the root cause. Looking deeper into some of the finer details in the CVE’s references, it was determined that the vulnerability occurs due to CWE-193 — an off-by-one error. This occurs when one uses the program sudo with a specific flag and only ends an argument with one backslash <\> instead of two. As a result, the program skips over the null terminator and then points to memory past the end of the string.
Importance of CWE mappings
The CVE results in a heap overflow, but this is caused by an off-by-one error. So which CWE mapping is correct? You might ask, why does it matter? A vulnerability is a vulnerability, and neither mapping is technically incorrect. Identifying the true underlying weakness matters for precise understanding, though, if we truly want to prevent similar vulnerabilities in the future.
In this case, it is important to understand as heap overflows can be caused by multiple different mistakes. In the case of CVE-2021–3156, there is a chain from CWE-193 to CWE-122. If the developer implemented some control to prevent the heap overflow, the program would still access memory it should not and crash. As luck would have it, it is interesting to note that an off-by-one (actually, off-by-five) occurred in sudo before. CVE-2002–0184 reported that sudo contained a heap-based buffer overflow instead of an off-by-one error. While this CVE’s description was originally published almost 20 years ago, it is now getting updated accordingly. In this case, the vulnerability occurred when parsing the command line.
If the correct underlying weakness was identified as an off-by-one (five) error and understood back then, would we have seen the new CVE at all?
How to prevent similar errors in the future
Knowing that an off-by-one error is the true root cause for CVE-2021–3156, what should developers do to prevent this from occurring again?
First, developers should consider looking where they have null-terminated strings and make sure they are not incrementing past them. Programmers should consider writing additional test cases for it. Some static code analysis tools are good at identifying these kinds of weaknesses. Second, developers could consider alternatives to null terminated strings. These include the standard string libraries like std::string, CString, CFString, and NSString. When using these implementations, the parsing would be handled by the framework, likely preventing this weakness in the first place.
Finally, this brings up the old but true concept: If you are building something new, where possible, use a memory safe language like Java, Go, or Rust.