Come posso sfruttare un endpoint PHP che mi consente di istanziare una classe arbitraria?

6

PHP ti permette di istanziare classi da variabili o voci di array, come questo:

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

Stranamente, alcuni dei miei colleghi - su più progetti a cui ho lavorato in più aziende - hanno usato questa caratteristica linguistica con i nomi di classe forniti dall'input dell'utente come un modo per creare un'istanza di una delle varie sottoclassi possibili a seconda di un tipo specificato in la richiesta. Ho visto il codice lungo queste linee ...

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

Questo, oltre ad essere un mal di testa per la manutenzione, è ovviamente stupido e pericoloso; stai permettendo a un aggressore di istanziare una classe arbitraria. Ma come pericoloso? Quali attacchi ci sono che usano solo classi PHP integrate (e quindi non richiedono conoscenze dettagliate del codice dell'applicazione) che potrebbero essere usate contro endpoint come quello sopra?

Sto cercando l'attacco più brutto che chiunque possa inventare che posso usare per spaventare i futuri colleghi che usano questo orribile anti-modello.

    
posta Mark Amery 26.01.2016 - 15:41
fonte

1 risposta

2

Non penso che tu possa fare qualsiasi cosa con solo questo codice.

Ma ciò non significa che questo sia sicuro in alcun modo. Rinuncia al flusso di controllo della tua applicazione all'utente, che non è una buona idea.

Ad esempio, se dovessi chiamare close sull'oggetto appena creato, un utente malintenzionato potrebbe ottenere SSRF:

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

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

O se avessi una classe come questa, un utente malintenzionato potrebbe ottenere la fissazione della sessione:

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

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

Oppure potresti avere una classe come questa:

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

    // [...]

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

E diciamo che le classi che gli utenti dovrebbero creare hanno anche un metodo save (ad esempio per salvare l'oggetto nel database). Ora un utente malintenzionato dovrebbe eseguire il codice.

È facile immaginare molti più scenari come questo, dove un costruttore di una classe fa qualcosa di pericoloso, o un metodo pericoloso di una classe ha lo stesso nome di un metodo sicuro della classe che ti aspetti.

È probabile che il tuo attuale codice base consenta a un utente malintenzionato di fare almeno qualcosa .

Anche il fatto che il tuo codice sia segreto non è una buona idea. Il tuo codice dovrebbe essere sicuro, anche se il codice sorgente in qualche modo trapelato.

    
risposta data 26.01.2016 - 17:19
fonte

Leggi altre domande sui tag