Los dos archivos
Es importante comprender sus diferentes roles de los dos archivos PHP que está utilizando:
-
one.php
es el sistema vulnerable, el que está atacando.
-
two.php
La segunda es solo una herramienta que el atacante puede usar para generar el objeto serializado (es decir, data
). No se supone que esté presente en el sistema que está atacando, y no lo necesita en absoluto. También podrías generar la cadena data
a mano.
Entonces, en un ejemplo real, los dos archivos ni siquiera estarían presentes en el mismo sistema. El primero se ejecutaría en el servidor que está siendo atacado, y el segundo se ejecutaría localmente en la máquina de los atacantes.
Entonces, ¿por qué el mismo nombre de clase en ambos archivos? Debido a que cuando data
se deserializa en el servidor, desea que cree una instancia de la clase utkarsh
. Después de todo, esa es la clase que escribirá el archivo por ti. Para que one.php
cree una instancia de ese objeto, data
necesita contener ese nombre de objeto. Y una manera fácil de crear una cadena de objeto serializada que contenga ese nombre de clase es crear una clase diferente con ese nombre y serializarla, tal como lo hizo en two.php
.
Tenga en cuenta que cuando one.php
ejecuta unserialize
crea una instancia del utkarsh
que conoce en one.php
y no del de two.php
.
El exploit actual
La parte explotada de su proceso es realizar una solicitud de one.php
con el objeto serializado en el parámetro data
. Entonces, ¿por qué eso resulta en una hazaña exitosa? Vamos a ver, paso a paso, lo que realmente sucede cuando se ejecuta one.php
.
-
La primera fila que realmente hace algo es esta:
$v1 = unserialize(@$_GET['data']);
Dado el data
que proporcionó, creará un objeto llamado $v1
de la clase utkarsh
(como se define en one.php
) con las siguientes propiedades:
$logfile = "test.php";
$logdata = '<?php system($_GET["cmd"])?>';
-
Luego está esto:
$object = new utkarsh();
$object->check();
Esto crea otra instancia de la clase utkarsh
. Pero no es realmente relevante para el exploit de ninguna manera, por lo que puedo ver, esto debería funcionar igual de bien sin esas dos líneas.
-
Luego llegamos al final del script. Cuando PHP llega al final de un script, ejecuta una "secuencia de apagado". Eso incluye llamar al método __destruct
en todos los objetos. Entonces para $v1
ejecutará este pequeño fragmento de código:
file_put_contents(__DIR__ . '/'. $this->logfile, $this->logdata)
O, si ingresamos los valores de las variables:
file_put_contents(__DIR__ . '/test.php', '<?php system($_GET["cmd"])?>')
Ahí lo tienes. Tiene razón en que "usted" no escribió el archivo; en su lugar, engañó al script PHP para que escribiera la puerta trasera para usted.
¿Por qué es vulnerable el sistema?
La razón principal por la que esta vulnerabilidad es posible es que pasa los datos de usuario a unserialize
. Eso permite que un atacante cree objetos en estados en los que nunca se encontraría durante la ejecución "normal" del programa, lo que permite que el programa tenga efectos inesperados.