Code injection, also called Remote Code Execution (RCE), occurs when an attacker exploits an input validation flaw in software to introduce and execute malicious code. Code is injected in the language of the targeted application and executed by the server-side interpreter. Any application that directly uses unvalidated input is vulnerable to code injection, and web applications are a prime target for attackers. This article shows how code injection vulnerabilities arise and how you can protect your web applications from injection.
Code injection, also called Remote Code Execution (RCE), occurs when an attacker exploits an input validation flaw in software to introduce and execute malicious code. Code is injected in the language of the targeted application and executed by the server-side interpreter for that language – PHP, Python, Java, Perl, Ruby, etc. Any application that directly evaluates unvalidated input is vulnerable to code injection, and web applications are a prime target for attackers. This article shows how code injection vulnerabilities arise and how you can protect your web applications from injection.
Note: Following OWASP terminology, this article uses the term “code injection” to refer specifically to attacks exploiting server-side dynamic evaluation (also called eval injection attacks). This is not to be confused with other types of code injection, such as cross-site scripting (XSS), which injects JavaScript code executed by the browser, or SQL injection, where SQL instructions for the database server are injected.
In general, an application is considered to have a code injection vulnerability when both of the following conditions occur:
In this case, user input is any data that is processed by the application and can be entered or manipulated by application users. This covers not just direct input, for example via form fields or file uploads, but also query string parameters, cookies and all other data sources that are beyond the developer’s control. The application usually expects specific types of input, and developers can neglect to validate and sanitize actual input data, especially if testing or debugging code makes it into the production application.
An application vulnerable to code injection takes this untrusted data and directly uses it in program code. This typically involves the use of eval()
or an equivalent function (depending on the language), but a direct concatenation of user-supplied strings also constitutes unsafe processing. An attacker can exploit such vulnerabilities by supplying malicious code in the application language. If successful, the attack can give full access to the server-side interpreter, allowing the attacker to execute arbitrary code within its process on the server. If the application has access to system calls, the attacker may be able to escalate this vulnerability to run system commands on the server, allowing command injection attacks.
Code injection attacks exploit vulnerabilities in applications to execute malicious commands. Here are some common types:
Cross-site scripting (XSS) involves injecting malicious scripts into websites or web applications, which then execute on users' devices. This allows attackers to impersonate users, bypass security controls, and steal session cookies, usernames, or passwords. XSS is commonly used against environments like JavaScript, Flash, and ActiveX due to their widespread browser integration.
LDAP injection exploits the Lightweight Directory Access Protocol (LDAP) by manipulating queries to execute malicious commands. Attackers use this method to search network resources like users, devices, and files through unvalidated LDAP statements.
SQL injection targets databases by exploiting Structured Query Language (SQL) vulnerabilities. Attackers inject malicious SQL commands to view, modify, or steal sensitive data. This method affects nearly all databases across programming languages.
Command injection involves executing arbitrary commands on the host operating system by exploiting vulnerabilities in applications. Attackers often target applications that improperly handle user inputs, such as forms or cookies, to inject commands into the server’s system shell.
Let's start with a quick example of vulnerable PHP code. The PHP eval()
function provides a quick and convenient way of executing string values as PHP code, especially in the initial phases of development or for debugging. However, when used with unknown inputs, it can leave your application vulnerable to code injection. Here’s a typical example of quick-and-dirty query string processing – just a simple echo command, like you might use for debugging parameters:
 <?php eval ("echo ".$_REQUEST["user_name"].";"); ?>
The PHP interpreter will attempt to evaluate whatever is passed in the user_name parameter. As the parameter name implies, the developer expects the query string to contain a valid user name, for example:
http://www.example.com/index.php?user_name=admin
However, an attacker might supply the following query string to exploit the vulnerable construct and inject PHP code into the application:
http://www.example.com/index.php?user_name=admin;phpinfo();
If successful, this injection will cause the PHP interpreter to echo admin, but then execute phpinfo()
, providing the attacker with information about the operating system, PHP version, and other configuration details.
Unless the system()
function is disabled in PHP interpreter settings, a successful code injection can use this function to execute operating system commands, in effect performing command injection (see note below). Working with the vulnerable code shown above, an attacker might supply the following URL to a Linux-based server:
http://www.example.com/index.php?user_name=admin;system('ls -l');
Again, this will echo admin and then execute code injected after the semicolon. In this example, system('ls -l')
runs the ls -l
command to list the contents of the PHP interpreter’s working directory, including permissions.
Note: Code injection is a separate concept from command injection (shell injection). An attacker exploiting a command injection vulnerability is limited to injecting commands of the underlying operating system, while a code injection vulnerability allows them to execute arbitrary code in the server-side interpreter for the web application’s language.
Regardless of language, you can avoid code injection vulnerabilities and improve web application security by following some basic security practices:
system()
function, you can disable that function in your php.ini file by specifying it in the disable_functions directive. Commonly disabled functions for PHP include: exec()
, passthru()
, shell_exec()
, system()
, proc_open()
, popen()
, curl_exec()
, curl_multi_exec()
, parse_ini_file()
, and show_source()
.