I due file
È importante comprendere i diversi ruoli dei due file PHP che stai utilizzando:
-
one.php è il sistema vulnerabile, quello che stai attaccando.
-
two.php Il secondo è solo uno strumento che l'utente malintenzionato può utilizzare per generare l'oggetto serializzato (cioè data ). Non dovrebbe essere presente sul sistema che stai attaccando, e non ne hai affatto bisogno. Potresti anche generare la stringa data a mano.
Quindi in un esempio reale i due file non sarebbero nemmeno presenti sullo stesso sistema. Il primo verrebbe eseguito sul server che viene attaccato e il secondo verrebbe eseguito localmente sulla macchina degli attaccanti.
Quindi perché lo stesso nome di classe in entrambi i file? Perché quando data è deserializzato sul server, vuoi che crei un'istanza della classe utkarsh . Dopotutto, questa è la classe che scriverà il file per te. Per one.php per creare un'istanza di quell'oggetto, data deve contenere il nome dell'oggetto. E un modo semplice per creare una stringa di oggetto serializzata contenente quel nome di classe è creare una classe diversa con quel nome e serializzarla, proprio come hai fatto in two.php .
Si noti che quando one.php esegue unserialize crea un'istanza di utkarsh che conosce in one.php e non di quella in two.php .
L'exploit attuale
La parte di exploit del tuo processo sta facendo una richiesta per one.php con l'oggetto serializzato nel parametro data . Quindi, perché questo si traduce in un exploit di successo? Esaminiamo, passo dopo passo, cosa sta effettivamente accadendo quando viene eseguito one.php .
-
La prima riga che fa effettivamente qualcosa è questa:
$v1 = unserialize(@$_GET['data']);
Dato il data che hai fornito, creerà un oggetto chiamato $v1 della classe utkarsh (come definito in one.php ) con le seguenti proprietà:
$logfile = "test.php";
$logdata = '<?php system($_GET["cmd"])?>';
-
Poi c'è questo:
$object = new utkarsh();
$object->check();
Questo crea un'altra istanza della classe utkarsh . Ma non è davvero rilevante per l'exploit in alcun modo, per quanto posso vedere - questo dovrebbe funzionare altrettanto bene senza quelle due righe.
-
Quindi raggiungiamo la fine della sceneggiatura. Quando PHP raggiunge la fine di uno script esegue una "sequenza di spegnimento". Ciò include la chiamata del metodo __destruct su tutti gli oggetti. Quindi per $v1 verrà eseguito questo piccolo pezzo di codice:
file_put_contents(__DIR__ . '/'. $this->logfile, $this->logdata)
Oppure, se inseriamo i valori delle variabili:
file_put_contents(__DIR__ . '/test.php', '<?php system($_GET["cmd"])?>')
Ce l'hai. Hai ragione che "tu" non hai scritto il file - invece hai ingannato con successo lo script PHP per scrivere la backdoor per te.
Perché il sistema è vulnerabile?
L'intera ragione per cui questa vulnerabilità è possibile è che passi i dati dell'utente a unserialize . Ciò consente a un utente malintenzionato di creare oggetti negli stati in cui non sarebbero mai presenti durante l'esecuzione "normale" del programma, consentendo al programma di avere effetti imprevisti.