Gadget chains in Laravel
As we have seen in the previous article about wordpress gadgets, very simple gadget chains can be found in major projects. But sometimes finding popchain may be more difficult. This article…
Série PHP Gadget Chains 2/2
- Gadget chains in Wordpress
- Gadget chains in Laravel
As we have seen in the previous article, very simple gadget chains can be found in major projects. But sometimes finding popchain may be more difficult. This article presents another pretty interesting gadget chain we found in the Laravel project on version 10.34 that leads to remote command execution.
Finding a vulnerable method
Serializing is a process that generates a storage representation of an object state. Unserializing is the opposite process, generating an object from its serialized representation. If an object implements magic methods, PHP will call an implicit execution of these methods depending on the method specificity.
During our research in the source code of Laravel, we found a class, InvokableComponentVariable, that implements an __invoke magic method as shown below:

This __invoke method executes call_user_func on a class attribute callable that could be controlled during the unserializing process. However, the __invoke magic method is implicitly called when the object is handled as a function, and we did not find any way to trigger this method implicitly. We noticed that the __call magic method executes the __invoke and we tried to find a way to build a popchain around this portion of code.
Triggering __call from a __destruct
To be able to exploit this code, we need to find a magic method implicitly called during the unserializing process that allows us to trigger the __call method of our desired class. We targeted three candidates: __destruct, __wakeup and __unserialize (called by PHP > 7.4)
The __call magic method is implicitly executed when invoking an inaccessible instance method of an object. We found that the Sleep class allows us to do it:

This class implements a __destruct method that calls copy() on the object stored in the duration class attribute. Calling unserialize on a serialized instance of the Sleep class built with an instance of InvokableComponentVariable class as duration attribute will do the job.
In other words, leveraging this destruct method will make a call to InvokableComponentVariable->copy() which does not exist. Consequently, it will trigger the execution of the __call magic method required to reach our __invoke destination.
Thus, we are able to execute call_user_func on a single controlled parameter. For instance, it’s already possible to execute a phpinfo as follows:

This behavior is pretty interesting; we are able to call an arbitrary method, but it does not allow us to execute arbitrary commands on the system because we are not able to control the parameters of the function being called.
Luckily, call_user_func is a funny PHP function. It offers multiple ways to call it. For instance, it also accepts its parameter to be an Array. The first position requires an instance of a callable, and the second, the method we want to call on this later object:
But call\_user_func also accepts as callback the representation of the namespace and the class name of the targeted method:
This behavior allows us to call any callable method of loaded classes using the namespace representation NAMESPACE\Class::Method() or the Array representation [Callable, 'method']. However, the only restriction is that we need to find an object with an interesting method, but we can’t provide it any parameter.
From phpinfo to RCE
To be able to transform this popchain that allows us to call an arbitrary method without parameters to a popchain that executes arbitrary code during the unserializing process, we need to find a method doing vulnerable stuff on controlled input, such as class attributes or on php://input for example.
After a quick search, we found the Terminal class of Laravel\Prompts namespace that implements two interesting methods. The first one, exec, executes system commands using proc_open with the parameter command:

As we were just saying, we are not able to control the method parameter; however, the Terminal class also implements a restoreTty method that calls exec instance method using the instance attribute initialTtyMode without any sanitization process:

We are now able to build a popchain that triggers, during the unserializing process, a system call with a command injection. We just need to build the popchain, calling, with call_user_func, an instance of Terminal class with an initialTtyMode breaking the legitimate command and injecting a rogue system command such as ;mycommand;#. The final gadget chain is shown below:

Conclusion
This exploitation vector is now available in the phpggc tool as Laravel/RCE19 and was tested on Laravel version 10.34. It was a pretty fun pop chain to dig through, as it uses much less common primitives such as __call.
Keep reading
Gadget chains in Wordpress
Exploiting an unserialization vulnerability in WordPress never was a small issue. Unlike other PHP frameworks, and until very recently, WordPress was not known for hosting gadget chains.
Open Build Service, one year later: command execution through Mercurial argument injection
In March 2025 we published an analysis of a remote code execution vulnerability in Open Build Service (OBS), tracked as CVE-2024-22033. A little over a year later we went back to the same attack surface and found a second, distinct flaw of the same family. It has now been reported to the openSUSE security team and fixed…
HTTP Request Smuggling in Hiawatha - CVE-2026-51785
As part of our ongoing research into request smuggling, we identified an HTTP Request Smuggling vulnerability (CWE-444) in Hiawatha ≤ 12.1. Hiawatha is an open-source, security-focused web server for Unix-like systems, used to serve websites and host web applications.
