Prevent injection attacks
What is file inclusion?
A file inclusion allows the attacker to include arbitrary files into the web application, resulting in the exposure of sensitive files.
Security assessment
CVSS vector: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/CR:H/IR:H/AR:H/MAV:N /MAC:L/MPR:N/MUI:N/MS:U/MC:H/MI:H/MA:H
What is the file inclusion?
A local/remote file inclusion allows the attacker to include arbitrary files into the web application, resulting in the exposure of sensitive files. Sometimes, the attacker can execute malicious code on the web server and take over the machine entirely.
Types of file inclusion
Exploiting a file inclusion vulnerability is possible when an application allows user input to act as a command (also known as dynamic file inclusion). When this happens, an attacker may direct the application to build a path toward a file that contains malicious code and execute the file. Alternatively, it may allow attackers to access files on the server and steal sensitive data contained in them.
Programming languages under which file inclusion vulnerabilities frequently occur are PHP, JavaServer Pages (JSP), and Server Side Includes (SSI).
This vulnerability is part of the more general injection vulnerability in the OWASP Top 10 vulnerability list. An attack that uses this vulnerability can potentially lead to cross-site scripting (XSS), directory traversal, and remote code execution.
A file inclusion exploit arises from using the include
statement or a similar filesystem functionality, such as the required statement. Developers typically utilize this functionality for several reasons.
- When specifying files to be parsed by the interpreter: to open a particular file containing code, and so that the parser can interpret the code, you must specify its path.
- When printing to a page: to save time and avoid recoding, developers will sometimes reuse certain portions of code, such as headers. In addition, it allows them to specify a file from which contents should be copied and used in the file that contains the include statement.
- When including files that users will download: to make files available for download, instead of being opened in the web browser, a specific header is included in the request.
In any of the above cases, if user input is not handled correctly, it can open the door for attackers to include malicious code or gain access to sensitive data.
Attackers exploit two significant file types inclusion vulnerabilities: local file inclusion (LFI) and remote file inclusion (RFI). Here is how they work.
Validating user input
<?php
if(isset($_GET['page']) and $_GET['page'] == 'home') {
include('home.php');
}
elseif(isset($_GET['page']) and $_GET['page'] == 'news') {
include('news.php');
}
// some other pages
?>
The best way to avoid this vulnerability is to hardcode all files you need to include, as the example above suggests. If you need the inclusion of dynamic files, you could only allow required characters like a-zA-Z and disallow anything else like ./. Maybe an even better solution is to maintain an allowlist of files that are allowed to be included. Any other file that the user requests can be rejected.
If you try to implement your filters and pass the filtered user input directly to the various included functions, ensure that your filters can not be bypassed by using methods like string encoding.
How to prevent LFI and RFI?
You can approach mitigating LFI and preventing RFI exploits in many ways. Proper input validation and sanitization play a part in this, but it is a misconception that this is enough. Ideally, you would best implement the following measures to best prevent file inclusion attacks.
- Sanitize user-supplied inputs, including GET/POST and URL parameters, cookie values, and HTTP header values. Apply validation on the server side, not on the client side.
- Assign IDs to every file path and save them in a secure database to prevent users from viewing or altering the path.
- Secured files and file types on your allowlist, checked file paths against this list, and ignored everything else. Do not rely on your allowlist validation, as attackers can evade it.
- Use a database for files that can be compromised instead of storing them on the server.
- Restrict execution permissions for upload directories as well as upload file sizes.
- Improve server instructions such as sending download headers automatically instead of executing files in a specified directory.
- Avoid directory traversal by limiting the API to allow file inclusions only from a specific directory.
- Run tests to determine if your code is vulnerable to file inclusion exploits.
What are command injections?
A command injection vulnerability allows an attacker to execute arbitrary system commands, resulting in an entire takeover of the webserver. Learn here how you can prevent command injections.
Security assessment
CVSS vector: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H/CR:M/IR:M/AR:M/MAV:N/MAC :L/MPR:N/MUI:N/MS:U/MC:H/MI:H/MA:H
What is OS command injection?
A command injection vulnerability allows attackers to execute arbitrary system commands on the attacked host operating system (OS). Doing this can override the original command to gain access to a system, obtain sensitive data, or even execute an entire takeover of the application server or system.
Some typical examples of command injection attacks include the insertion of harmful files into the runtime environment of the vulnerable application server, shell command execution, and abuse of configuration file vulnerabilities.
The basics of command injection vulnerabilities
A command injection attack can occur with web applications that run OS commands to interact with the host and file systems. They execute system commands, start applications in a different language, or execute shell, Python, Perl, or PHP scripts. While this functionality is standard, it can be used for cyber attacks.
The main loophole through which command injection can be executed is when user-supplied input is not validated in applications. This input is used in the construction of commands that will be executed. Such cyber-attacks are possible when a web application passes the unverified user input (cookies, forms, HTTP headers, and the like) directly to OS functions likeexec()andsystem(). The input is always a string (string cmd) linked to a constant string of the application, which shapes the full command.
Command injection is also known as shell injection. The arbitrary commands that the attacker applies to the system shell of the web server running the application can compromise all relevant data. The command injection can also attack other systems in the infrastructure connected to and trusted by the initial one. This is how the attacker can use the privileges of the targeted application to gain wider control over the system.
Most OS command injections are blind security risks. The targeted application does not return the command output within the HTTP response. Still, blind injections are a security threat and can be used to compromise a system.
Example of a command injection
Malicious attackers can escape the ping command by adding a semicolon and executing arbitrary attacker-supplied operating system commands.
<?php
$ip = $_POST['ip'];
$cmd = system('ping '.$ip);
echo $cmd
?>
Example input: ; cat /etc/passwd
To ensure your web application is not vulnerable to command injections, you must validate all user input and only allow commands needed for the task. You can also clean up user input by removing special characters like ;
(semicolon), and other shell escapes like &
, &&
, |
, ||
, <*
.
There are proven ways to limit the situations in which command injections can be executed in your systems.
The differences between command injection and code injection
While they seem similar, code injection and command injection are different types of vulnerabilities.
Code injection entails an attacker inserting new malicious code into a vulnerable application, which executes. The attack is based on insufficient input validation of the malicious version of user data. Therefore, the code injection attack is limited to the functionalities of the application that is being targeted.
In contrast, a command injection is a case when an attacker modifies the default function of the application that executes system commands. Thus, no new code is being inserted. However, with a command injection, an attacker can target the server or systems of the application and other trusted infrastructure by using the compromised privileges for the application.
Prevent attacks
Here are the most valuable tips for applying:
-
Limit the use of shell command execution functions as much as possible.
-
Employ a trusted API for user input into your application, especially when running system commands such as
execFile()
. -
Always validate user input that will be feeding into a shell execution command, which entails having a sound input validation strategy.
-
Filter potentially problematic special characters by using an allowlist for user input or by targeting command-related terms and delimiters
-
Encode user input before using it in commands to avoid command-related characters being read as elements of the command or as a delimiter, as well as malformed inputs
-
Parameterize user input or limit it to certain data sections of the command to avoid the input being read as an element of the command
-
Ensure users are not able to get control over the name of an application by using
execFile()
securely.
A command injection vulnerability exists when user-supplied input is not validated correctly by the web application. The following snippet shows PHP code that is vulnerable to command injection.
Testing for command injection attacks
Application security is a top priority, so it is essential to routinely check the critical vulnerability risks for your systems.
To check for blind command injections, you can use various detection techniques, such as time delays, redirecting output and checking the file manually, or running an OOB network interaction with an external server.
You can use some standard parameters to test for operating system command injections:
cmd
exec
command
execute
ping
query
jump
code
reg
do
func
arg
option
load
process
step
read
function
req
feature
exe
module
payload
run
print
If you prefer to perform automated pentesting over manual testing for dangerous software weaknesses, you can use a dynamic application security testing tool to check your applications.
What is SQL injection?
An SQL injection allows an attacker to run arbitrary SQL code in the database, which may allow him to retrieve, change or delete data from the database.
Security assessment
CVSS vector: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
What is a SQL injection attack?
When a malicious user performs a SQL Injection (SQLi) attack, they typically intend to control the web application database server using malicious SQL statements. This allows them to bypass authentication controls required to access and retrieve the contents of the database. This usually is initiated by hackers scouting the application firewall for vulnerable user input points. Once identified, the attacker creates input content known as a malicious payload, executing unauthorized SQL injection commands at the back-end database.
Attackers commonly developed SQL injection commands to perform a wide variety of malicious acts, such as:
- Retrieving user credentials within the database.
- Selecting and outputting crucial system data.
- Appending or adding new data to a database.
- Deleting tables and records from the database.
- Using the back-end database server to access the operating system.
Prevention guide
Preventing SQLi attacks is a complex and rigorous process since prevention techniques vary according to the programming language used, the SQL database engine, and the SQLi subtype being addressed. This section explores the tools and best practices to prevent SQL Injection vulnerabilities.
Some strategic principles and practices to keep web applications safe from SQLi attacks include:
Training and awareness
Everyone involved in developing and managing the application should understand the risk and impacts of SQL injections. Training should also be extended to users to know why it is essential only to include valid inputs when prompted.
Filter user input
A database administrator should never trust user input. Internal and public user inputs should be filtered and validated before being exposed to the database server.
Use allowlist-based filters
Attackers constantly develop clever methods to circumvent blocklists. Allowlists help you prevent attacks using a list that only allows certain users to access the protected system. In addition, malicious payloads deployed by SQLi injections cannot execute when they do not exist in the whitelist.
Use updated web technologies
Software updates often include patches for discovered vulnerabilities. Hackers typically rely on these vulnerabilities to deploy malicious payloads. The latest patched versions of development environments and frameworks will meet compliance standards and keep the web application safe from exploits. Most software organizations try to stay ahead of hackers.
Regular scanning
Attackers inject malicious input through vulnerabilities they discover in the system code. Therefore, security teams should undertake a SQL injection scanner because using the right tools to find any possible SQLi vulnerabilities before attackers can take advantage of them.
Practical prevention tips
Filter user input
For an attacker to successfully execute an SQL injection, he needs to plant some code run by the web application database. Therefore, all user input should be validated first and limited to the required characters. E.g., you may ask a user to input a username, password, and e-mail address in a registration form. You can limit the allowed characters of these input fields to characters that do not interfere with the database. The following example filters out user input for the three values in PHP:
if (preg_match("/[^A-Za-z0-9]/", $username) ||
(preg_match("/[^A-Za-z0-9\!_-]/", $password) ||
(preg_match("/[^A-Za-z0-9_-@]/", $email)) {
echo "Invalid Characters!";
} else {
# Run Database Command
}
Database mappers
Most modern web frameworks provide some abstraction of database handling. E.g., Laravel provides Eloquent queries. Created objects are automatically converted and stored or retrieved from the database. In the example of the user registration form, one could make the user object in the following way:
$user = new User;
$user->username = $request->username;
$user->password = $request->password;
$user->email = $request->email;
$user->save();
The resulting SQL statement is automatically sanitized and will prevent SQL injections.
Sanitize user input / prepared statements
It may not always be possible to use a database mapper. In these cases, use prepared statements to create your SQL queries. These statements validate and sanitize the user-provided values and prevent SQL injections. E.g., in PHP, you can make a prepared account the following way:
$stmt = $mysqli->prepare("INSERT INTO users(username, password, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $username, $password, $email) # "sss" here states, that three strings are expected.
$username = $request->username;
$password = $request->password;
$email = $request->email;
$stmt->execute();