About the author
Will Barrett is a Software Engineer, Technical Lead, and Engineering Manager from the San Francisco Bay Area with over 14 years of experience. He’s a Superset PMC Member of The Apache Software Foundation. He’s held staff software engineer and senior engineer roles at Change.org, Entelo, Sqwiggle and Preset.
Will is the author of On Learning to Program, a blog for new Software Engineers entering the industry. Will is also a certified reviewer on PullRequest where he’s caught hundreds of bugs, security issues, and other critical issues for over 40 teams.
In Part 1, we covered the first four items from the OWASP #1 security vulnerability category for 2021, Broken Access Control - mostly endpoint-level vulnerabilities that created inconsistent access controls between different sections of code.
The second half of the OWASP definition contains a number of interesting types of the vulnerability:
- Elevation of privilege. Acting as a user without being logged in or acting as an admin when logged in as a user without admin-level credentials.
- Metadata manipulation, such as replaying or tampering with a JSON Web Token (JWT) access control token, or a cookie or hidden field manipulated to elevate privileges or abusing JWT invalidation.
- CORS misconfiguration allows API access from unauthorized/untrusted origins.
- Force browsing to authenticated pages as an unauthenticated user or to privileged pages as a standard user.
From the OWASP Website - numbers added to the list for easy reference in the rest of the article.
5. Escalation of Privilege
An escalation of privilege occurs when a user is able to access information that should be restricted to certain other users - when a standard user can access an admin-only page, or a logged out user can access information that should be restricted to known users. There are a number of ways that this can happen. Here are some common ones:
Insecure User Impersonation
Many websites allow for administrative users to impersonate other users for debugging purposes. Typically this is handled by adding metadata to the user that indicates the user they are impersonating. If this metadata is not handled securely, it can allow non-administrative users to impersonate other users, including administrative users. When I review code, I’m always on the lookout for situations where a standard user could access the impersonation system, and also for controls that would keep the impersonation system from allowing access to administrative accounts.
Shell Injection Vulnerabilities
At times it is necessary to shell out from web applications to the underlying system. These cases must be handled with care. If an part of a user’s input is incorporated into shell commands it can result in users gaining access to information on the underlying machine. As an example, I was once made aware of a vulnerability created by allowing users to create SQLite databases server-side and specifying the file path to the SQLite database. By allowing a file path, the system allowed a user to determine whether or not specific files existed on the host machine. In general, as a reviewer of the code, I look for any instance where user input is interpolated into shell commands.
Insecure Session Handling
Another common issue that would allow for an escalation of privilege attack is insecure session handling. A common pattern in web applications is to store the session information server-side, and the session’s ID in the web browser. This is a more secure pattern generally than storing everything on the client, but it’s possible to get it wrong.
A common failure is guessable session IDs: storing the session information in a database table and then using that database’s primary key as the session key would be one example. Another would be using an encoded time stamp. Either of these approaches would allow an attacker to easily guess different session IDs from their own, allowing them to interact with the system as a different user.
Another simple failure is a lack of server-side logout. If the logout removes the cookie from the browser but does not invalidate the session server-side, it creates an attack vector where a user’s session can be re-used indefinitely by an attacker who gets hold of it, be that by inspecting session traffic or pulling it off of a shared computer.
Insecure Password Reset
Similar to insecure session handling, an insecure password reset system will allow an attacker to gain access to a user account and its related information.
Common failures in this area include using a guessable token and not expiring tokens after use or after a set period of time when unused. Of course, common API access control failures can also expose reset tokens to an attacker, so the API tokens should be unavailable via the API.
6. Metadata Manipulation
Some forms of storage in web applications are secure, and some forms are not. The key to avoiding metadata manipulation is to use the secure forms. On the client, encrypted JWTs that are not user-editable are reasonably secure. Most other forms of storage - be that local storage, cookies, or local session storage - are insecure, they can be edited by the client.
When reviewing code, I look for situations where information that is used for access control is written to one of the insecure forms of storage. For instance, if the user’s ID is written to a plain-text cookie and then used to identify the user thereafter, this is insecure. The user could modify that cookie and gain access to a different user account.
The key to catching these problems at the code review stage as a pull request is gaining familiarity with the way that information is written to the browser in the languages under review. A clear understanding of what secure storage and insecure storage look like will make these issues clearer and more obvious to the engineer reviewing the code.
7. CORS Misconfiguration
CORS misconfiguration allows an attacker to exfiltrate information from the current site to one that they control.
This can leak all manner of secure information. The key to stopping this type of attack is to avoid wildcards in the
ACCESS_CONTROL_ALLOW_ORIGIN
header. This is relatively simple to look for when reviewing code - when looking at
alterations to that header, check to ensure that no wildcards (*
) are part of the configuration. It’s also worth
noting that by default most web applications are insecure, so for configuration of new systems it’s worth mentioning
to the developer that this needs to be configured properly out of the gate.
8. Force Browsing
Force browsing is a type of brute-force attack where the attacker attempts to request information from a large number of paths on the web application to find misconfigured access controls, available directories to spider, and other bits of information. Many applications are vulnerable to this type of attack because many programmers and other technical users believe in the idea of “security via obscurity” - if something is not easy to find, it is reasoned that it will not be found. In a force browsing attack, the attacker hits a large number of URLs either manually, in the case of easily-guessed identifiers, or with an automated tool following a database of common patterns.
The main way that I catch these security issues at the code review stage is I look for items where security via obscurity seems to be the approach - telltale signs are hard-coded long URLs and other similar efforts to hide an endpoint rather than implement proper access controls.
The second main protection from brute-force style attacks is ensuring that there is rate limiting in place on particularly sensitive endpoints - particularly login and password reset. Making it hard to perform dictionary attacks against sensitive endpoints is a helpful approach for mitigating the severity of this type of attack. When looking at login and password reset systems in code review, I generally check to make sure some form of rate limiting has been put in place by the developer.
The third item to look for related to this is any system that might allow access to the underlying operating system.
Any instance of the use of the os
package, for instance, in Python could potentially open up the program to a
dictionary attack via force browsing.
Conclusion
There are many ways that access control can be misconfigured, leading to security vulnerabilities in a web application. In my experience, code review is one of the most helpful, if not the most helpful, tool for discovering these vulnerabilities and remediating them before they reach production. One of the reasons Broken Access Control jumped to #1 on the OWASP Top 10 is because code-level security issues that cause these vulnerabilities are not always obvious and hard to catch with automated tools.
While no single approach will lead to perfect security, having experienced engineers review code does greatly reduce the number of security problems introduced into web applications. The telltale signs of these security problems are obvious to a trained eye.
Find this useful? Be sure to check out these additional articles by Will Barrett:
- Tips for Migrating to a New Computer for Programmers
- The Top 5 Most Common Security Issues I Discover When Reviewing Code
- Reviewing One’s Own Code
- Handling Code Reviews with Empathy
- What We Can Learn About Code Review From the Apache Superset Project
- What We Can Learn About Code Review From the Apache Spark Project
More from PullRequest on catching security issues in pull request code review: