← All cybersecurity posts

PHP Security Vulnerabilities: From File Uploads to Web Shells

PHP still runs a huge portion of the web, from WordPress and Laravel apps to long-lived custom platforms. PHP has matured significantly, but certain patterns remain a direct path from a web request to a shell on the server. Our research team has found and reported critical PHP vulnerabilities in open-source projects, including CVE-2026-33867, an RCE in AVideo.

Unsafe file uploads leading to web shells

The classic PHP compromise: an attacker uploads shell.php and the web server executes it.

Common causes:

  • Uploads stored in a web-accessible directory where PHP executes.
  • Extension checks bypassed with shell.php5, shell.phtml, shell.php.jpg with misconfigured handlers, or case tricks.
  • Trusting the Content-Type header.
  • Image validation that only checks magic bytes, allowing polyglot files that are valid images and valid PHP.

Prevent: store uploads outside the web root, generate random names, allowlist extensions, verify content, and disable PHP execution in upload directories at the server level.

Local and remote file inclusion

// Vulnerable
include($_GET['page'] . '.php');

Attackers use path traversal to include other files, or PHP stream wrappers such as php://filter to read source code. Combined with log poisoning or uploaded files, inclusion can become code execution. If allow_url_include is enabled, remote files can be included directly.

Prevent: never include files based on user input. Map input to an allowlist of templates. Keep allow_url_include off.

Insecure deserialisation

// Vulnerable
$prefs = unserialize($_COOKIE['prefs']);

PHP's unserialize() can instantiate objects and trigger magic methods like __wakeup and __destruct, enabling gadget chains in frameworks and libraries. Phar archives can also trigger deserialisation through file functions on older PHP versions.

Prevent: use json_decode() for untrusted data. If you must use unserialize(), pass ['allowed_classes' => false].

Dangerous functions

Review any use of these with user-influenced input:

FunctionRisk
eval(), assert() with stringsCode execution
system(), exec(), shell_exec(), passthru(), popen(), proc_open()Command injection
preg_replace() with the /e modifier on old PHPCode execution
include, requireFile inclusion
unserialize()Object injection
extract() on request dataVariable overwrite

Consider disabling unneeded functions with disable_functions in php.ini.

Type juggling

Loose comparison with == can produce surprising results, such as some strings comparing equal to 0 in older PHP versions, or "magic hash" strings comparing equal. This has led to authentication bypasses. Use === and hash_equals() for secrets.

SQL injection

Still common in legacy PHP. Use PDO prepared statements with bound parameters.

Configuration hardening

  • Run supported PHP versions; end-of-life versions receive no security fixes.
  • display_errors = Off in production.
  • expose_php = Off.
  • Remove phpinfo() files.
  • Use open_basedir to limit file access.

Free PHP2Shell scanner

We built a free scanner that checks PHP applications for upload and execution paths that could lead to a web shell. Try PHP2Shell, or start free for full testing.

Frequently asked questions

Is PHP insecure?

Modern PHP with a good framework and secure practices can be very secure. Risk comes mainly from legacy code, outdated versions and dangerous patterns.

Do frameworks like Laravel prevent these issues?

They provide safe defaults for queries, templating and CSRF, but developers can still introduce unsafe uploads, raw queries and deserialisation.

How do I find web shells on my server?

Look for recently modified PHP files in upload and writable directories, unusual file names, and code using eval, base64_decode and system together.

Find what attackers can see, before they do.

AI pentesting agents test your web app, API and cloud, and every finding comes with evidence and a fix. First report in about 10 minutes.

Stay ahead of attackers.

New vulnerabilities, breach write-ups and practical fixes. A few emails a month.