You may have heard of OWASP Top 10 Vulnerabilities or the top 10 vulnerabilities that threaten web applications. OWASP also periodically selects a list of the top ten security vulnerabilities that threaten APIs, known as the OWASP . API. The current top ten API vulnerabilities are:
Join the channel Telegram of the AnonyViet 👉 Link 👈 |
- Broken Object Level Authorization
- Broken User Authentication
- Excessive Data Exposure
- Lack of Resources & Rate Limiting
- Broken Function Level Authorization
- Mass Assignment
- Security Misconfiguration
- Injection
- Improper Assets Management
- Insufficient Logging & Monitoring
These are the vulnerabilities that affect the API the most. So in this article, let’s talk about the 8th API vulnerability, Injection, a type of vulnerability that affects most API applications and systems.
Injection is the underlying problem of a large number of vulnerabilities, such as SQL injection, OS command injection, and XML injection. Together, Injection accounts for a large percentage of vulnerabilities found in real-world applications and APIs.
How injection works
In short, Injection occurs when an application cannot correctly distinguish between user data and untrusted code.
Untrusted user data can be HTTP request parameters, HTTP headers and cookies. They can also come from a database or stored file that the user can modify. If the application does not properly process untrusted user data before inserting it into a command or query, the program’s interpreter will mistake user input as part of a command or query. In this case, attackers can send malicious data as input, changing the original purpose of the command.
In an SQL injection attack, for example, the attacker injects data to manipulate SQL commands. And in a command injection attack, the attacker injects data that controls the logic of the operating system commands on the host server. Any program that combines user data with commands or programming code is vulnerable.
Injection vulnerabilities can also affect API systems because APIs are just another way that users input data into an application. Let’s see how security holes appear in the API.
Example #1: Retrieve blog posts
Assume that an API allows users to retrieve blog posts by sending a GET request like this:
GET /api/v1.1/posts?id=12358
This request will cause the API to return post 12358. The server will retrieve the corresponding blog post from the database using an SQL query, where post_id is the id passed in by the user via the URL.
SELECT * FROM posts WHERE post_id = 12358
Now, what if the user sends this request from the API endpoint?
GET /api/v1.1/posts?id=
12358; DROP TABLE users
SQL Server will interpret the id after the semicolon as a separate SQL command. So the SQL engine will first execute this command to retrieve the blog post as usual:
SELECT * FROM posts WHERE post_id = 12358;
It will then execute this command to delete the users table, causing the application to lose the data stored in that table.
DROP TABLE users
This is known as an SQL injection attack and can occur whenever user input is passed into SQL queries in an unsafe manner. Note that user input in an API is not only entered via URL parameters, but can also be via POST request, URL path parameters, etc. So it’s important that you protect it. those places.
Example #2: Read System Files
Let’s say the site allows users to read the files they’ve uploaded through the API endpoint:
GET /api/v1.1/files?id=1123581321
This request will cause the server to retrieve the user’s file via the system command:
cat /var/www/html/users/tmp/1123581321
In this case, the user can introduce new commands to the operating system by adding additional commands after the semicolon.
GET /api/v1.1/files?id=1123581321; rm -rf /var/www/html/users
This command will force the server to delete the directory located at /var/www/html/users
this is where the application stores user information.
rm -rf /var/www/html/users
Prevent injection vulnerabilities in API
These are simple examples of injection vulnerabilities. In fact, it’s important to remember that injection vulnerabilities aren’t always so obvious. And this operation can happen anytime this piece of data is being processed or used. Even if malicious data is not immediately used by the application, this data can move to somewhere in the program where it can do something bad, such as a malicious function. or an unprotected query. And this is where they cause damage to the application.
That’s why injections are so hard to prevent. Untrusted data can attack any application component. And for every piece of untrusted data an application receives, it needs to detect and neutralize attacks that target every part of the application. And the application may think that a piece of data is safe because it does not contain any special characters that are used for XSS by an attacker with SQL injection intent. It is not always easy to determine what data is safe and what is not, as safe and unsafe data look very different in different parts of the application.
Input validation
So, how to protect apps against these threats? The first thing you can do is validate untrusted data. This means that you need to implement a blocklist to reject any input that contains dangerous characters that could affect application components. Or you implement a list that only allows inputs with known good characters. For example, let’s say you’re implementing a subscription function. Since you know that data will be inserted into an SQL query, you reject any username input that is special characters in SQL, such as quotes. Or, you can implement a rule that only allows alphanumeric characters.
But sometimes block lists are difficult to implement because you don’t always know which characters will be important for application components.
And the whitelist can be too restrictive, and in some cases you may need to accept special characters like quotes in user input fields sometimes. For example, if a user named Conan O’Brien is registering, he must be allowed to use a single apostrophe in his name.
Parameterization
Another possible defense against injection is parameterization. Parameterization refers to compiling the code portion of the directive before inserting any user-supplied parameters.
This means that instead of concatenating user input into program commands and sending it to the server to be compiled, you define all the logic first, compile it, and then insert the user input. command just before execution. After user input is inserted in the last command, the command will not be parsed and recompiled. And anything not in the original statement will be treated as string data and not executable code. So the program logic part of the instruction will remain intact.
This allows the database to distinguish between the code and data portions of the command, regardless of what the user input looks like. This method is very effective in preventing some injection vulnerabilities, but cannot be used in every context in the code.
Special character encoding
You encode special characters in user input so that they are treated as data and not as special characters. By using special marks and syntax to mark special characters in user input, let the interpreter know what data should not be executed.
But this method also comes with its problems. You must use the correct encoding syntax for every parser or risk the encoded values ​​being misinterpreted by the parser. You can also forget some characters that an attacker can use to disable your encryption attempts. So the key to preventing security holes is to understand how parsers of different languages ​​work and which parsers run first in your processes.