The two files
It is important to understand their different roles of the two PHP files that you are using:
one.php is the vulnerable system, the one you are attacking.
two.php The second one is just a tool the attacker can use to generate the serialized object (i.e.
data). It isn't supposed to be present on the system that you are attacking, and you don't need it at all. You could just as well generate the
data string by hand.
So in a real example the two files wouldn't even be present on the same system. The first would run on the server that is being attacked, and the second would be executed localy at the attackers machine.
So why the same classname in both files? Because when
data is deserialized on the server, you want it to create an instance of the
utkarsh class. After all, that's the class that will write the file for you. For
one.php to create an instance of that object,
data needs to contain that object name. And an easy way to create a serialized object string containing that class name is to create a different class with that name and serialize it, just as you have done in
Note that when
unserialize it creates an instance of the
utkarsh it knows about in
one.php and not of the one in
The actual exploit
The exploit part of your process is making a request for
one.php with the serialized object in the
data parameter. So why does that result in a successful exploit? Let's go through, step by step, what is actually happening when
one.php is executed.
The first row that actually does something is this one:
$v1 = unserialize(@$_GET['data']);
data you provided, it will create an object named
$v1 of the class
utkarsh (as defined in
one.php) with the following properties:
$logfile = "test.php";
$logdata = '<?php system($_GET["cmd"])?>';
Then there's this:
$object = new utkarsh();
This creates another instance of the
utkarsh class. But it's not realy relevant for the exploit in any way as far as I can see - this should work equally well without those two lines.
Then we reach the end of the script. When PHP reaches the end of a script it runs a "shutdown sequence". That includes calling the
__destruct method on all objects. So for
$v1 it will run this little piece of code:
file_put_contents(__DIR__ . '/'. $this->logfile, $this->logdata)
Or, if we enter the variable values:
file_put_contents(__DIR__ . '/test.php', '<?php system($_GET["cmd"])?>')
There you have it. You are right that "you" didn't write the file - instead you succesfully tricked the PHP script to write the backdoor for you.
Why is the system vulnerable?
The whole reason that this vulnerability is possible is that you pass user data to
unserialize. That allows an attacker to create objects in states that they would never be in during "normal" execution of the program, allowing the program to have unexpected effects.