¿Cómo puedo explotar un punto final de PHP que me permite crear una instancia de una clase arbitraria?

6

PHP le permite crear instancias de variables o entradas de matriz, como esto:

class Foo {}
$className = 'Foo';
new $className();
$someArray = ['class_name' => 'Foo'];
new $someArray['class_name']();

Desgraciadamente, algunos de mis compañeros de trabajo - en múltiples proyectos en los que he trabajado en múltiples compañías - han usado esta función de lenguaje con nombres de clase proporcionados por la entrada del usuario como una forma de crear una instancia de una de las varias subclases posibles, dependiendo de un tipo especificado en la solicitud. He visto código a lo largo de estas líneas ...

new $_GET['product_type']($_GET['product_id']);

Esto, además de ser un dolor de cabeza de mantenimiento, es obviamente estúpido y peligroso; estás dejando a un atacante crear una instancia de una clase arbitraria. Pero ¿cómo es peligroso? ¿Qué ataques existen que solo usan clases de PHP incorporadas (y, por lo tanto, no requieren un conocimiento detallado del código de la aplicación) que podrían usarse contra puntos finales como el anterior?

Estoy buscando el ataque más desagradable que alguien pueda hacer y que puedo usar para asustar a los futuros compañeros de trabajo que usen este horrible anti-patrón.

    
pregunta Mark Amery 26.01.2016 - 15:41
fuente

1 respuesta

2

No creo que puedas hacer nada solo con este código.

Pero eso no significa que esto sea seguro de ninguna manera. Usted cede el flujo de control de su aplicación al usuario, lo cual no es una buena idea.

Por ejemplo, si llamara a close en el objeto recién creado, un atacante ganaría SSRF:

$obj = new $_GET['x']($_GET['y']);
$obj->close();

// SSRF: 
http://localhost/shell.php?x=SoapClient&y=http://localhost/called

O si tuviera una clase como esta, un atacante obtendría la fijación de la sesión:

class Session {
   function __construct($sessionId) {
       session_id($sessionId);
   }
}

// session fixation:    
http://localhost/shell.php?x=Session&y=123

O puedes tener una clase como esta:

class File {
    function __construct($filename, $content) {
        $this->filename = $filename;
        $this->content = $content;
    }

    // [...]

    function save() {
        file_put_contents($this->filename, $this->content);
    }
}

Y digamos que las clases que los usuarios deben crear también tienen un método save (por ejemplo, para guardar el objeto en la base de datos). Ahora un atacante tendría ejecución de código.

Es fácil imaginar muchos más escenarios como este, donde un constructor de una clase hace algo peligroso o un método peligroso de una clase tiene el mismo nombre que un método seguro de la clase que esperas.

Es probable que su base de código actual le permita a un atacante hacer al menos algo .

Dependiendo de que su código sea secreto tampoco es una buena idea. Su código debe ser seguro, incluso si el código fuente se filtró de alguna manera.

    
respondido por el tim 26.01.2016 - 17:19
fuente

Lea otras preguntas en las etiquetas