Secure code - real world scenarios
In the previous edition, we saw some of the code-related OWASP vulnerabilities. Knowing these vulnerabilities is the first step towards developing secure coding practices. However, it still leaves the more significant step of understanding its real-world context and mitigation. In line with this, the post will be focused on examining example scenarios and providing possible mitigations for each of the 5 OWASP critical security risks related to code.
1. Broken Access Control
This occurs when a malicious actor bypasses access control and gains access to admin screens, databases, or business critical components.
Example Scenario 1:
An API that was exposed to handle a user's nickname change. The same API is also used for admins to change user roles. Since access control checks are missing, the attacker can change their role to admin and disguise it as part of a nickname change request. As a result, the attacker gains elevated privileges to that of an admin.
curl --request POST \
--url https://example.com/users \
--header 'Content-Type: application/json' \
--data '{"nickname": "Role changing attacker", "role": "admin"}'
Example Scenario 2:
There’s an API in an auction platform that returns the current client’s bid details when given a client ID. Such as “https://example-auction.com/bids?client-id=logged-in-client-id”
This API then checks if the user's ID is active in the database and returns the bid details as a response. But this API doesn't check whether that particular user belongs to or has permission to access that client. Now, the attacker only needs to log in with their own client account. Once logged in, the attacker can change the browser URL to point to a competing client's ID and expose their data with a url that looks like “https://example-auction.com/bids?client-id=competing-client-id”.
Though it’s a read-only request, sensitive data might still be exposed.
Possible Mitigations:
With the exception of resources that are meant to be public, deny by default
Introduce an access control mechanism with authentication and authorization and reuse it across the application
Implement auditing mechanism for destructive actions like DELETE requests and implement soft delete when possible
Delete support as well as privileged accounts that are no longer needed
Implement multi-factor authentication for all accounts as needed
Keep shorter expiry times for stateless auth tokens like JWT to reduce the attack window
For longer-lived tokens, it's imperative to implement token revoke functionality to invalidate them anytime they get compromised or are not needed anymore, and also before their expiration time
Invalidate their Stateful Session Identifier once a user logs out
2. Cryptographic Failures
This vulnerability refers to sensitive data being stored using outdated encryption algorithms or, even worse, without any encryption. It is important to note that having outdated encryption algorithms is as bad as not using any encryption algorithm at all, as attackers can easily crack them.
Example Scenario:
An application that stores user passwords in an unsalted hash (no element of randomness) or simple md5. Once a malicious actor gains access to this data, they can use a rainbow table (https://en.wikipedia.org/wiki/Rainbow_table) to prepare a matching hash value to gain access to a user's account.
Possible Mitigations:
Use strong encryption algorithms
Use strong protocols like TLS 1.2 or TLS 1.3
Encrypt data while in transit and at rest
Don't store sensitive data unless it's essential to avoid the risk of a data breach, and avoid logging them if you do
Use Strong adaptive and salted hashing functions when saving passwords. It's better to use a proper library that does this for you.
Disable connection downgrade from HTTPS to HTTP
3. Injection - SQL injection
When user forms or input payloads are used without proper validation, malicious actors can craft a valid-looking payload to make the application execute or return something it is not supposed to.
Example Scenario:
Consider an application that uses SQL queries to fetch data from a database. The application uses string concatenation to build a query. An attacker can use this to inject SQL commands and gain access to the database.
string query = "select * from users where username = '" + username + "' and password_hash = '" + hashPassword(password) + "'";
This innocent-looking query is used to fetch a user's details (like hashed password, user ID, etc.) from the user's table entry when they submit a valid username and password. If a match is found, then the user is returned. But attackers can bypass this query using another language feature, i.e., `Comment`. Let's see how this is done:
In SQL, "--" is used for code comments, so as part of the username, if an attacker sends username as `admin' -- ` and password as `dummy-value` then the final query will look like this:
select * from users where username = 'admin' -- ' and password_hash = <hash-of-dummy-value>'
Anything after the – symbol is considered as a comment and ignored by the SQL engine. So the query returns the admin user details (their user ID, etc, which will then be used as part of the request flow to create a session/auth token or, worse, their complete details as a response) without even checking the password. Voila! The malicious actor has the admin privilege now.
Possible Mitigations:
Use parameterized queries
Use an ORM (Object Relational Mapper) that creates parameterized queries for you
Use SAST tools as part of CI/CD pipeline
4. Vulnerable and Outdated Components - Applications using components/libraries with known vulnerabilities
Example Scenario:
An application that uses an outdated version of a library which has a known vulnerability. An attacker can use this to gain access to the application.
Possible Mitigations:
Use a library that doesn't have known vulnerabilities or look for alternatives
Choose libraries that have a large and active user base
Use an automated scanner to check for vulnerabilities as part of the CI/CD pipeline
5. Identification and Authentication Failures
This applies when an attacker can take the identity of another user by using their unique ID through brute force or exposed session tokens that are valid even after user logout.
Example Scenario 1:
Application Session timeouts are set for a very long duration. In this example, a user uses a public computer to access an application, and instead of selecting "logout," the user simply closes the browser tab and leaves. An attacker uses the same browser an hour later, and the user is still authenticated, giving them complete access.
Example Scenario 2:
Login API of an app returns whether the credentials are valid. There are no penalties implemented when wrong credentials are tried out (eg. accounts are not locked after x attempts). In addition to that, this API can be called any number of times.
Now an attacker can craft a simple script to figure out the password by trying out many combinations of passwords by brute force.
Possible Mitigations:
Implement password strength checks and enforce strong passwords as standard
Implement brute force protection by adding a delay or locking the account (if needed) after a certain number of failed attempts
Implement shorter session timeouts and invalidate session tokens on logout
Implement multi-factor authentication for admin accounts
Always use secure credentials (maybe using password managers to generate one) and avoid default values, particularly for admin users
Round Up
It is easier to lament what could've been done differently in hindsight. In fact, during a product’s life cycle, it is best practice to listen to user feedback and pivot as needed. However, you must always keep security in mind when making these changes and even consider rejecting user feedback if it opposes security best practices - a compromised account is not great UX! Additionally, we should start proactively looking at possible attack vectors and close them. Once we start including these checks as part of the application development process, it becomes second nature, and can result in building more secure products. In our next post, we will start looking at some of the tools that can aid in these processes.





