There are a number of places online where you can find details about application security vulnerabilities, but it is surprisingly hard to find a single location that provides a summary of all the most important vulnerabilities to be aware of.
While any high-risk vulnerability is worth fixing, It’s worth adding a layer of prioritization around the most common vulnerabilities that are being used in attacks and exploits.
The following statistics were reported by Contrast Security. While this is based primarily on what they are seeing with their customers, I think it is generally useful:
- 65% of applications were targeted by SQLi attacks, 62% by broken access control attacks, and 54% by XSS attacks.
- The most common serious vulnerabilities found in applications are: XSS at 15%, Broken Access Control at 13%, SQLi at 6%.
- Command injection attacks are relatively rare but are increasing rapidly (179% between 2019 and 2020). Keep in mind that most applications are targeted by more than one type of attack, so the percentages above are overlapping.
There were a couple of additional valuable nuggets of information that I think are worth considering:
- Vulnerabilities not remediated in 30 days tend to persist and add to security debt.
- SQLi mean time to fix is 10 days, while sensitive data exposure and broken AuthN are over 90 days.
If you are postponing your security fixes, you most likely will never make it back to them and they will instead contribute to your security debt. It’s important to be conscious about that decision - would you still postpone, if you knew that meant the fix would never come?
It’s interesting to note that difference in meant time to fix for SQLi (and I think XSS would fit here, too) versus broken authentication or sensitive data exposure. Most XSS and SQLi are line-level coding problems that can be fixed relatively cleanly. Sensitive data exposure and broken authentication, however, are more likely to be design decisions and fixes are much harder and more disruptive to implement.
With that said, let’s dive into the vulnerability summaries. This is the bare minimum of what you should be aware of as a developer, or as a security professional. For each, you will find a brief description as well as a summary of mitigation techniques. Each of the vulnerability names below is linked to a site with more in-depth information. If you have any questions on any of these, let me know in comments on HackerNews.
Vulnerabilities (alphabetical order)
- Attacker takes over the account of a victim. There could be a variety of entry points, but the result is the attacker now owns the credentials and the victim does not.
- Make sure password change page is protected from CSRF and that it requires the old password to validate the user
- Require user to enter pwd when changing their email address
- Review for XSS and CSRF vulnerabilities that can subvert these functions (e.g. CSRF that allows mail forwarding to be set up on a victim’s email account).
- Attacker gains access to administrative interface.
- Require unique credentials to log into the interface.
- Limit access by source IP.
- Put interface into its own subdomain with its own user management.
- This vulnerability covers a lot of ground - basically any way in which an attacker can subvert the authorization logic to gain access to an asset they should not.
- Think through an application’s access control requirements and capture it in a web application security policy - use an access control matrix to define the access control rules.
- The policy should document what types of users can access the system, and what functions and content each of these types of users should be allowed to access.
- The access control mechanism should be extensively tested to be sure that there is no way to bypass it. This testing requires a variety of accounts and extensive attempts to access unauthorized content or functions.
- Protect by centralizing access control code mechanisms, using standard framework mechanisms when possible, creating simple idioms for developers to follow, and deploying continuous testing to assure that access controls are in place and effective.
- Enforce server-side checks, not on the client.
- Deny by default.
- Log access control failures, alert on repeated failures.
- Attacker repeatedly attempts to guess credentials in the hopes of getting one that works. This is generally not a totally random approach, but instead is done by some combination of common passwords and/or side-channel information to reduce the search space.
- Be careful with error messages to not give away when a username is correct.
- Limit number of attempts allowed.
- Require strong passwords.
- Require multi-factor authentication.
- This is possible when an application passes unsafe user supplied data (forms, cookies, HTTP headers, etc.) to a system shell where it may be interpreted as a command.
- Whitelist validation.
- Use safe APIs.
- This is a variation on command injection where an application passes user input to a command line interface.
- Use system(command, parameters) to separate parameters from the command itself.
- Large numbers of stolen credentials are automatically entered into websites until they are potentially matched to an existing account which the attacker can then hijack for their own purposes.
- Multi-Factor Authentication.
- Security Questions or Pin.
- Request Fingerprinting.
- Force less predictable usernames (e.g. not email address).
- Warn users when passwords are leaked/breached (e.g. Apple and Google do this).
- Notify users of strange logins.
- Persistent - the attack is persisted in the data store to effect other users.
- Reflected - the attack is immediately executed in the context of a single user.
- DOM - the attack is used in the construction of a dynamic document object model.
- XSS source examples: HTTP request parameters, user controlled data in persistent stores, JSON data (stringify blind rendering).
- XSS sink examples: HTTP response in HTML, DOM innerHTML.
- Encode untrustworthy data, according to context, immediately before echoing back to the page.
- Encode untrustworthy data before use in DOM.
- Use CSP to restrict from where scripts can run
- Use HTTPOnly so that cookies cannot be accessed by script
- Use inherently safe APIs: wrap injection prone APIs with ones that protect against XSS. Some platforms (e.g. React) have this build into the platform.
- Coding guidelines: specify which APIs to use and when further review is necessary.
- Occurs when a maliciously crafted link is used to issue commands to a web application/service to which the user has already authenticated.
- Can be partially mitigated by using POST for actions that change the state of resources/data instead of GET.
- You must also use an unguessable token and require that in the request. Token is only known by the application/domain so if link is coming from outside, they will not have it and the request will fail. Keep in mind that XSS can be used to steal the token and create a chained attack.
Only allow input into a property value and nowhere else.
CSS encode before adding the input to the CSS.
- Occurs when Malformed data or unexpected data could be used to abuse application logic, deny service, or execute arbitrary code when the data is deserialized by the application.
- Examples of where deserialization could cause a problem:
- Remote- and inter-process communication (RPC/IPC).
- Wire protocols, web services, message brokers.
- Databases, cache servers, file systems.
- HTTP cookies, HTML form parameters, API authentication token.
- Don’t accept untrusted serialized data.
- Use digital signatures to check integrity/authenticity.
- Enforce type constraints on deserialization.
- Happens when attacker controlled data enters an EL interpreter.
- Avoid putting user data into an expression interpreter if possible. Otherwise, validate and/or encode the data to ensure it is not evaluated as expression language. Use framework protections if they exist.
- Difficult to protect from, best step is to keep frameworks up to date and continuously monitor.
- Occurs when a user can modify file name or path of a file being uploaded. Can be used to replace an important existing file, or create a file that will then be deserialized by the application. Or in some cases the uploaded file can contain a payload that is part of an attack chain.
- File download attacks are similar to above but could allow an attacker access to files they shouldn’t have. Mitigation is the same (permissions and file validation).
- Use permissions to restrict what directories the web application can write into.
- Use a whitelist approach to validate filenames.
- Synchronous file upload architecture can also be attacked to perform a DoS attack, so perform file uploads asynchronously instead.
- HTTP headers should be untrustworthy data. Header injection occurs when this data is echoed back to the page and could be interpreted as script.
- Encode HTTP headers.
- Relied upon inconsistency between the interpretation of Content-length and/or Transfer-encoding headers between front-end and back-end servers. This is a growing problem in large-scale cloud-based applications behind load balancers and/or CDNs.
- This can be used for malicious redirect for users or to redirect a restful api call.
- Variant 1: The front end processes the request using Content-Length header while backend processes the request using Transfer-Encoding header
- Variant 2: The front end processes request using Transfer-Encoding header while backend processes the request using Content-Length header
- HTTP/2 should be used for backend connections.
- Use web servers accepting the same type of HTTP headers.
- LDAP Injection is an attack used to exploit web based applications that construct LDAP statements based on user input. When an application fails to properly sanitize user input, it’s possible to modify LDAP statements through techniques similar to SQLi.
- LDAP injection attacks could result in the granting of permissions to unauthorized queries, and content modification inside the LDAP tree.
- Encode all variables using LDAP encoding.
- Use a safe framework like LINQ.
- Use least privilege and whitelist validation as backup protections.
- Developers may log sensitive information that could then be recovered by an attacker to either steal that information or as leverage for additional attacks.
- Carefully reviews logs and logging functionality to ensure secrets and sensitive information aren’t logged in cleartext.
- Failure to configure permissions/users on server or cloud service.
- Unnecessary features/ports/attack surface.
- Overly verbose error massages or logging.
- Failure to configure security features/settings.
- Failure to use latest most secure/patched versions of components and libraries.
- Have a consistent/repeatable hardening process.
- Configure test/dev/prod identically.
- Remove features/frameworks not used.
- Ensure latest patches installed.
- Segment network to reduce blast radius.
- Use HTTP security headers: Strict-Transport-Security (force HTTPS), Content-Security-Policy (locks down where script can run from).
- Similar to SQLi except the query is written in the language of the DB, which could be PHP, Script, Java, etc.
- This can allow SQLi style attacks or even worse, allow code to run on the DB server directly.
- Occurs when the user has the ability to influence a redirect through the URL.
- Redirection can be used for phishing (redirect to an attack site that looks like the valid site) or for XSS (redirect to script code).
- Do not ever use untrusted input in a generated URL.
Major types of session issues
- Cookie containing session ID can be sniffed on the network.
- User fails to log out on a shared-computer and the session doesn’t expire.
- Session hijacking occurs when an attacker can steal or predict a session token.
- Session fixation can occur when attacker gains a session ID and then forces victim session into using same ID (e.g. session token in the url, in a hidden form field, fix ID in victim’s cookie via XSS). Attacker can now take over the session. Fix is to force new session ID on each login or include user/machine specific information in the cookie that can be validated as well (e.g. IP address). Session expiration can also help limit attack window. Expiration should be on the server, not the client.
- Cookie replay attacks can occur when important state for business logic is stored in the cookie. Even if user cannot decrypt, they can re-use old-state cookies to influence business logic. Don’t store this kind of state information in cookies.
- Expire sessions
- Unpredictable sessionIDs
- Protect session information (e.g. secure cookies). Not in URL!
- Strong passwords. 2FA if possible.
- Use strong password recovery mechanisms
- Strongly hash passwords in DB
- SQLi occurs when untrusted input is used in the construction of a SQL query.
- It can be used for unauthorized logins as well as for unauthorized access to DB information (e,g, using a Union).
- Parameterized queries.
- Whitelist validation can be added as backup but is only partial protection.
- Stored procedures provide only partial protection.
- SSRF exploits trust relationships, since the request comes from the vulnerable application/server itself.
- Allows an attacker to induce the server-side application to make HTTP requests to an arbitrary domain of the attacker’s choosing.
- Can be used to get unauthorized access to actions or data inside the vulnerable application or from other back-end systems.
- Blind SSRF is when the results of the SSRF are not returned to the user. Can be harder to exploit, but still dangerous.
- Ensure that the data provided is a valid domain name.
- Ensure that the domain name provided belongs to one of the domain names of the identified and trusted applications (the whitelisting comes to action here).
- Firewall to limit access to only applications/servers it should be able to make calls to (network segregation)
- URL parameters can be manipulated by the user in order to gain access to data or functionality they should not be allowed to access. This occurs when important business logic or security decisions are made, based on the data in a URL parameter.
- Make sure url params are not used to perform sensitive actions.
- E.g. do not authenticate a user based on sessionID or userID in a url parameter.
- Don’t return user records based on predictable url-param lookup.
- XXE occurs when XML input containing a reference to an external entity is processed by a weakly configured XML parser (allows doctype processing and resolution of external entities).
- Allows an attacker to interfere with an application’s processing of XML data.
- It often allows an attacker to view files on the application server filesystem, and to interact with any back-end or external systems that the application itself can access.
- May lead to the disclosure of confidential data, denial of service, server side request forgery, port scanning from the perspective of the machine where the parser is located, etc.
- Disallow the use of XML parsers unless doctype processing is disabled.
- Keep frameworks and libraries up to date.