The SANS/CWE Top 25 dangerous software errors of 2021
Since we last looked at it in 2019, the SANS/CWE Top 25 list has been updated twice. Let’s see what this year’s SANS Top 25 tells us about the state of software security in 2021 and how it relates to the latest OWASP Top 10.
Your Information will be kept private.
Your Information will be kept private.
Differences between the SANS Top 25 and OWASP Top 10
While they both serve as a reference point for software security and are partly based on the same source data, the SANS/MITRE CWE Top 25 and the OWASP Top 10 differ in scope and purpose. The OWASP list groups the most prevalent web application security weaknesses into ten categories corresponding to broader cybersecurity concerns. With each subsequent edition, the categories have been moving away from specific vulnerabilities or even common vulnerability classes and towards a more strategic view – see our post on the 2021 OWASP Top 10 to learn what this means in practice.
The SANS/CWE Top 25 lists the most prevalent issues from the Common Weakness Enumeration (CWE). In a way, CWE takes the opposite approach to the OWASP list, focusing on specific weaknesses rather than more abstract classifications. This makes the list more directly useful for developers and security engineers, as each item relates to concrete implementation flaws that can be found and addressed. Interestingly, although the SANS/CWE Top 25 applies to all types of software while the OWASP list is limited to web applications, with each edition there is more and more common ground between web and non-web software security.
Weaknesses vs. vulnerabilities: Both the SANS Top 25 and the OWASP Top 10 deal solely with CWEs, i.e. security weaknesses that commonly occur during software development. These are different from CVEs, which are confirmed security vulnerabilities in specific products. In simple terms, exploitable weaknesses reported in production become vulnerabilities.
Common themes in software security weaknesses in 2021
The SANS Top 25 list is based on the prevalence of specific weaknesses in real-life vulnerabilities taken from the NIST NVD. Each CWE that has led to a vulnerability gets a score that reflects its frequency and severity (see here for the actual formula), and this score determines its position on the list. A dry technical list doesn’t seem particularly useful or exciting, but if you read closely, the CWE codes, scores, and trends tell the story of modern software development and security – a tale of trust, deceit, and demons of the past, all set firmly in the cloud. Let’s look at the four common themes running through the Top 25.
Web application security is everywhere
If you came to the SANS TOP 25 CWEs from the OWASP Top 10, you’d be forgiven for having a sense of deja vu, as eight of the top 25 weaknesses are either web-specific or most commonly found in web applications. It’s no secret that as software development moves to the web, so does application security. Here are the four web-specific weaknesses on the list, along with their official names and overall positions:
- #2: Cross-site scripting (XSS), officially Improper Neutralization of Input During Web Page Generation [CWE-79]
- #9: Cross-site request forgery (CSRF) [CWE-352]
- #23: XXE injection, officially Improper Restriction of XML External Entity Reference [CWE-611]
- #24: Server-side request forgery (SSRF) [CWE-918]
Apart from these, several other weaknesses in the list usually occur in web security contexts, notably SQL injection, OS command injection, and path traversal (a.k.a. directory traversal). While these can apply to other types of software, they are easiest to exploit in web applications. Again, the position reflects the frequency and severity of vulnerabilities linked to a specific weakness, so having XSS way up at #2 means there is a lot of cross-site scripting going on.
Memory management issues never go away
On the one hand, we see that all the cloudy headlines are true – software development is increasingly web development, and software security is increasingly web application security. However, the #1 weakness (along with five relatives) serves as a stark reminder that a lot of critical software relies on lower-level programming languages that need careful memory management. The top software security weakness of 2021 is essentially buffer overflow, though this specific term is considered too general for CWE. Here are the weaknesses related to low-level memory operations:
- #1: Out-of-bounds write (code can write to memory that shouldn’t be accessible) [CWE-787]
- #3: Out-of-bounds read (code can read memory that shouldn’t be accessible) [CWE-125]
- #7: Use after free (code uses a variable that shouldn’t be used anymore) [CWE-416]
- #12: Integer overflow or wraparound (mismanagement of large numeric values) [CWE-190]
- #15: NULL pointer dereference (code attempts to access a non-existent value) [CWE-476]
- #17: Improper restriction of operations within the bounds of a memory buffer (code can operate on memory that shouldn’t be accessible) [CWE-119]
None of these weaknesses can occur in a higher-level language such as Java or Python, not to mention web languages such as PHP or JavaScript. And yet they appear in the top 25 year after year, proving that the cloud-first world sits on a foundation of C/C++ code that runs our operating systems, servers, network devices, embedded systems, industrial installations… A sobering thought, considering that this is where you are likely to find the most dangerous programming errors.
Trust no one with your inputs
The other overarching theme of this software security tale is trust. It is difficult enough to write software that works correctly with the expected data and users. When every user could be malicious and every input could be an attack attempt, writing even the simplest piece of code is like walking through a minefield. How can you do anything when everyone is suspicious? How can you check every piece of data? And yet this is the reality of application security, as shown by over a quarter of the top 25 being weaknesses related to blindly trusting your inputs:
- #4: Improper input validation [CWE-20]
- #5: OS command injection, officially Improper Neutralization of Special Elements used in an OS Command [CWE-78]
- #6: SQL injection, officially Improper Neutralization of Special Elements used in an SQL Command [CWE-89]
- #8: Path traversal/directory traversal, officially Improper Limitation of a Pathname to a Restricted Directory [CWE-22]
- #10: Unrestricted upload of file with dangerous type [CWE-434]
- #13: Loading saved data without checking, officially Deserialization of Untrusted Data [CWE-502]
- #25: Code injection, officially Improper Neutralization of Special Elements used in a Command [CWE-77]
In all these cases, failure to sanitize user-controlled inputs can have devastating consequences, from software crashes to information exposure or code execution. And as mentioned earlier, many of these are typically found in web application security, where user-controlled inputs make up most of the data your application uses.
Trust no one with access
The threat landscape is easily the biggest change across the history of software security. With threat actors now active at every stage of the application lifecycle, access control should be an integral part of software and data design – except that it’s not. All the remaining weaknesses from the Top 25 are related to implicit trust or failures to protect sensitive data at all times, showing that, all too often, security is still an afterthought during development:
- #11: Missing authentication for critical function [CWE-306]
- #14: Improper authentication [CWE-287]
- #16: Use of hard-coded credentials [CWE-798]
- #18: Missing authorization [CWE-862]
- #19: Incorrect default permissions [CWE-276]
- #20: Exposure of sensitive information to an unauthorized actor [CWE-200]
- #21: Insufficiently protected credentials [CWE-522]
- #22: Incorrect permission assignment for critical resource [CWE-732]
The importance of such trust-related issues is also reflected in the OWASP Top 10, where the top categories are now Broken Access Control and Cryptographic Failures. Ensuring application security means encrypting sensitive data (or all data, in many cases) at rest and in transit using secure algorithms while also thinking of authentication and authorization when designing user roles and function access.
To be effective, security must come first
With over half of the SANS Top 25 security weaknesses being related to trust and access control, it’s no coincidence that CISA is calling for organizations to implement zero trust principles in their systems. What’s more, the three fastest risers on the list since 2020 are all trust-related: Incorrect Default Permissions, Missing Authentication for Critical Function, and Deserialization of Untrusted Data. And remember that the list is based on prevalence in real-life vulnerabilities, so these weaknesses are out there and growing in frequency or severity (or both).
There are no shortcuts to avoiding software vulnerabilities, only hard work to build a security-first mindset and embed security into every stage of the software development lifecycle (SDLC). Vulnerability testing, mitigation, and remediation all need to be a routine part of the development workflow, built on a solid foundation of education and security awareness.
Organizations can no longer afford to compromise on security or accept security risks as the price of rapid development and growth. When anything can be a target and anyone can be an attacker, security must come first.